/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 __init__.py

Merge changes to avoid inventories.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
"""A GIT branch and repository format implementation for bzr."""
23
23
 
 
24
from __future__ import absolute_import
 
25
 
24
26
import os
25
27
import sys
26
28
 
27
29
import bzrlib
28
30
import bzrlib.api
29
31
 
30
 
from info import (
 
32
from bzrlib.plugins.git.info import (
31
33
    bzr_compatible_versions,
32
34
    bzr_plugin_version as version_info,
33
35
    dulwich_minimum_version,
41
43
 
42
44
bzrlib.api.require_any_api(bzrlib, bzr_compatible_versions)
43
45
 
 
46
try:
 
47
    from bzrlib.i18n import load_plugin_translations
 
48
except ImportError: # No translations for bzr < 2.5
 
49
    gettext = lambda x: x
 
50
else:
 
51
    translation = load_plugin_translations("bzr-git")
 
52
    gettext = translation.gettext
44
53
 
45
54
from bzrlib import (
46
55
    errors as bzr_errors,
47
 
    osutils,
48
 
    )
49
 
try:
50
 
    from bzrlib.controldir import (
51
 
        ControlDirFormat,
52
 
        ControlDir,
53
 
        Prober,
54
 
        format_registry,
55
 
        )
56
 
except ImportError:
57
 
    # bzr < 2.3
58
 
    from bzrlib.bzrdir import (
59
 
        BzrDirFormat,
60
 
        BzrDir,
61
 
        format_registry,
62
 
        )
63
 
    ControlDir = BzrDir
64
 
    ControlDirFormat = BzrDirFormat
65
 
    Prober = object
66
 
    has_controldir = False
67
 
else:
68
 
    has_controldir = True
 
56
    trace,
 
57
    )
 
58
 
 
59
from bzrlib.controldir import (
 
60
    ControlDirFormat,
 
61
    Prober,
 
62
    format_registry,
 
63
    network_format_registry as controldir_network_format_registry,
 
64
    )
69
65
 
70
66
from bzrlib.foreign import (
71
67
    foreign_vcs_registry,
73
69
from bzrlib.help_topics import (
74
70
    topic_registry,
75
71
    )
76
 
from bzrlib.lockable_files import (
77
 
    TransportLock,
78
 
    )
79
72
from bzrlib.transport import (
80
73
    register_lazy_transport,
81
74
    register_transport_proto,
83
76
from bzrlib.commands import (
84
77
    plugin_cmds,
85
78
    )
86
 
from bzrlib.version_info_formats.format_rio import (
87
 
    RioVersionInfoBuilder,
88
 
    )
89
79
from bzrlib.send import (
90
80
    format_registry as send_format_registry,
91
81
    )
133
123
revspec_registry.register_lazy("git:", "bzrlib.plugins.git.revspec",
134
124
    "RevisionSpec_git")
135
125
 
136
 
try:
137
 
    from bzrlib.revisionspec import dwim_revspecs
138
 
except ImportError:
139
 
    pass
140
 
else:
141
 
    from bzrlib.plugins.git.revspec import RevisionSpec_git
142
 
    dwim_revspecs.append(RevisionSpec_git)
143
 
 
144
 
 
145
 
class GitControlDirFormat(ControlDirFormat):
146
 
 
147
 
    _lock_class = TransportLock
148
 
 
149
 
    colocated_branches = True
150
 
 
151
 
    def __eq__(self, other):
152
 
        return type(self) == type(other)
153
 
 
154
 
    def is_supported(self):
155
 
        return True
156
 
 
157
 
    def network_name(self):
158
 
        return "git"
 
126
from bzrlib.revisionspec import RevisionSpec_dwim
 
127
RevisionSpec_dwim.append_possible_lazy_revspec(
 
128
    "bzrlib.plugins.git.revspec", "RevisionSpec_git")
159
129
 
160
130
 
161
131
class LocalGitProber(Prober):
162
132
 
163
133
    def probe_transport(self, transport):
164
134
        try:
165
 
            if not transport.has_any(['info/refs', '.git/branches',
166
 
                                      'branches']):
167
 
                raise bzr_errors.NotBranchError(path=transport.base)
168
 
        except bzr_errors.NoSuchFile:
 
135
            external_url = transport.external_url()
 
136
        except bzr_errors.InProcessTransport:
 
137
            raise bzr_errors.NotBranchError(path=transport.base)
 
138
        if (external_url.startswith("http:") or
 
139
            external_url.startswith("https:")):
 
140
            # Already handled by RemoteGitProber
169
141
            raise bzr_errors.NotBranchError(path=transport.base)
170
142
        from bzrlib import urlutils
171
143
        if urlutils.split(transport.base)[1] == ".git":
172
144
            raise bzr_errors.NotBranchError(path=transport.base)
 
145
        if not transport.has_any(['objects', '.git/objects']):
 
146
            raise bzr_errors.NotBranchError(path=transport.base)
173
147
        lazy_check_versions()
174
 
        import dulwich
175
 
        from bzrlib.plugins.git.transportgit import TransportRepo
176
 
        try:
177
 
            gitrepo = TransportRepo(transport)
178
 
        except dulwich.errors.NotGitRepository, e:
179
 
            raise bzr_errors.NotBranchError(path=transport.base)
 
148
        from bzrlib.plugins.git.dir import (
 
149
            BareLocalGitControlDirFormat,
 
150
            LocalGitControlDirFormat,
 
151
            )
 
152
        if transport.has_any(['.git/objects']):
 
153
            return LocalGitControlDirFormat()
 
154
        if transport.has('info') and transport.has('objects'):
 
155
            return BareLocalGitControlDirFormat()
 
156
        raise bzr_errors.NotBranchError(path=transport.base)
 
157
 
 
158
    @classmethod
 
159
    def known_formats(cls):
 
160
        from bzrlib.plugins.git.dir import (
 
161
            BareLocalGitControlDirFormat,
 
162
            LocalGitControlDirFormat,
 
163
            )
 
164
        return set([BareLocalGitControlDirFormat(), LocalGitControlDirFormat()])
 
165
 
 
166
 
 
167
class RemoteGitProber(Prober):
 
168
 
 
169
    def probe_http_transport(self, transport):
 
170
        from bzrlib import urlutils
 
171
        base_url, _ = urlutils.split_segment_parameters(transport.external_url())
 
172
        url = urlutils.join(base_url, "info/refs") + "?service=git-upload-pack"
 
173
        from bzrlib.transport.http._urllib import HttpTransport_urllib, Request
 
174
        if isinstance(transport, HttpTransport_urllib):
 
175
            req = Request('GET', url, accepted_errors=[200, 403, 404, 405],
 
176
                          headers={"Content-Type": "application/x-git-upload-pack-request"})
 
177
            req.follow_redirections = True
 
178
            resp = transport._perform(req)
 
179
            if resp.code in (404, 405):
 
180
                raise bzr_errors.NotBranchError(transport.base)
 
181
            headers = resp.headers
 
182
            refs_text = resp.read()
180
183
        else:
181
 
            if gitrepo.bare:
182
 
                return BareLocalGitControlDirFormat()
 
184
            try:
 
185
                from bzrlib.transport.http._pycurl import PyCurlTransport
 
186
            except bzr_errors.DependencyNotPresent:
 
187
                raise bzr_errors.NotBranchError(transport.base)
183
188
            else:
184
 
                return LocalGitControlDirFormat()
185
 
 
186
 
 
187
 
class LocalGitControlDirFormat(GitControlDirFormat):
188
 
    """The .git directory control format."""
189
 
 
190
 
    bare = False
191
 
 
192
 
    @classmethod
193
 
    def _known_formats(self):
194
 
        return set([LocalGitControlDirFormat()])
195
 
 
196
 
    def open(self, transport, _found=None):
197
 
        """Open this directory.
198
 
 
199
 
        """
200
 
        lazy_check_versions()
201
 
        from bzrlib.plugins.git.transportgit import TransportRepo
202
 
        gitrepo = TransportRepo(transport)
203
 
        from bzrlib.plugins.git.dir import LocalGitDir, GitLockableFiles, GitLock
204
 
        lockfiles = GitLockableFiles(transport, GitLock())
205
 
        return LocalGitDir(transport, lockfiles, gitrepo, self)
206
 
 
207
 
    @classmethod
208
 
    def probe_transport(klass, transport):
209
 
        prober = LocalGitProber()
210
 
        return prober.probe_transport(transport)
211
 
 
212
 
    def get_format_description(self):
213
 
        return "Local Git Repository"
214
 
 
215
 
    def initialize_on_transport(self, transport):
216
 
        from bzrlib.transport.local import LocalTransport
217
 
 
218
 
        if not isinstance(transport, LocalTransport):
219
 
            raise NotImplementedError(self.initialize,
220
 
                "Can't create Git Repositories/branches on "
221
 
                "non-local transports")
222
 
        lazy_check_versions()
223
 
        from dulwich.repo import Repo
224
 
        Repo.init(transport.local_abspath(".").encode(osutils._fs_enc),
225
 
            bare=self.bare)
226
 
        return self.open(transport)
227
 
 
228
 
    def is_supported(self):
229
 
        return True
230
 
 
231
 
 
232
 
class BareLocalGitControlDirFormat(LocalGitControlDirFormat):
233
 
 
234
 
    bare = True
235
 
    supports_workingtrees = False
236
 
 
237
 
    @classmethod
238
 
    def _known_formats(self):
239
 
        return set([RemoteGitControlDirFormat()])
240
 
 
241
 
    def get_format_description(self):
242
 
        return "Local Git Repository (bare)"
243
 
 
244
 
 
245
 
class RemoteGitProber(Prober):
 
189
                import pycurl
 
190
                from cStringIO import StringIO
 
191
                if isinstance(transport, PyCurlTransport):
 
192
                    conn = transport._get_curl()
 
193
                    conn.setopt(pycurl.URL, url)
 
194
                    conn.setopt(pycurl.FOLLOWLOCATION, 1)
 
195
                    transport._set_curl_options(conn)
 
196
                    conn.setopt(pycurl.HTTPGET, 1)
 
197
                    header = StringIO()
 
198
                    data = StringIO()
 
199
                    conn.setopt(pycurl.HEADERFUNCTION, header.write)
 
200
                    conn.setopt(pycurl.WRITEFUNCTION, data.write)
 
201
                    transport._curl_perform(conn, header,
 
202
                        ["Content-Type: application/x-git-upload-pack-request"])
 
203
                    code = conn.getinfo(pycurl.HTTP_CODE)
 
204
                    if code in (404, 405):
 
205
                        raise bzr_errors.NotBranchError(transport.base)
 
206
                    if code != 200:
 
207
                        raise bzr_errors.InvalidHttpResponse(transport._path,
 
208
                            str(code))
 
209
                    headers = transport._parse_headers(header)
 
210
                else:
 
211
                    raise bzr_errors.NotBranchError(transport.base)
 
212
                refs_text = data.getvalue()
 
213
        ct = headers.getheader("Content-Type")
 
214
        if ct is None:
 
215
            raise bzr_errors.NotBranchError(transport.base)
 
216
        if ct.startswith("application/x-git"):
 
217
            from bzrlib.plugins.git.remote import RemoteGitControlDirFormat
 
218
            return RemoteGitControlDirFormat()
 
219
        else:
 
220
            from bzrlib.plugins.git.dir import (
 
221
                BareLocalGitControlDirFormat,
 
222
                )
 
223
            ret = BareLocalGitControlDirFormat()
 
224
            ret._refs_text = refs_text
 
225
            return ret
246
226
 
247
227
    def probe_transport(self, transport):
248
 
        url = transport.base
249
 
        if url.startswith('readonly+'):
250
 
            url = url[len('readonly+'):]
251
 
        if (not url.startswith("git://") and not url.startswith("git+")):
 
228
        try:
 
229
            external_url = transport.external_url()
 
230
        except bzr_errors.InProcessTransport:
 
231
            raise bzr_errors.NotBranchError(path=transport.base)
 
232
 
 
233
        if (external_url.startswith("http:") or
 
234
            external_url.startswith("https:")):
 
235
            return self.probe_http_transport(transport)
 
236
 
 
237
        if (not external_url.startswith("git://") and
 
238
            not external_url.startswith("git+")):
252
239
            raise bzr_errors.NotBranchError(transport.base)
 
240
 
253
241
        # little ugly, but works
254
 
        from bzrlib.plugins.git.remote import GitSmartTransport
255
 
        if not isinstance(transport, GitSmartTransport):
256
 
            raise bzr_errors.NotBranchError(transport.base)
257
 
        return RemoteGitControlDirFormat()
258
 
 
259
 
 
260
 
 
261
 
class RemoteGitControlDirFormat(GitControlDirFormat):
262
 
    """The .git directory control format."""
263
 
 
264
 
    supports_workingtrees = False
 
242
        from bzrlib.plugins.git.remote import (
 
243
            GitSmartTransport,
 
244
            RemoteGitControlDirFormat,
 
245
            )
 
246
        if isinstance(transport, GitSmartTransport):
 
247
            return RemoteGitControlDirFormat()
 
248
        raise bzr_errors.NotBranchError(path=transport.base)
265
249
 
266
250
    @classmethod
267
 
    def _known_formats(self):
 
251
    def known_formats(cls):
 
252
        from bzrlib.plugins.git.remote import RemoteGitControlDirFormat
268
253
        return set([RemoteGitControlDirFormat()])
269
254
 
270
 
    def open(self, transport, _found=None):
271
 
        """Open this directory.
272
 
 
273
 
        """
274
 
        # we dont grok readonly - git isn't integrated with transport.
275
 
        url = transport.base
276
 
        if url.startswith('readonly+'):
277
 
            url = url[len('readonly+'):]
278
 
        if (not url.startswith("git://") and not url.startswith("git+")):
279
 
            raise bzr_errors.NotBranchError(transport.base)
280
 
        from bzrlib.plugins.git.remote import RemoteGitDir, GitSmartTransport
281
 
        if not isinstance(transport, GitSmartTransport):
282
 
            raise bzr_errors.NotBranchError(transport.base)
283
 
        from bzrlib.plugins.git.dir import GitLockableFiles, GitLock
284
 
        lockfiles = GitLockableFiles(transport, GitLock())
285
 
        return RemoteGitDir(transport, lockfiles, self)
286
 
 
287
 
    @classmethod
288
 
    def probe_transport(klass, transport):
289
 
        """Our format is present if the transport ends in '.not/'."""
290
 
        prober = RemoteGitProber()
291
 
        return prober.probe_transport(transport)
292
 
 
293
 
    def get_format_description(self):
294
 
        return "Remote Git Repository"
295
 
 
296
 
    def initialize_on_transport(self, transport):
297
 
        raise bzr_errors.UninitializableFormat(self)
298
 
 
299
 
 
300
 
if has_controldir:
301
 
    ControlDirFormat.register_format(LocalGitControlDirFormat())
302
 
    ControlDirFormat.register_format(BareLocalGitControlDirFormat())
303
 
    ControlDirFormat.register_format(RemoteGitControlDirFormat())
304
 
    ControlDirFormat.register_prober(LocalGitProber)
305
 
    ControlDirFormat.register_prober(RemoteGitProber)
306
 
else:
307
 
    ControlDirFormat.register_control_format(LocalGitControlDirFormat)
308
 
    ControlDirFormat.register_control_format(BareLocalGitControlDirFormat)
309
 
    ControlDirFormat.register_control_format(RemoteGitControlDirFormat)
 
255
 
 
256
ControlDirFormat.register_prober(LocalGitProber)
 
257
ControlDirFormat._server_probers.append(RemoteGitProber)
310
258
 
311
259
register_transport_proto('git://',
312
260
        help="Access using the Git smart server protocol.")
319
267
                        'SSHGitSmartTransport')
320
268
 
321
269
foreign_vcs_registry.register_lazy("git",
322
 
    "bzrlib.plugins.git.mapping", "foreign_git", "Stupid content tracker")
 
270
    "bzrlib.plugins.git.mapping", "foreign_vcs_git", "Stupid content tracker")
323
271
 
324
272
plugin_cmds.register_lazy("cmd_git_import", [], "bzrlib.plugins.git.commands")
325
273
plugin_cmds.register_lazy("cmd_git_object", ["git-objects", "git-cat"],
327
275
plugin_cmds.register_lazy("cmd_git_refs", [], "bzrlib.plugins.git.commands")
328
276
plugin_cmds.register_lazy("cmd_git_apply", [], "bzrlib.plugins.git.commands")
329
277
 
 
278
def extract_git_foreign_revid(rev):
 
279
    try:
 
280
        foreign_revid = rev.foreign_revid
 
281
    except AttributeError:
 
282
        from bzrlib.plugins.git.mapping import mapping_registry
 
283
        foreign_revid, mapping = \
 
284
            mapping_registry.parse_revision_id(rev.revision_id)
 
285
        return foreign_revid
 
286
    else:
 
287
        from bzrlib.plugins.git.mapping import foreign_vcs_git
 
288
        if rev.mapping.vcs == foreign_vcs_git:
 
289
            return foreign_revid
 
290
        else:
 
291
            raise bzr_errors.InvalidRevisionId(rev.revision_id, None)
 
292
 
 
293
 
330
294
def update_stanza(rev, stanza):
331
295
    mapping = getattr(rev, "mapping", None)
332
 
    if mapping is not None and mapping.revid_prefix.startswith("git-"):
333
 
        stanza.add("git-commit", rev.foreign_revid)
334
 
 
335
 
 
336
 
rio_hooks = getattr(RioVersionInfoBuilder, "hooks", None)
337
 
if rio_hooks is not None:
338
 
    rio_hooks.install_named_hook('revision', update_stanza, None)
 
296
    try:
 
297
        git_commit = extract_git_foreign_revid(rev)
 
298
    except bzr_errors.InvalidRevisionId:
 
299
        pass
 
300
    else:
 
301
        stanza.add("git-commit", git_commit)
 
302
 
 
303
from bzrlib.hooks import install_lazy_named_hook
 
304
install_lazy_named_hook("bzrlib.version_info_formats.format_rio",
 
305
    "RioVersionInfoBuilder.hooks", "revision", update_stanza,
 
306
    "git commits")
339
307
 
340
308
 
341
309
from bzrlib.transport import transport_server_registry
344
312
    'serve_git',
345
313
    'Git Smart server protocol over TCP. (default port: 9418)')
346
314
 
 
315
transport_server_registry.register_lazy('git-receive-pack',
 
316
    'bzrlib.plugins.git.server',
 
317
    'serve_git_receive_pack',
 
318
    help='Git Smart server receive pack command (inetd mode only)')
 
319
transport_server_registry.register_lazy('git-upload-pack',
 
320
    'bzrlib.plugins.git.server',
 
321
    'serve_git_upload_pack',
 
322
    help='Git Smart server upload pack command (inetd mode only)')
347
323
 
348
324
from bzrlib.repository import (
 
325
    format_registry as repository_format_registry,
349
326
    network_format_registry as repository_network_format_registry,
350
327
    )
351
328
repository_network_format_registry.register_lazy('git',
352
329
    'bzrlib.plugins.git.repository', 'GitRepositoryFormat')
353
330
 
354
 
try:
355
 
    from bzrlib.controldir import (
356
 
        network_format_registry as controldir_network_format_registry,
357
 
        )
358
 
except ImportError:
359
 
    from bzrlib.bzrdir import (
360
 
        network_format_registry as controldir_network_format_registry,
361
 
        )
362
 
controldir_network_format_registry.register('git', GitControlDirFormat)
 
331
register_extra_lazy_repository_format = getattr(repository_format_registry,
 
332
    "register_extra_lazy")
 
333
register_extra_lazy_repository_format('bzrlib.plugins.git.repository',
 
334
    'GitRepositoryFormat')
 
335
 
 
336
from bzrlib.branch import (
 
337
    network_format_registry as branch_network_format_registry,
 
338
    )
 
339
branch_network_format_registry.register_lazy('git',
 
340
    'bzrlib.plugins.git.branch', 'GitBranchFormat')
 
341
 
 
342
from bzrlib.branch import (
 
343
    format_registry as branch_format_registry,
 
344
    )
 
345
branch_format_registry.register_extra_lazy(
 
346
    'bzrlib.plugins.git.branch',
 
347
    'GitBranchFormat',
 
348
    )
 
349
 
 
350
from bzrlib.workingtree import (
 
351
    format_registry as workingtree_format_registry,
 
352
    )
 
353
workingtree_format_registry.register_extra_lazy(
 
354
    'bzrlib.plugins.git.workingtree',
 
355
    'GitWorkingTreeFormat',
 
356
    )
 
357
 
 
358
controldir_network_format_registry.register_lazy('git',
 
359
    "bzrlib.plugins.git.dir", "GitControlDirFormat")
363
360
 
364
361
send_format_registry.register_lazy('git', 'bzrlib.plugins.git.send',
365
362
                                   'send_git', 'Git am-style diff format')
366
363
 
367
 
topic_registry.register_lazy('git',
368
 
                             'bzrlib.plugins.git.help',
369
 
                             'help_git', 'Using Bazaar with Git')
370
 
 
371
 
try:
372
 
    from bzrlib.diff import format_registry as diff_format_registry
373
 
except ImportError:
374
 
    pass
375
 
else:
376
 
    diff_format_registry.register_lazy('git', 'bzrlib.plugins.git.send',
377
 
        'GitDiffTree', 'Git am-style diff format')
 
364
topic_registry.register_lazy('git', 'bzrlib.plugins.git.help', 'help_git',
 
365
    'Using Bazaar with Git')
 
366
 
 
367
from bzrlib.diff import format_registry as diff_format_registry
 
368
diff_format_registry.register_lazy('git', 'bzrlib.plugins.git.send',
 
369
    'GitDiffTree', 'Git am-style diff format')
 
370
 
 
371
 
 
372
def update_git_cache(repository, revid):
 
373
    """Update the git cache after a local commit."""
 
374
    if getattr(repository, "_git", None) is not None:
 
375
        return # No need to update cache for git repositories
 
376
 
 
377
    if not repository.control_transport.has("git"):
 
378
        return # No existing cache, don't bother updating
 
379
    try:
 
380
        lazy_check_versions()
 
381
    except bzr_errors.DependencyNotPresent, e:
 
382
        # dulwich is probably missing. silently ignore
 
383
        trace.mutter("not updating git map for %r: %s",
 
384
            repository, e)
 
385
 
 
386
    from bzrlib.plugins.git.object_store import BazaarObjectStore
 
387
    store = BazaarObjectStore(repository)
 
388
    store.lock_write()
 
389
    try:
 
390
        parent_revisions = set(repository.get_parent_map([revid])[revid])
 
391
        missing_revisions = store._missing_revisions(parent_revisions)
 
392
        if not missing_revisions:
 
393
            # Only update if the cache was up to date previously
 
394
            store._update_sha_map_revision(revid)
 
395
    finally:
 
396
        store.unlock()
 
397
 
 
398
 
 
399
def post_commit_update_cache(local_branch, master_branch, old_revno, old_revid,
 
400
        new_revno, new_revid):
 
401
    if local_branch is not None:
 
402
        update_git_cache(local_branch.repository, new_revid)
 
403
    update_git_cache(master_branch.repository, new_revid)
 
404
 
 
405
 
 
406
def loggerhead_git_hook(branch_app, environ):
 
407
    from bzrlib.config import GlobalConfig
 
408
    branch = branch_app.branch
 
409
    if GlobalConfig().get_user_option('http_git') != 'True':
 
410
        return None
 
411
    from bzrlib.plugins.git.server import git_http_hook
 
412
    return git_http_hook(branch, environ['REQUEST_METHOD'],
 
413
        environ['PATH_INFO'])
 
414
 
 
415
install_lazy_named_hook("bzrlib.branch",
 
416
    "Branch.hooks", "post_commit", post_commit_update_cache,
 
417
    "git cache")
 
418
install_lazy_named_hook("bzrlib.plugins.loggerhead.apps.branch",
 
419
    "BranchWSGIApp.hooks", "controller",
 
420
    loggerhead_git_hook, "git support")
 
421
 
 
422
from bzrlib.directory_service import directories
 
423
 
 
424
directories.register_lazy('github:', 'bzrlib.plugins.git.directory',
 
425
                          'GitHubDirectory',
 
426
                          'GitHub directory.')
 
427
directories.register_lazy('git@github.com:', 'bzrlib.plugins.git.directory',
 
428
                          'GitHubDirectory',
 
429
                          'GitHub directory.')
378
430
 
379
431
def test_suite():
380
432
    from bzrlib.plugins.git import tests