/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to dir.py

Handle empty metadata.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2007 Canonical Ltd
 
2
# Copyright (C) 2010 Jelmer Vernooij
2
3
#
3
4
# This program is free software; you can redistribute it and/or modify
4
5
# it under the terms of the GNU General Public License as published by
14
15
# along with this program; if not, write to the Free Software
15
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
 
17
 
"""An adapter between a Git control dir and a Bazaar BzrDir."""
 
18
"""An adapter between a Git control dir and a Bazaar ControlDir."""
18
19
 
19
20
from bzrlib import (
20
 
    bzrdir,
21
21
    errors as bzr_errors,
22
22
    lockable_files,
23
23
    urlutils,
27
27
LockWarner = getattr(lockable_files, "_LockWarner", None)
28
28
 
29
29
from bzrlib.plugins.git import (
30
 
    LocalGitBzrDirFormat,
31
 
    get_rich_root_format,
 
30
    LocalGitControlDirFormat,
32
31
    )
 
32
try:
 
33
    from bzrlib.controldir import (
 
34
        ControlDir,
 
35
        format_registry,
 
36
        )
 
37
except ImportError:
 
38
    # bzr < 2.3
 
39
    from bzrlib.bzrdir import (
 
40
        BzrDir,
 
41
        format_registry,
 
42
        )
 
43
    ControlDir = BzrDir
33
44
 
34
45
 
35
46
class GitLock(object):
69
80
            self._lock_warner = LockWarner(repr(self))
70
81
 
71
82
 
72
 
class GitDir(bzrdir.BzrDir):
 
83
class GitDir(ControlDir):
73
84
    """An adapter to the '.git' dir used by git."""
74
85
 
75
86
    def is_supported(self):
76
87
        return True
77
88
 
 
89
    def can_convert_format(self):
 
90
        return False
 
91
 
78
92
    def cloning_metadir(self, stacked=False):
79
 
        return get_rich_root_format(stacked)
 
93
        return format_registry.make_bzrdir("default")
80
94
 
81
95
    def _branch_name_to_ref(self, name):
82
96
        raise NotImplementedError(self._branch_name_to_ref)
83
97
 
84
98
    if bzrlib_version >= (2, 2):
85
 
        def open_branch(self, name=None, ignore_fallbacks=None,
86
 
            unsupported=False):
 
99
        def open_branch(self, name=None, unsupported=False, 
 
100
            ignore_fallbacks=None):
87
101
            return self._open_branch(name=name,
88
102
                ignore_fallbacks=ignore_fallbacks, unsupported=unsupported)
89
103
    else:
101
115
 
102
116
    _gitrepository_class = property(_get_gitrepository_class)
103
117
 
 
118
    @property
 
119
    def user_transport(self):
 
120
        return self.root_transport
 
121
 
 
122
    @property
 
123
    def control_transport(self):
 
124
        return self.transport
 
125
 
104
126
    def __init__(self, transport, lockfiles, gitrepo, format):
105
127
        self._format = format
106
128
        self.root_transport = transport
 
129
        self._mode_check_done = False
107
130
        self._git = gitrepo
108
131
        if gitrepo.bare:
109
132
            self.transport = transport
113
136
        self._mode_check_done = None
114
137
 
115
138
    def _branch_name_to_ref(self, name):
116
 
        from bzrlib.plugins.git.branch import branch_name_to_ref
117
 
        if name in (None, "HEAD"):
 
139
        from bzrlib.plugins.git.refs import branch_name_to_ref
 
140
        ref = branch_name_to_ref(name, None)
 
141
        if ref == "HEAD":
118
142
            from dulwich.repo import SYMREF
119
 
            refcontents = self._git.refs.read_ref("HEAD")
 
143
            refcontents = self._git.refs.read_ref(ref)
120
144
            if refcontents.startswith(SYMREF):
121
 
                name = refcontents[len(SYMREF):]
122
 
            else:
123
 
                name = "HEAD"
124
 
        return branch_name_to_ref(name, "HEAD")
 
145
                ref = refcontents[len(SYMREF):]
 
146
        return ref
125
147
 
126
148
    def is_control_filename(self, filename):
127
149
        return filename == '.git' or filename.startswith('.git/')
128
150
 
129
 
    def get_branch_transport(self, branch_format):
 
151
    def get_branch_transport(self, branch_format, name=None):
130
152
        if branch_format is None:
131
153
            return self.transport
132
 
        if isinstance(branch_format, LocalGitBzrDirFormat):
 
154
        if isinstance(branch_format, LocalGitControlDirFormat):
133
155
            return self.transport
134
156
        raise bzr_errors.IncompatibleFormat(branch_format, self._format)
135
157
 
136
 
    get_repository_transport = get_branch_transport
137
 
    get_workingtree_transport = get_branch_transport
 
158
    def get_repository_transport(self, format):
 
159
        if format is None:
 
160
            return self.transport
 
161
        if isinstance(format, LocalGitControlDirFormat):
 
162
            return self.transport
 
163
        raise bzr_errors.IncompatibleFormat(format, self._format)
 
164
 
 
165
    def get_workingtree_transport(self, format):
 
166
        if format is None:
 
167
            return self.transport
 
168
        if isinstance(format, LocalGitControlDirFormat):
 
169
            return self.transport
 
170
        raise bzr_errors.IncompatibleFormat(format, self._format)
138
171
 
139
172
    def _open_branch(self, name=None, ignore_fallbacks=None, unsupported=False):
140
173
        """'create' a branch for this dir."""
144
177
            self._lockfiles)
145
178
 
146
179
    def destroy_branch(self, name=None):
147
 
        del self._git.refs[self._branch_name_to_ref(name)]
 
180
        refname = self._branch_name_to_ref(name)
 
181
        if not refname in self._git.refs:
 
182
            raise bzr_errors.NotBranchError(self.root_transport.base,
 
183
                    bzrdir=self)
 
184
        del self._git.refs[refname]
 
185
 
 
186
    def destroy_repository(self):
 
187
        raise bzr_errors.UnsupportedOperation(self.destroy_repository, self)
 
188
 
 
189
    def destroy_workingtree(self):
 
190
        raise bzr_errors.UnsupportedOperation(self.destroy_workingtree, self)
 
191
 
 
192
    def needs_format_conversion(self, format=None):
 
193
        return not isinstance(self._format, format.__class__)
148
194
 
149
195
    def list_branches(self):
150
196
        ret = []
167
213
                pass
168
214
            else:
169
215
                from bzrlib.plugins.git.workingtree import GitWorkingTree
170
 
                return GitWorkingTree(self, repo, self.open_branch(), index)
 
216
                try:
 
217
                    branch = self.open_branch()
 
218
                except bzr_errors.NotBranchError:
 
219
                    pass
 
220
                else:
 
221
                    return GitWorkingTree(self, repo, branch, index)
171
222
        loc = urlutils.unescape_for_display(self.root_transport.base, 'ascii')
172
223
        raise bzr_errors.NoWorkingTree(loc)
173
224
 
176
227
 
177
228
    def create_branch(self, name=None):
178
229
        refname = self._branch_name_to_ref(name)
179
 
        self._git.refs[refname] = "0" * 40
 
230
        from dulwich.protocol import ZERO_SHA
 
231
        self._git.refs[refname or "HEAD"] = ZERO_SHA
180
232
        return self.open_branch(name)
181
233
 
182
234
    def backup_bzrdir(self):
200
252
        finally:
201
253
            f.close()
202
254
        return self.open_workingtree()
 
255
 
 
256
    def find_repository(self):
 
257
        """Find the repository that should be used.
 
258
 
 
259
        This does not require a branch as we use it to find the repo for
 
260
        new branches as well as to hook existing branches up to their
 
261
        repository.
 
262
        """
 
263
        return self.open_repository()
 
264
 
 
265
    def _find_creation_modes(self):
 
266
        """Determine the appropriate modes for files and directories.
 
267
 
 
268
        They're always set to be consistent with the base directory,
 
269
        assuming that this transport allows setting modes.
 
270
        """
 
271
        # TODO: Do we need or want an option (maybe a config setting) to turn
 
272
        # this off or override it for particular locations? -- mbp 20080512
 
273
        if self._mode_check_done:
 
274
            return
 
275
        self._mode_check_done = True
 
276
        try:
 
277
            st = self.transport.stat('.')
 
278
        except TransportNotPossible:
 
279
            self._dir_mode = None
 
280
            self._file_mode = None
 
281
        else:
 
282
            # Check the directory mode, but also make sure the created
 
283
            # directories and files are read-write for this user. This is
 
284
            # mostly a workaround for filesystems which lie about being able to
 
285
            # write to a directory (cygwin & win32)
 
286
            if (st.st_mode & 07777 == 00000):
 
287
                # FTP allows stat but does not return dir/file modes
 
288
                self._dir_mode = None
 
289
                self._file_mode = None
 
290
            else:
 
291
                self._dir_mode = (st.st_mode & 07777) | 00700
 
292
                # Remove the sticky and execute bits for files
 
293
                self._file_mode = self._dir_mode & ~07111
 
294
 
 
295
    def _get_file_mode(self):
 
296
        """Return Unix mode for newly created files, or None.
 
297
        """
 
298
        if not self._mode_check_done:
 
299
            self._find_creation_modes()
 
300
        return self._file_mode
 
301
 
 
302
    def _get_dir_mode(self):
 
303
        """Return Unix mode for newly created directories, or None.
 
304
        """
 
305
        if not self._mode_check_done:
 
306
            self._find_creation_modes()
 
307
        return self._dir_mode
 
308
 
 
309