/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

  • Committer: John Carr
  • Date: 2009-01-13 20:26:54 UTC
  • mto: (0.217.53 git-serve)
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: john.carr@unrouted.co.uk-20090113202654-9hsels0a9r35o7u0
Rename upload-pack and receive-pack so they don't clash with the Git versions

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
3
2
#
4
3
# This program is free software; you can redistribute it and/or modify
5
4
# it under the terms of the GNU General Public License as published by
15
14
# along with this program; if not, write to the Free Software
16
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
16
 
18
 
"""An adapter between a Git control dir and a Bazaar ControlDir."""
19
 
 
 
17
"""An adapter between a Git control dir and a Bazaar BzrDir"""
 
18
 
 
19
import os
 
20
 
 
21
import bzrlib
 
22
from bzrlib.lazy_import import lazy_import
20
23
from bzrlib import (
21
 
    errors as bzr_errors,
 
24
    bzrdir,
22
25
    lockable_files,
23
26
    urlutils,
24
 
    version_info as bzrlib_version,
25
27
    )
26
28
 
27
 
LockWarner = getattr(lockable_files, "_LockWarner", None)
28
 
 
 
29
lazy_import(globals(), """
 
30
from bzrlib.lockable_files import TransportLock
29
31
from bzrlib.plugins.git import (
30
 
    BareLocalGitControlDirFormat,
31
 
    LocalGitControlDirFormat,
 
32
    errors,
 
33
    branch,
 
34
    repository,
 
35
    workingtree,
32
36
    )
33
 
try:
34
 
    from bzrlib.controldir import (
35
 
        ControlDir,
36
 
        format_registry,
37
 
        )
38
 
except ImportError:
39
 
    # bzr < 2.3
40
 
    from bzrlib.bzrdir import (
41
 
        BzrDir,
42
 
        format_registry,
43
 
        )
44
 
    ControlDir = BzrDir
 
37
""")
 
38
 
45
39
 
46
40
 
47
41
class GitLock(object):
62
56
    def validate_token(self, token):
63
57
        pass
64
58
 
65
 
    def break_lock(self):
66
 
        pass
67
 
 
68
59
 
69
60
class GitLockableFiles(lockable_files.LockableFiles):
70
61
    """Git specific lockable files abstraction."""
73
64
        self._lock = lock
74
65
        self._transaction = None
75
66
        self._lock_mode = None
 
67
        self._lock_count = 0
76
68
        self._transport = transport
77
 
        if LockWarner is None:
78
 
            # Bzr 1.13
79
 
            self._lock_count = 0
80
 
        else:
81
 
            self._lock_warner = LockWarner(repr(self))
82
 
 
83
 
 
84
 
class GitDirConfig(object):
85
 
 
86
 
    def get_default_stack_on(self):
87
 
        return None
88
 
 
89
 
    def set_default_stack_on(self, value):
90
 
        raise bzr_errors.BzrError("Cannot set configuration")
91
 
 
92
 
 
93
 
class GitDir(ControlDir):
 
69
 
 
70
 
 
71
class GitDir(bzrdir.BzrDir):
94
72
    """An adapter to the '.git' dir used by git."""
95
73
 
96
74
    def is_supported(self):
97
75
        return True
98
76
 
99
 
    def can_convert_format(self):
100
 
        return False
101
 
 
102
 
    def break_lock(self):
103
 
        pass
104
 
 
105
77
    def cloning_metadir(self, stacked=False):
106
 
        return format_registry.make_bzrdir("default")
107
 
 
108
 
    def _branch_name_to_ref(self, name):
109
 
        raise NotImplementedError(self._branch_name_to_ref)
110
 
 
111
 
    if bzrlib_version >= (2, 2):
112
 
        def open_branch(self, name=None, unsupported=False, 
113
 
            ignore_fallbacks=None):
114
 
            return self._open_branch(name=name,
115
 
                ignore_fallbacks=ignore_fallbacks, unsupported=unsupported)
116
 
    else:
117
 
        def open_branch(self, ignore_fallbacks=None, unsupported=False):
118
 
            return self._open_branch(name=None,
119
 
                ignore_fallbacks=ignore_fallbacks, unsupported=unsupported)
120
 
 
121
 
    def get_config(self):
122
 
        return GitDirConfig()
 
78
        return bzrlib.bzrdir.format_registry.make_bzrdir("1.9-rich-root")
123
79
 
124
80
 
125
81
class LocalGitDir(GitDir):
126
82
    """An adapter to the '.git' dir used by git."""
127
83
 
128
 
    def _get_gitrepository_class(self):
129
 
        from bzrlib.plugins.git.repository import LocalGitRepository
130
 
        return LocalGitRepository
131
 
 
132
 
    _gitrepository_class = property(_get_gitrepository_class)
133
 
 
134
 
    @property
135
 
    def user_transport(self):
136
 
        return self.root_transport
137
 
 
138
 
    @property
139
 
    def control_transport(self):
140
 
        return self.transport
 
84
    _gitrepository_class = repository.LocalGitRepository
141
85
 
142
86
    def __init__(self, transport, lockfiles, gitrepo, format):
143
87
        self._format = format
144
88
        self.root_transport = transport
145
 
        self._mode_check_done = False
146
89
        self._git = gitrepo
147
90
        if gitrepo.bare:
148
91
            self.transport = transport
149
92
        else:
150
93
            self.transport = transport.clone('.git')
151
94
        self._lockfiles = lockfiles
152
 
        self._mode_check_done = None
153
 
 
154
 
    def _branch_name_to_ref(self, name):
155
 
        from bzrlib.plugins.git.refs import branch_name_to_ref
156
 
        ref = branch_name_to_ref(name, None)
157
 
        if ref == "HEAD":
158
 
            from dulwich.repo import SYMREF
159
 
            refcontents = self._git.refs.read_ref(ref)
160
 
            if refcontents.startswith(SYMREF):
161
 
                ref = refcontents[len(SYMREF):]
162
 
        return ref
163
 
 
164
 
    def is_control_filename(self, filename):
165
 
        return filename == '.git' or filename.startswith('.git/')
166
 
 
167
 
    def get_branch_transport(self, branch_format, name=None):
 
95
 
 
96
    def get_branch_transport(self, branch_format):
168
97
        if branch_format is None:
169
98
            return self.transport
170
 
        if isinstance(branch_format, LocalGitControlDirFormat):
171
 
            return self.transport
172
 
        raise bzr_errors.IncompatibleFormat(branch_format, self._format)
173
 
 
174
 
    def get_repository_transport(self, format):
175
 
        if format is None:
176
 
            return self.transport
177
 
        if isinstance(format, LocalGitControlDirFormat):
178
 
            return self.transport
179
 
        raise bzr_errors.IncompatibleFormat(format, self._format)
180
 
 
181
 
    def get_workingtree_transport(self, format):
182
 
        if format is None:
183
 
            return self.transport
184
 
        if isinstance(format, LocalGitControlDirFormat):
185
 
            return self.transport
186
 
        raise bzr_errors.IncompatibleFormat(format, self._format)
187
 
 
188
 
    def _open_branch(self, name=None, ignore_fallbacks=None, unsupported=False):
 
99
        if isinstance(branch_format, LocalGitBzrDirFormat):
 
100
            return self.transport
 
101
        raise errors.bzr_errors.IncompatibleFormat(branch_format, self._format)
 
102
 
 
103
    get_repository_transport = get_branch_transport
 
104
    get_workingtree_transport = get_branch_transport
 
105
 
 
106
    def open_branch(self, ignored=None):
189
107
        """'create' a branch for this dir."""
190
108
        repo = self.open_repository()
191
 
        from bzrlib.plugins.git.branch import LocalGitBranch
192
 
        return LocalGitBranch(self, repo, self._branch_name_to_ref(name),
193
 
            self._lockfiles)
194
 
 
195
 
    def destroy_branch(self, name=None):
196
 
        refname = self._branch_name_to_ref(name)
197
 
        if not refname in self._git.refs:
198
 
            raise bzr_errors.NotBranchError(self.root_transport.base,
199
 
                    bzrdir=self)
200
 
        del self._git.refs[refname]
201
 
 
202
 
    def destroy_repository(self):
203
 
        raise bzr_errors.UnsupportedOperation(self.destroy_repository, self)
204
 
 
205
 
    def destroy_workingtree(self):
206
 
        raise bzr_errors.UnsupportedOperation(self.destroy_workingtree, self)
207
 
 
208
 
    def needs_format_conversion(self, format=None):
209
 
        return not isinstance(self._format, format.__class__)
210
 
 
211
 
    def list_branches(self):
212
 
        ret = []
213
 
        for name in self._git.get_refs():
214
 
            if name.startswith("refs/heads/"):
215
 
                ret.append(self.open_branch(name=name))
216
 
        return ret
 
109
        return branch.LocalGitBranch(self, repo, "HEAD", repo._git.head(), self._lockfiles)
217
110
 
218
111
    def open_repository(self, shared=False):
219
112
        """'open' a repository for this dir."""
220
113
        return self._gitrepository_class(self, self._lockfiles)
221
114
 
222
115
    def open_workingtree(self, recommend_upgrade=True):
223
 
        if not self._git.bare:
224
 
            from dulwich.errors import NoIndexPresent
225
 
            repo = self.open_repository()
226
 
            try:
227
 
                index = repo._git.open_index()
228
 
            except NoIndexPresent:
229
 
                pass
230
 
            else:
231
 
                from bzrlib.plugins.git.workingtree import GitWorkingTree
232
 
                try:
233
 
                    branch = self.open_branch()
234
 
                except bzr_errors.NotBranchError:
235
 
                    pass
236
 
                else:
237
 
                    return GitWorkingTree(self, repo, branch, index)
 
116
        if (not self._git.bare and 
 
117
            os.path.exists(os.path.join(self._git.controldir(), "index"))):
 
118
            return workingtree.GitWorkingTree(self, self.open_repository(), 
 
119
                                                  self.open_branch())
238
120
        loc = urlutils.unescape_for_display(self.root_transport.base, 'ascii')
239
 
        raise bzr_errors.NoWorkingTree(loc)
 
121
        raise errors.bzr_errors.NoWorkingTree(loc)
240
122
 
241
123
    def create_repository(self, shared=False):
242
124
        return self.open_repository()
243
125
 
244
 
    def create_branch(self, name=None):
245
 
        refname = self._branch_name_to_ref(name)
246
 
        from dulwich.protocol import ZERO_SHA
247
 
        self._git.refs[refname or "HEAD"] = ZERO_SHA
248
 
        return self.open_branch(name)
249
 
 
250
 
    def backup_bzrdir(self):
251
 
        if self._git.bare:
252
 
            self.root_transport.copy_tree(".git", ".git.backup")
253
 
            return (self.root_transport.abspath(".git"),
254
 
                    self.root_transport.abspath(".git.backup"))
255
 
        else:
256
 
            raise bzr_errors.BzrError("Unable to backup bare repositories")
257
 
 
258
 
    def create_workingtree(self, revision_id=None, from_branch=None,
259
 
        accelerator_tree=None, hardlink=False):
260
 
        if self._git.bare:
261
 
            raise bzr_errors.BzrError("Can't create working tree in a bare repo")
262
 
        from dulwich.index import write_index
263
 
        from dulwich.pack import SHA1Writer
264
 
        f = open(self.transport.local_abspath("index"), 'w+')
265
 
        try:
266
 
            f = SHA1Writer(f)
267
 
            write_index(f, [])
268
 
        finally:
269
 
            f.close()
270
 
        return self.open_workingtree()
271
 
 
272
 
    def find_repository(self):
273
 
        """Find the repository that should be used.
274
 
 
275
 
        This does not require a branch as we use it to find the repo for
276
 
        new branches as well as to hook existing branches up to their
277
 
        repository.
278
 
        """
279
 
        return self.open_repository()
280
 
 
281
 
    def _find_creation_modes(self):
282
 
        """Determine the appropriate modes for files and directories.
283
 
 
284
 
        They're always set to be consistent with the base directory,
285
 
        assuming that this transport allows setting modes.
286
 
        """
287
 
        # TODO: Do we need or want an option (maybe a config setting) to turn
288
 
        # this off or override it for particular locations? -- mbp 20080512
289
 
        if self._mode_check_done:
290
 
            return
291
 
        self._mode_check_done = True
292
 
        try:
293
 
            st = self.transport.stat('.')
294
 
        except TransportNotPossible:
295
 
            self._dir_mode = None
296
 
            self._file_mode = None
297
 
        else:
298
 
            # Check the directory mode, but also make sure the created
299
 
            # directories and files are read-write for this user. This is
300
 
            # mostly a workaround for filesystems which lie about being able to
301
 
            # write to a directory (cygwin & win32)
302
 
            if (st.st_mode & 07777 == 00000):
303
 
                # FTP allows stat but does not return dir/file modes
304
 
                self._dir_mode = None
305
 
                self._file_mode = None
306
 
            else:
307
 
                self._dir_mode = (st.st_mode & 07777) | 00700
308
 
                # Remove the sticky and execute bits for files
309
 
                self._file_mode = self._dir_mode & ~07111
310
 
 
311
 
    def _get_file_mode(self):
312
 
        """Return Unix mode for newly created files, or None.
313
 
        """
314
 
        if not self._mode_check_done:
315
 
            self._find_creation_modes()
316
 
        return self._file_mode
317
 
 
318
 
    def _get_dir_mode(self):
319
 
        """Return Unix mode for newly created directories, or None.
320
 
        """
321
 
        if not self._mode_check_done:
322
 
            self._find_creation_modes()
323
 
        return self._dir_mode
324
 
 
 
126
 
 
127
class GitBzrDirFormat(bzrdir.BzrDirFormat):
 
128
    _lock_class = TransportLock
 
129
 
 
130
    def is_supported(self):
 
131
        return True
 
132
 
 
133
 
 
134
class LocalGitBzrDirFormat(GitBzrDirFormat):
 
135
    """The .git directory control format."""
 
136
 
 
137
    _gitdir_class = LocalGitDir
 
138
 
 
139
    @classmethod
 
140
    def _known_formats(self):
 
141
        return set([LocalGitBzrDirFormat()])
 
142
 
 
143
    def open(self, transport, _found=None):
 
144
        """Open this directory.
 
145
 
 
146
        """
 
147
        from bzrlib.plugins.git import git
 
148
        # we dont grok readonly - git isn't integrated with transport.
 
149
        url = transport.base
 
150
        if url.startswith('readonly+'):
 
151
            url = url[len('readonly+'):]
 
152
 
 
153
        try:
 
154
            gitrepo = git.repo.Repo(transport.local_abspath("."))
 
155
        except errors.bzr_errors.NotLocalUrl:
 
156
            raise errors.bzr_errors.NotBranchError(path=transport.base)
 
157
        lockfiles = GitLockableFiles(transport, GitLock())
 
158
        return self._gitdir_class(transport, lockfiles, gitrepo, self)
 
159
 
 
160
    @classmethod
 
161
    def probe_transport(klass, transport):
 
162
        """Our format is present if the transport ends in '.not/'."""
 
163
        from bzrlib.plugins.git import git
 
164
        # little ugly, but works
 
165
        format = klass()
 
166
        # delegate to the main opening code. This pays a double rtt cost at the
 
167
        # moment, so perhaps we want probe_transport to return the opened thing
 
168
        # rather than an openener ? or we could return a curried thing with the
 
169
        # dir to open already instantiated ? Needs more thought.
 
170
        try:
 
171
            format.open(transport)
 
172
            return format
 
173
        except git.errors.NotGitRepository, e:
 
174
            raise errors.bzr_errors.NotBranchError(path=transport.base)
 
175
        raise errors.bzr_errors.NotBranchError(path=transport.base)
 
176
 
 
177
    def get_format_description(self):
 
178
        return "Local Git Repository"
 
179
 
 
180
    def get_format_string(self):
 
181
        return "Local Git Repository"
 
182
 
 
183
    def initialize_on_transport(self, transport):
 
184
        from bzrlib.transport.local import LocalTransport
 
185
        from bzrlib.plugins.git import git
 
186
 
 
187
        if not isinstance(transport, LocalTransport):
 
188
            raise NotImplementedError(self.initialize, 
 
189
                "Can't create Git Repositories/branches on "
 
190
                "non-local transports")
 
191
 
 
192
        git.repo.Repo.create(transport.local_abspath(".")) 
 
193
        return self.open(transport)
 
194
 
 
195
    def is_supported(self):
 
196
        return True
 
197
 
 
198
 
 
199
class RemoteGitBzrDirFormat(GitBzrDirFormat):
 
200
    """The .git directory control format."""
 
201
 
 
202
    @classmethod
 
203
    def _known_formats(self):
 
204
        return set([RemoteGitBzrDirFormat()])
 
205
 
 
206
    def open(self, transport, _found=None):
 
207
        """Open this directory.
 
208
 
 
209
        """
 
210
        from bzrlib.plugins.git.remote import RemoteGitDir, GitSmartTransport
 
211
        if not isinstance(transport, GitSmartTransport):
 
212
            raise errors.bzr_errors.NotBranchError(transport.base)
 
213
        # we dont grok readonly - git isn't integrated with transport.
 
214
        url = transport.base
 
215
        if url.startswith('readonly+'):
 
216
            url = url[len('readonly+'):]
 
217
 
 
218
        lockfiles = GitLockableFiles(transport, GitLock())
 
219
        return RemoteGitDir(transport, lockfiles, self)
 
220
 
 
221
    @classmethod
 
222
    def probe_transport(klass, transport):
 
223
        """Our format is present if the transport ends in '.not/'."""
 
224
        # little ugly, but works
 
225
        format = klass()
 
226
        from bzrlib.plugins.git.remote import GitSmartTransport
 
227
        if not isinstance(transport, GitSmartTransport):
 
228
            raise errors.bzr_errors.NotBranchError(transport.base)
 
229
        # The only way to know a path exists and contains a valid repository 
 
230
        # is to do a request against it:
 
231
        try:
 
232
            transport.fetch_pack(lambda x: [], None, lambda x: None, 
 
233
                                 lambda x: mutter("git: %s" % x))
 
234
        except errors.git_errors.GitProtocolError:
 
235
            raise errors.bzr_errors.NotBranchError(path=transport.base)
 
236
        else:
 
237
            return format
 
238
        raise errors.bzr_errors.NotBranchError(path=transport.base)
 
239
 
 
240
    def get_format_description(self):
 
241
        return "Remote Git Repository"
 
242
 
 
243
    def get_format_string(self):
 
244
        return "Remote Git Repository"
 
245
 
 
246
    def initialize_on_transport(self, transport):
 
247
        raise errors.bzr_errors.UninitializableFormat(self)
325
248