/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

In prober, always return or raise NotBranchError.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006-2009 Canonical Ltd
 
2
 
 
3
# Authors: Robert Collins <robert.collins@canonical.com>
 
4
#          Jelmer Vernooij <jelmer@samba.org>
 
5
#          John Carr <john.carr@unrouted.co.uk>
 
6
#
 
7
# This program is free software; you can redistribute it and/or modify
 
8
# it under the terms of the GNU General Public License as published by
 
9
# the Free Software Foundation; either version 2 of the License, or
 
10
# (at your option) any later version.
 
11
#
 
12
# This program is distributed in the hope that it will be useful,
 
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
# GNU General Public License for more details.
 
16
#
 
17
# You should have received a copy of the GNU General Public License
 
18
# along with this program; if not, write to the Free Software
 
19
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
20
 
 
21
 
 
22
"""A GIT branch and repository format implementation for bzr."""
 
23
 
 
24
import os
 
25
import sys
 
26
 
 
27
import bzrlib
 
28
import bzrlib.api
 
29
 
 
30
from info import (
 
31
    bzr_compatible_versions,
 
32
    bzr_plugin_version as version_info,
 
33
    dulwich_minimum_version,
 
34
    )
 
35
 
 
36
if version_info[3] == 'final':
 
37
    version_string = '%d.%d.%d' % version_info[:3]
 
38
else:
 
39
    version_string = '%d.%d.%d%s%d' % version_info
 
40
__version__ = version_string
 
41
 
 
42
bzrlib.api.require_any_api(bzrlib, bzr_compatible_versions)
 
43
 
 
44
 
 
45
from bzrlib import (
 
46
    errors as bzr_errors,
 
47
    trace,
 
48
    )
 
49
 
 
50
from bzrlib.controldir import (
 
51
    ControlDirFormat,
 
52
    Prober,
 
53
    format_registry,
 
54
    network_format_registry as controldir_network_format_registry,
 
55
    )
 
56
 
 
57
from bzrlib.foreign import (
 
58
    foreign_vcs_registry,
 
59
    )
 
60
from bzrlib.help_topics import (
 
61
    topic_registry,
 
62
    )
 
63
from bzrlib.transport import (
 
64
    register_lazy_transport,
 
65
    register_transport_proto,
 
66
    )
 
67
from bzrlib.commands import (
 
68
    plugin_cmds,
 
69
    )
 
70
from bzrlib.send import (
 
71
    format_registry as send_format_registry,
 
72
    )
 
73
 
 
74
 
 
75
if getattr(sys, "frozen", None):
 
76
    # allow import additional libs from ./_lib for bzr.exe only
 
77
    sys.path.append(os.path.normpath(
 
78
        os.path.join(os.path.dirname(__file__), '_lib')))
 
79
 
 
80
 
 
81
def import_dulwich():
 
82
    try:
 
83
        from dulwich import __version__ as dulwich_version
 
84
    except ImportError:
 
85
        raise bzr_errors.DependencyNotPresent("dulwich",
 
86
            "bzr-git: Please install dulwich, https://launchpad.net/dulwich")
 
87
    else:
 
88
        if dulwich_version < dulwich_minimum_version:
 
89
            raise bzr_errors.DependencyNotPresent("dulwich",
 
90
                "bzr-git: Dulwich is too old; at least %d.%d.%d is required" %
 
91
                    dulwich_minimum_version)
 
92
 
 
93
 
 
94
_versions_checked = False
 
95
def lazy_check_versions():
 
96
    global _versions_checked
 
97
    if _versions_checked:
 
98
        return
 
99
    import_dulwich()
 
100
    _versions_checked = True
 
101
 
 
102
format_registry.register_lazy('git',
 
103
    "bzrlib.plugins.git.dir", "LocalGitControlDirFormat",
 
104
    help='GIT repository.', native=False, experimental=False,
 
105
    )
 
106
 
 
107
format_registry.register_lazy('git-bare',
 
108
    "bzrlib.plugins.git.dir", "BareLocalGitControlDirFormat",
 
109
    help='Bare GIT repository (no working tree).', native=False,
 
110
    experimental=False,
 
111
    )
 
112
 
 
113
from bzrlib.revisionspec import revspec_registry
 
114
revspec_registry.register_lazy("git:", "bzrlib.plugins.git.revspec",
 
115
    "RevisionSpec_git")
 
116
 
 
117
from bzrlib.revisionspec import dwim_revspecs, RevisionSpec_dwim
 
118
if getattr(RevisionSpec_dwim, "append_possible_lazy_revspec", None):
 
119
    RevisionSpec_dwim.append_possible_lazy_revspec(
 
120
        "bzrlib.plugins.git.revspec", "RevisionSpec_git")
 
121
else: # bzr < 2.4
 
122
    from bzrlib.plugins.git.revspec import RevisionSpec_git
 
123
    dwim_revspecs.append(RevisionSpec_git)
 
124
 
 
125
 
 
126
class LocalGitProber(Prober):
 
127
 
 
128
    def probe_transport(self, transport):
 
129
        try:
 
130
            external_url = transport.external_url()
 
131
        except bzr_errors.InProcessTransport:
 
132
            raise bzr_errors.NotBranchError(path=transport.base)
 
133
        if (external_url.startswith("http:") or
 
134
            external_url.startswith("https:")):
 
135
            # Already handled by RemoteGitProber
 
136
            raise bzr_errors.NotBranchError(path=transport.base)
 
137
        from bzrlib import urlutils
 
138
        if urlutils.split(transport.base)[1] == ".git":
 
139
            raise bzr_errors.NotBranchError(path=transport.base)
 
140
        if not transport.has_any(['objects', '.git/objects']):
 
141
            raise bzr_errors.NotBranchError(path=transport.base)
 
142
        lazy_check_versions()
 
143
        from bzrlib.plugins.git.dir import (
 
144
            BareLocalGitControlDirFormat,
 
145
            LocalGitControlDirFormat,
 
146
            )
 
147
        if transport.has_any(['.git/objects']):
 
148
            return LocalGitControlDirFormat()
 
149
        if transport.has('info') and transport.has('objects'):
 
150
            return BareLocalGitControlDirFormat()
 
151
        raise bzr_errors.NotBranchError(path=transport.base)
 
152
 
 
153
    @classmethod
 
154
    def known_formats(cls):
 
155
        from bzrlib.plugins.git.dir import (
 
156
            BareLocalGitControlDirFormat,
 
157
            LocalGitControlDirFormat,
 
158
            )
 
159
        return set([BareLocalGitControlDirFormat(), LocalGitControlDirFormat()])
 
160
 
 
161
 
 
162
class RemoteGitProber(Prober):
 
163
 
 
164
    def probe_http_transport(self, transport):
 
165
        from bzrlib import urlutils
 
166
        url = urlutils.join(transport.external_url(), "info/refs") + "?service=git-upload-pack"
 
167
        from bzrlib.transport.http._urllib import HttpTransport_urllib, Request
 
168
        if isinstance(transport, HttpTransport_urllib):
 
169
            req = Request('GET', url, accepted_errors=[200, 403, 404, 405],
 
170
                          headers={"Content-Type": "application/x-git-upload-pack-request"})
 
171
            req.follow_redirections = True
 
172
            resp = transport._perform(req)
 
173
            if resp.code == 404:
 
174
                raise bzr_errors.NotBranchError(transport.base)
 
175
            headers = resp.headers
 
176
        else:
 
177
            try:
 
178
                from bzrlib.transport.http._pycurl import PyCurlTransport
 
179
            except bzr_errors.DependencyNotPresent:
 
180
                raise bzr_errors.NotBranchError(transport.base)
 
181
            else:
 
182
                import pycurl
 
183
                from cStringIO import StringIO
 
184
                if isinstance(transport, PyCurlTransport):
 
185
                    conn = transport._get_curl()
 
186
                    conn.setopt(pycurl.URL, url)
 
187
                    transport._set_curl_options(conn)
 
188
                    conn.setopt(pycurl.HTTPGET, 1)
 
189
                    header = StringIO()
 
190
                    data = StringIO()
 
191
                    conn.setopt(pycurl.HEADERFUNCTION, header.write)
 
192
                    conn.setopt(pycurl.WRITEFUNCTION, data.write)
 
193
                    transport._curl_perform(conn, header,
 
194
                        ["Content-Type: application/x-git-upload-pack-request"])
 
195
                    code = conn.getinfo(pycurl.HTTP_CODE)
 
196
                    if code == 404:
 
197
                        raise bzr_errors.NotBranchError(transport.base)
 
198
                    if code != 200:
 
199
                        raise bzr_errors.InvalidHttpResponse(transport._path,
 
200
                            str(code))
 
201
                    headers = transport._parse_headers(header)
 
202
                else:
 
203
                    raise bzr_errors.NotBranchError(transport.base)
 
204
        ct = headers.getheader("Content-Type")
 
205
        if ct.startswith("application/x-git"):
 
206
            from bzrlib.plugins.git.remote import RemoteGitControlDirFormat
 
207
            return RemoteGitControlDirFormat()
 
208
        else:
 
209
            from bzrlib.plugins.git.dir import (
 
210
                BareLocalGitControlDirFormat,
 
211
                )
 
212
            return BareLocalGitControlDirFormat()
 
213
 
 
214
    def probe_transport(self, transport):
 
215
        try:
 
216
            external_url = transport.external_url()
 
217
        except bzr_errors.InProcessTransport:
 
218
            raise bzr_errors.NotBranchError(path=transport.base)
 
219
 
 
220
        if (external_url.startswith("http:") or
 
221
            external_url.startswith("https:")):
 
222
            return self.probe_http_transport(transport)
 
223
 
 
224
        if (not external_url.startswith("git://") and
 
225
            not external_url.startswith("git+")):
 
226
            raise bzr_errors.NotBranchError(transport.base)
 
227
 
 
228
        # little ugly, but works
 
229
        from bzrlib.plugins.git.remote import (
 
230
            GitSmartTransport,
 
231
            RemoteGitControlDirFormat,
 
232
            )
 
233
        if isinstance(transport, GitSmartTransport):
 
234
            return RemoteGitControlDirFormat()
 
235
        raise bzr_errors.NotBranchError(path=transport.base)
 
236
 
 
237
    @classmethod
 
238
    def known_formats(cls):
 
239
        from bzrlib.plugins.git.remote import RemoteGitControlDirFormat
 
240
        return set([RemoteGitControlDirFormat()])
 
241
 
 
242
 
 
243
if not getattr(Prober, "known_formats", None): # bzr < 2.4
 
244
    from bzrlib.plugins.git.dir import (
 
245
        LocalGitControlDirFormat, BareLocalGitControlDirFormat,
 
246
        )
 
247
    from bzrlib.plugins.git.remote import RemoteGitControlDirFormat
 
248
    ControlDirFormat.register_format(LocalGitControlDirFormat())
 
249
    ControlDirFormat.register_format(BareLocalGitControlDirFormat())
 
250
    ControlDirFormat.register_format(RemoteGitControlDirFormat())
 
251
    # Provide RevisionTree.get_file_revision, so various parts of bzr-svn
 
252
    # can avoid inventories.
 
253
    from bzrlib.revisiontree import RevisionTree
 
254
    def get_file_revision(tree, file_id, path=None):
 
255
        return tree.inventory[file_id].revision
 
256
    RevisionTree.get_file_revision = get_file_revision
 
257
 
 
258
ControlDirFormat.register_prober(LocalGitProber)
 
259
ControlDirFormat._server_probers.insert(0, RemoteGitProber)
 
260
 
 
261
register_transport_proto('git://',
 
262
        help="Access using the Git smart server protocol.")
 
263
register_transport_proto('git+ssh://',
 
264
        help="Access using the Git smart server protocol over SSH.")
 
265
 
 
266
register_lazy_transport("git://", 'bzrlib.plugins.git.remote',
 
267
                        'TCPGitSmartTransport')
 
268
register_lazy_transport("git+ssh://", 'bzrlib.plugins.git.remote',
 
269
                        'SSHGitSmartTransport')
 
270
 
 
271
foreign_vcs_registry.register_lazy("git",
 
272
    "bzrlib.plugins.git.mapping", "foreign_vcs_git", "Stupid content tracker")
 
273
 
 
274
plugin_cmds.register_lazy("cmd_git_import", [], "bzrlib.plugins.git.commands")
 
275
plugin_cmds.register_lazy("cmd_git_object", ["git-objects", "git-cat"],
 
276
    "bzrlib.plugins.git.commands")
 
277
plugin_cmds.register_lazy("cmd_git_refs", [], "bzrlib.plugins.git.commands")
 
278
plugin_cmds.register_lazy("cmd_git_apply", [], "bzrlib.plugins.git.commands")
 
279
 
 
280
def extract_git_foreign_revid(rev):
 
281
    try:
 
282
        foreign_revid = rev.foreign_revid
 
283
    except AttributeError:
 
284
        from bzrlib.plugins.git.mapping import mapping_registry
 
285
        foreign_revid, mapping = \
 
286
            mapping_registry.parse_revision_id(rev.revision_id)
 
287
        return foreign_revid
 
288
    else:
 
289
        from bzrlib.plugins.git.mapping import foreign_vcs_git
 
290
        if rev.mapping.vcs == foreign_vcs_git:
 
291
            return foreign_revid
 
292
        else:
 
293
            raise bzr_errors.InvalidRevisionId(rev.revision_id, None)
 
294
 
 
295
 
 
296
def update_stanza(rev, stanza):
 
297
    mapping = getattr(rev, "mapping", None)
 
298
    try:
 
299
        git_commit = extract_git_foreign_revid(rev)
 
300
    except bzr_errors.InvalidRevisionId:
 
301
        pass
 
302
    else:
 
303
        stanza.add("git-commit", git_commit)
 
304
 
 
305
try:
 
306
    from bzrlib.hooks import install_lazy_named_hook
 
307
except ImportError: # Compatibility with bzr < 2.4
 
308
    from bzrlib.version_info_formats.format_rio import (
 
309
        RioVersionInfoBuilder,
 
310
        )
 
311
    RioVersionInfoBuilder.hooks.install_named_hook('revision', update_stanza,
 
312
        "git commits")
 
313
else:
 
314
    install_lazy_named_hook("bzrlib.version_info_formats.format_rio",
 
315
        "RioVersionInfoBuilder.hooks", "revision", update_stanza,
 
316
        "git commits")
 
317
 
 
318
 
 
319
from bzrlib.transport import transport_server_registry
 
320
transport_server_registry.register_lazy('git',
 
321
    'bzrlib.plugins.git.server',
 
322
    'serve_git',
 
323
    'Git Smart server protocol over TCP. (default port: 9418)')
 
324
 
 
325
 
 
326
from bzrlib.repository import (
 
327
    format_registry as repository_format_registry,
 
328
    network_format_registry as repository_network_format_registry,
 
329
    )
 
330
repository_network_format_registry.register_lazy('git',
 
331
    'bzrlib.plugins.git.repository', 'GitRepositoryFormat')
 
332
 
 
333
try:
 
334
    register_extra_lazy_repository_format = getattr(repository_format_registry,
 
335
        "register_extra_lazy")
 
336
except AttributeError: # bzr < 2.4
 
337
    pass
 
338
else:
 
339
    register_extra_lazy_repository_format('bzrlib.plugins.git.repository',
 
340
        'GitRepositoryFormat')
 
341
 
 
342
from bzrlib.branch import (
 
343
    network_format_registry as branch_network_format_registry,
 
344
    )
 
345
branch_network_format_registry.register_lazy('git',
 
346
    'bzrlib.plugins.git.branch', 'GitBranchFormat')
 
347
 
 
348
try:
 
349
    from bzrlib.branch import (
 
350
        format_registry as branch_format_registry,
 
351
        )
 
352
except ImportError: # bzr < 2.4
 
353
    pass
 
354
else:
 
355
    branch_format_registry.register_extra_lazy(
 
356
        'bzrlib.plugins.git.branch',
 
357
        'GitBranchFormat',
 
358
        )
 
359
 
 
360
try:
 
361
    from bzrlib.workingtree import (
 
362
        format_registry as workingtree_format_registry,
 
363
        )
 
364
except ImportError: # bzr < 2.4
 
365
    pass
 
366
else:
 
367
    workingtree_format_registry.register_extra_lazy(
 
368
        'bzrlib.plugins.git.workingtree',
 
369
        'GitWorkingTreeFormat',
 
370
        )
 
371
 
 
372
controldir_network_format_registry.register_lazy('git',
 
373
    "bzrlib.plugins.git.dir", "GitControlDirFormat")
 
374
 
 
375
send_format_registry.register_lazy('git', 'bzrlib.plugins.git.send',
 
376
                                   'send_git', 'Git am-style diff format')
 
377
 
 
378
topic_registry.register_lazy('git', 'bzrlib.plugins.git.help', 'help_git',
 
379
    'Using Bazaar with Git')
 
380
 
 
381
from bzrlib.diff import format_registry as diff_format_registry
 
382
diff_format_registry.register_lazy('git', 'bzrlib.plugins.git.send',
 
383
    'GitDiffTree', 'Git am-style diff format')
 
384
 
 
385
 
 
386
def update_git_cache(repository, revid):
 
387
    """Update the git cache after a local commit."""
 
388
    if getattr(repository, "_git", None) is not None:
 
389
        return # No need to update cache for git repositories
 
390
 
 
391
    if not repository.control_transport.has("git"):
 
392
        return # No existing cache, don't bother updating
 
393
    try:
 
394
        lazy_check_versions()
 
395
    except bzr_errors.DependencyNotPresent, e:
 
396
        # dulwich is probably missing. silently ignore
 
397
        trace.mutter("not updating git map for %r: %s",
 
398
            repository, e)
 
399
 
 
400
    from bzrlib.plugins.git.object_store import BazaarObjectStore
 
401
    store = BazaarObjectStore(repository)
 
402
    store.lock_write()
 
403
    try:
 
404
        parent_revisions = set(repository.get_parent_map([revid])[revid])
 
405
        missing_revisions = store._missing_revisions(parent_revisions)
 
406
        if not missing_revisions:
 
407
            # Only update if the cache was up to date previously
 
408
            store._update_sha_map_revision(revid)
 
409
    finally:
 
410
        store.unlock()
 
411
 
 
412
 
 
413
def post_commit_update_cache(local_branch, master_branch, old_revno, old_revid,
 
414
        new_revno, new_revid):
 
415
    if local_branch is not None:
 
416
        update_git_cache(local_branch.repository, new_revid)
 
417
    update_git_cache(master_branch.repository, new_revid)
 
418
 
 
419
 
 
420
try:
 
421
    from bzrlib.hooks import install_lazy_named_hook
 
422
except ImportError: # Compatibility with bzr < 2.4
 
423
    pass
 
424
else:
 
425
    install_lazy_named_hook("bzrlib.branch",
 
426
        "Branch.hooks", "post_commit", post_commit_update_cache,
 
427
        "git cache")
 
428
 
 
429
 
 
430
def test_suite():
 
431
    from bzrlib.plugins.git import tests
 
432
    return tests.test_suite()