/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

Avoid using HEAD.

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
 
 
152
    @classmethod
 
153
    def known_formats(cls):
 
154
        from bzrlib.plugins.git.dir import (
 
155
            BareLocalGitControlDirFormat,
 
156
            LocalGitControlDirFormat,
 
157
            )
 
158
        return set([BareLocalGitControlDirFormat(), LocalGitControlDirFormat()])
 
159
 
 
160
 
 
161
class RemoteGitProber(Prober):
 
162
 
 
163
    def probe_http_transport(self, transport):
 
164
        from bzrlib import urlutils
 
165
        url = urlutils.join(transport.external_url(), "info/refs") + "?service=git-upload-pack"
 
166
        from bzrlib.transport.http._urllib import HttpTransport_urllib, Request
 
167
        if isinstance(transport, HttpTransport_urllib):
 
168
            req = Request('GET', url, accepted_errors=[200, 403, 404, 405],
 
169
                          headers={"Content-Type": "application/x-git-upload-pack-request"})
 
170
            req.follow_redirections = True
 
171
            resp = transport._perform(req)
 
172
            if resp.code == 404:
 
173
                raise bzr_errors.NotBranchError(transport.base)
 
174
            headers = resp.headers
 
175
        else:
 
176
            try:
 
177
                from bzrlib.transport.http._pycurl import PyCurlTransport
 
178
            except bzr_errors.DependencyNotPresent:
 
179
                raise bzr_errors.NotBranchError(transport.base)
 
180
            else:
 
181
                import pycurl
 
182
                from cStringIO import StringIO
 
183
                if isinstance(transport, PyCurlTransport):
 
184
                    conn = transport._get_curl()
 
185
                    conn.setopt(pycurl.URL, url)
 
186
                    transport._set_curl_options(conn)
 
187
                    conn.setopt(pycurl.HTTPGET, 1)
 
188
                    header = StringIO()
 
189
                    data = StringIO()
 
190
                    conn.setopt(pycurl.HEADERFUNCTION, header.write)
 
191
                    conn.setopt(pycurl.WRITEFUNCTION, data.write)
 
192
                    transport._curl_perform(conn, header,
 
193
                        ["Content-Type: application/x-git-upload-pack-request"])
 
194
                    code = conn.getinfo(pycurl.HTTP_CODE)
 
195
                    if code == 404:
 
196
                        raise bzr_errors.NotBranchError(transport.base)
 
197
                    if code != 200:
 
198
                        raise bzr_errors.InvalidHttpResponse(transport._path,
 
199
                            str(code))
 
200
                    headers = transport._parse_headers(header)
 
201
                else:
 
202
                    raise bzr_errors.NotBranchError(transport.base)
 
203
        ct = headers.getheader("Content-Type")
 
204
        if ct.startswith("application/x-git"):
 
205
            from bzrlib.plugins.git.remote import RemoteGitControlDirFormat
 
206
            return RemoteGitControlDirFormat()
 
207
        else:
 
208
            from bzrlib.plugins.git.dir import (
 
209
                BareLocalGitControlDirFormat,
 
210
                )
 
211
            return BareLocalGitControlDirFormat()
 
212
 
 
213
    def probe_transport(self, transport):
 
214
        try:
 
215
            external_url = transport.external_url()
 
216
        except bzr_errors.InProcessTransport:
 
217
            raise bzr_errors.NotBranchError(path=transport.base)
 
218
 
 
219
        if (external_url.startswith("http:") or
 
220
            external_url.startswith("https:")):
 
221
            return self.probe_http_transport(transport)
 
222
 
 
223
        if (not external_url.startswith("git://") and
 
224
            not external_url.startswith("git+")):
 
225
            raise bzr_errors.NotBranchError(transport.base)
 
226
 
 
227
        # little ugly, but works
 
228
        from bzrlib.plugins.git.remote import (
 
229
            GitSmartTransport,
 
230
            RemoteGitControlDirFormat,
 
231
            )
 
232
        if isinstance(transport, GitSmartTransport):
 
233
            return RemoteGitControlDirFormat()
 
234
        raise bzr_errors.NotBranchError(path=transport.base)
 
235
 
 
236
    @classmethod
 
237
    def known_formats(cls):
 
238
        from bzrlib.plugins.git.remote import RemoteGitControlDirFormat
 
239
        return set([RemoteGitControlDirFormat()])
 
240
 
 
241
 
 
242
if not getattr(Prober, "known_formats", None): # bzr < 2.4
 
243
    from bzrlib.plugins.git.dir import (
 
244
        LocalGitControlDirFormat, BareLocalGitControlDirFormat,
 
245
        )
 
246
    from bzrlib.plugins.git.remote import RemoteGitControlDirFormat
 
247
    ControlDirFormat.register_format(LocalGitControlDirFormat())
 
248
    ControlDirFormat.register_format(BareLocalGitControlDirFormat())
 
249
    ControlDirFormat.register_format(RemoteGitControlDirFormat())
 
250
    # Provide RevisionTree.get_file_revision, so various parts of bzr-svn
 
251
    # can avoid inventories.
 
252
    from bzrlib.revisiontree import RevisionTree
 
253
    def get_file_revision(tree, file_id, path=None):
 
254
        return tree.inventory[file_id].revision
 
255
    RevisionTree.get_file_revision = get_file_revision
 
256
 
 
257
ControlDirFormat.register_prober(LocalGitProber)
 
258
ControlDirFormat._server_probers.insert(0, RemoteGitProber)
 
259
 
 
260
register_transport_proto('git://',
 
261
        help="Access using the Git smart server protocol.")
 
262
register_transport_proto('git+ssh://',
 
263
        help="Access using the Git smart server protocol over SSH.")
 
264
 
 
265
register_lazy_transport("git://", 'bzrlib.plugins.git.remote',
 
266
                        'TCPGitSmartTransport')
 
267
register_lazy_transport("git+ssh://", 'bzrlib.plugins.git.remote',
 
268
                        'SSHGitSmartTransport')
 
269
 
 
270
foreign_vcs_registry.register_lazy("git",
 
271
    "bzrlib.plugins.git.mapping", "foreign_vcs_git", "Stupid content tracker")
 
272
 
 
273
plugin_cmds.register_lazy("cmd_git_import", [], "bzrlib.plugins.git.commands")
 
274
plugin_cmds.register_lazy("cmd_git_object", ["git-objects", "git-cat"],
 
275
    "bzrlib.plugins.git.commands")
 
276
plugin_cmds.register_lazy("cmd_git_refs", [], "bzrlib.plugins.git.commands")
 
277
plugin_cmds.register_lazy("cmd_git_apply", [], "bzrlib.plugins.git.commands")
 
278
 
 
279
def extract_git_foreign_revid(rev):
 
280
    try:
 
281
        foreign_revid = rev.foreign_revid
 
282
    except AttributeError:
 
283
        from bzrlib.plugins.git.mapping import mapping_registry
 
284
        foreign_revid, mapping = \
 
285
            mapping_registry.parse_revision_id(rev.revision_id)
 
286
        return foreign_revid
 
287
    else:
 
288
        from bzrlib.plugins.git.mapping import foreign_vcs_git
 
289
        if rev.mapping.vcs == foreign_vcs_git:
 
290
            return foreign_revid
 
291
        else:
 
292
            raise bzr_errors.InvalidRevisionId(rev.revision_id, None)
 
293
 
 
294
 
 
295
def update_stanza(rev, stanza):
 
296
    mapping = getattr(rev, "mapping", None)
 
297
    try:
 
298
        git_commit = extract_git_foreign_revid(rev)
 
299
    except bzr_errors.InvalidRevisionId:
 
300
        pass
 
301
    else:
 
302
        stanza.add("git-commit", git_commit)
 
303
 
 
304
try:
 
305
    from bzrlib.hooks import install_lazy_named_hook
 
306
except ImportError: # Compatibility with bzr < 2.4
 
307
    from bzrlib.version_info_formats.format_rio import (
 
308
        RioVersionInfoBuilder,
 
309
        )
 
310
    RioVersionInfoBuilder.hooks.install_named_hook('revision', update_stanza,
 
311
        "git commits")
 
312
else:
 
313
    install_lazy_named_hook("bzrlib.version_info_formats.format_rio",
 
314
        "RioVersionInfoBuilder.hooks", "revision", update_stanza,
 
315
        "git commits")
 
316
 
 
317
 
 
318
from bzrlib.transport import transport_server_registry
 
319
transport_server_registry.register_lazy('git',
 
320
    'bzrlib.plugins.git.server',
 
321
    'serve_git',
 
322
    'Git Smart server protocol over TCP. (default port: 9418)')
 
323
 
 
324
 
 
325
from bzrlib.repository import (
 
326
    format_registry as repository_format_registry,
 
327
    network_format_registry as repository_network_format_registry,
 
328
    )
 
329
repository_network_format_registry.register_lazy('git',
 
330
    'bzrlib.plugins.git.repository', 'GitRepositoryFormat')
 
331
 
 
332
try:
 
333
    register_extra_lazy_repository_format = getattr(repository_format_registry,
 
334
        "register_extra_lazy")
 
335
except AttributeError: # bzr < 2.4
 
336
    pass
 
337
else:
 
338
    register_extra_lazy_repository_format('bzrlib.plugins.git.repository',
 
339
        'GitRepositoryFormat')
 
340
 
 
341
from bzrlib.branch import (
 
342
    network_format_registry as branch_network_format_registry,
 
343
    )
 
344
branch_network_format_registry.register_lazy('git',
 
345
    'bzrlib.plugins.git.branch', 'GitBranchFormat')
 
346
 
 
347
try:
 
348
    from bzrlib.branch import (
 
349
        format_registry as branch_format_registry,
 
350
        )
 
351
except ImportError: # bzr < 2.4
 
352
    pass
 
353
else:
 
354
    branch_format_registry.register_extra_lazy(
 
355
        'bzrlib.plugins.git.branch',
 
356
        'GitBranchFormat',
 
357
        )
 
358
 
 
359
try:
 
360
    from bzrlib.workingtree import (
 
361
        format_registry as workingtree_format_registry,
 
362
        )
 
363
except ImportError: # bzr < 2.4
 
364
    pass
 
365
else:
 
366
    workingtree_format_registry.register_extra_lazy(
 
367
        'bzrlib.plugins.git.workingtree',
 
368
        'GitWorkingTreeFormat',
 
369
        )
 
370
 
 
371
controldir_network_format_registry.register_lazy('git',
 
372
    "bzrlib.plugins.git.dir", "GitControlDirFormat")
 
373
 
 
374
send_format_registry.register_lazy('git', 'bzrlib.plugins.git.send',
 
375
                                   'send_git', 'Git am-style diff format')
 
376
 
 
377
topic_registry.register_lazy('git', 'bzrlib.plugins.git.help', 'help_git',
 
378
    'Using Bazaar with Git')
 
379
 
 
380
from bzrlib.diff import format_registry as diff_format_registry
 
381
diff_format_registry.register_lazy('git', 'bzrlib.plugins.git.send',
 
382
    'GitDiffTree', 'Git am-style diff format')
 
383
 
 
384
 
 
385
def update_git_cache(repository, revid):
 
386
    """Update the git cache after a local commit."""
 
387
    if getattr(repository, "_git", None) is not None:
 
388
        return # No need to update cache for git repositories
 
389
 
 
390
    if not repository.control_transport.has("git"):
 
391
        return # No existing cache, don't bother updating
 
392
    try:
 
393
        lazy_check_versions()
 
394
    except bzr_errors.DependencyNotPresent, e:
 
395
        # dulwich is probably missing. silently ignore
 
396
        trace.mutter("not updating git map for %r: %s",
 
397
            repository, e)
 
398
 
 
399
    from bzrlib.plugins.git.object_store import BazaarObjectStore
 
400
    store = BazaarObjectStore(repository)
 
401
    store.lock_write()
 
402
    try:
 
403
        parent_revisions = set(repository.get_parent_map([revid])[revid])
 
404
        missing_revisions = store._missing_revisions(parent_revisions)
 
405
        if not missing_revisions:
 
406
            # Only update if the cache was up to date previously
 
407
            store._update_sha_map_revision(revid)
 
408
    finally:
 
409
        store.unlock()
 
410
 
 
411
 
 
412
def post_commit_update_cache(local_branch, master_branch, old_revno, old_revid,
 
413
        new_revno, new_revid):
 
414
    if local_branch is not None:
 
415
        update_git_cache(local_branch.repository, new_revid)
 
416
    update_git_cache(master_branch.repository, new_revid)
 
417
 
 
418
 
 
419
try:
 
420
    from bzrlib.hooks import install_lazy_named_hook
 
421
except ImportError: # Compatibility with bzr < 2.4
 
422
    pass
 
423
else:
 
424
    install_lazy_named_hook("bzrlib.branch",
 
425
        "Branch.hooks", "post_commit", post_commit_update_cache,
 
426
        "git cache")
 
427
 
 
428
 
 
429
def test_suite():
 
430
    from bzrlib.plugins.git import tests
 
431
    return tests.test_suite()