/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

More work on supporting roundtripping push.

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 GitDirConfig(object):
 
84
 
 
85
    def get_default_stack_on(self):
 
86
        return None
 
87
 
 
88
    def set_default_stack_on(self, value):
 
89
        raise bzr_errors.BzrError("Cannot set configuration")
 
90
 
 
91
 
 
92
class GitDir(ControlDir):
73
93
    """An adapter to the '.git' dir used by git."""
74
94
 
75
95
    def is_supported(self):
76
96
        return True
77
97
 
 
98
    def can_convert_format(self):
 
99
        return False
 
100
 
 
101
    def break_lock(self):
 
102
        pass
 
103
 
78
104
    def cloning_metadir(self, stacked=False):
79
 
        return get_rich_root_format(stacked)
 
105
        return format_registry.make_bzrdir("default")
80
106
 
81
107
    def _branch_name_to_ref(self, name):
82
 
        from bzrlib.plugins.git.branch import branch_name_to_ref
83
 
        return branch_name_to_ref(name)
 
108
        raise NotImplementedError(self._branch_name_to_ref)
84
109
 
85
110
    if bzrlib_version >= (2, 2):
86
 
        def open_branch(self, name=None, ignore_fallbacks=None,
87
 
            unsupported=False):
 
111
        def open_branch(self, name=None, unsupported=False, 
 
112
            ignore_fallbacks=None):
88
113
            return self._open_branch(name=name,
89
114
                ignore_fallbacks=ignore_fallbacks, unsupported=unsupported)
90
115
    else:
92
117
            return self._open_branch(name=None,
93
118
                ignore_fallbacks=ignore_fallbacks, unsupported=unsupported)
94
119
 
 
120
    def get_config(self):
 
121
        return GitDirConfig()
 
122
 
95
123
 
96
124
class LocalGitDir(GitDir):
97
125
    """An adapter to the '.git' dir used by git."""
102
130
 
103
131
    _gitrepository_class = property(_get_gitrepository_class)
104
132
 
 
133
    @property
 
134
    def user_transport(self):
 
135
        return self.root_transport
 
136
 
 
137
    @property
 
138
    def control_transport(self):
 
139
        return self.transport
 
140
 
105
141
    def __init__(self, transport, lockfiles, gitrepo, format):
106
142
        self._format = format
107
143
        self.root_transport = transport
 
144
        self._mode_check_done = False
108
145
        self._git = gitrepo
109
146
        if gitrepo.bare:
110
147
            self.transport = transport
113
150
        self._lockfiles = lockfiles
114
151
        self._mode_check_done = None
115
152
 
 
153
    def _branch_name_to_ref(self, name):
 
154
        from bzrlib.plugins.git.refs import branch_name_to_ref
 
155
        ref = branch_name_to_ref(name, None)
 
156
        if ref == "HEAD":
 
157
            from dulwich.repo import SYMREF
 
158
            refcontents = self._git.refs.read_ref(ref)
 
159
            if refcontents.startswith(SYMREF):
 
160
                ref = refcontents[len(SYMREF):]
 
161
        return ref
 
162
 
116
163
    def is_control_filename(self, filename):
117
164
        return filename == '.git' or filename.startswith('.git/')
118
165
 
119
 
    def get_branch_transport(self, branch_format):
 
166
    def get_branch_transport(self, branch_format, name=None):
120
167
        if branch_format is None:
121
168
            return self.transport
122
 
        if isinstance(branch_format, LocalGitBzrDirFormat):
 
169
        if isinstance(branch_format, LocalGitControlDirFormat):
123
170
            return self.transport
124
171
        raise bzr_errors.IncompatibleFormat(branch_format, self._format)
125
172
 
126
 
    get_repository_transport = get_branch_transport
127
 
    get_workingtree_transport = get_branch_transport
 
173
    def get_repository_transport(self, format):
 
174
        if format is None:
 
175
            return self.transport
 
176
        if isinstance(format, LocalGitControlDirFormat):
 
177
            return self.transport
 
178
        raise bzr_errors.IncompatibleFormat(format, self._format)
 
179
 
 
180
    def get_workingtree_transport(self, format):
 
181
        if format is None:
 
182
            return self.transport
 
183
        if isinstance(format, LocalGitControlDirFormat):
 
184
            return self.transport
 
185
        raise bzr_errors.IncompatibleFormat(format, self._format)
128
186
 
129
187
    def _open_branch(self, name=None, ignore_fallbacks=None, unsupported=False):
130
188
        """'create' a branch for this dir."""
134
192
            self._lockfiles)
135
193
 
136
194
    def destroy_branch(self, name=None):
137
 
        del self._git.refs[self._branch_name_to_ref(name)]
 
195
        refname = self._branch_name_to_ref(name)
 
196
        if not refname in self._git.refs:
 
197
            raise bzr_errors.NotBranchError(self.root_transport.base,
 
198
                    bzrdir=self)
 
199
        del self._git.refs[refname]
 
200
 
 
201
    def destroy_repository(self):
 
202
        raise bzr_errors.UnsupportedOperation(self.destroy_repository, self)
 
203
 
 
204
    def destroy_workingtree(self):
 
205
        raise bzr_errors.UnsupportedOperation(self.destroy_workingtree, self)
 
206
 
 
207
    def needs_format_conversion(self, format=None):
 
208
        return not isinstance(self._format, format.__class__)
138
209
 
139
210
    def list_branches(self):
140
211
        ret = []
141
212
        for name in self._git.get_refs():
142
 
            if name.startswith("refs/heads/") or name == "HEAD":
 
213
            if name.startswith("refs/heads/"):
143
214
                ret.append(self.open_branch(name=name))
144
215
        return ret
145
216
 
157
228
                pass
158
229
            else:
159
230
                from bzrlib.plugins.git.workingtree import GitWorkingTree
160
 
                return GitWorkingTree(self, repo, self.open_branch(), index)
 
231
                try:
 
232
                    branch = self.open_branch()
 
233
                except bzr_errors.NotBranchError:
 
234
                    pass
 
235
                else:
 
236
                    return GitWorkingTree(self, repo, branch, index)
161
237
        loc = urlutils.unescape_for_display(self.root_transport.base, 'ascii')
162
238
        raise bzr_errors.NoWorkingTree(loc)
163
239
 
166
242
 
167
243
    def create_branch(self, name=None):
168
244
        refname = self._branch_name_to_ref(name)
169
 
        self._git.refs[refname] = "0" * 40
 
245
        from dulwich.protocol import ZERO_SHA
 
246
        self._git.refs[refname or "HEAD"] = ZERO_SHA
170
247
        return self.open_branch(name)
171
248
 
172
249
    def backup_bzrdir(self):
190
267
        finally:
191
268
            f.close()
192
269
        return self.open_workingtree()
 
270
 
 
271
    def find_repository(self):
 
272
        """Find the repository that should be used.
 
273
 
 
274
        This does not require a branch as we use it to find the repo for
 
275
        new branches as well as to hook existing branches up to their
 
276
        repository.
 
277
        """
 
278
        return self.open_repository()
 
279
 
 
280
    def _find_creation_modes(self):
 
281
        """Determine the appropriate modes for files and directories.
 
282
 
 
283
        They're always set to be consistent with the base directory,
 
284
        assuming that this transport allows setting modes.
 
285
        """
 
286
        # TODO: Do we need or want an option (maybe a config setting) to turn
 
287
        # this off or override it for particular locations? -- mbp 20080512
 
288
        if self._mode_check_done:
 
289
            return
 
290
        self._mode_check_done = True
 
291
        try:
 
292
            st = self.transport.stat('.')
 
293
        except TransportNotPossible:
 
294
            self._dir_mode = None
 
295
            self._file_mode = None
 
296
        else:
 
297
            # Check the directory mode, but also make sure the created
 
298
            # directories and files are read-write for this user. This is
 
299
            # mostly a workaround for filesystems which lie about being able to
 
300
            # write to a directory (cygwin & win32)
 
301
            if (st.st_mode & 07777 == 00000):
 
302
                # FTP allows stat but does not return dir/file modes
 
303
                self._dir_mode = None
 
304
                self._file_mode = None
 
305
            else:
 
306
                self._dir_mode = (st.st_mode & 07777) | 00700
 
307
                # Remove the sticky and execute bits for files
 
308
                self._file_mode = self._dir_mode & ~07111
 
309
 
 
310
    def _get_file_mode(self):
 
311
        """Return Unix mode for newly created files, or None.
 
312
        """
 
313
        if not self._mode_check_done:
 
314
            self._find_creation_modes()
 
315
        return self._file_mode
 
316
 
 
317
    def _get_dir_mode(self):
 
318
        """Return Unix mode for newly created directories, or None.
 
319
        """
 
320
        if not self._mode_check_done:
 
321
            self._find_creation_modes()
 
322
        return self._dir_mode
 
323
 
 
324