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

  • Committer: Jelmer Vernooij
  • Date: 2020-05-24 00:39:50 UTC
  • mto: This revision was merged to the branch mainline in revision 7504.
  • Revision ID: jelmer@jelmer.uk-20200524003950-bbc545r76vc5yajg
Add github action.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2009-2018 Jelmer Vernooij <jelmer@jelmer.uk>
 
2
# Copyright (C) 2006-2009 Canonical Ltd
2
3
 
3
4
# Authors: Robert Collins <robert.collins@canonical.com>
4
 
#          Jelmer Vernooij <jelmer@samba.org>
 
5
#          Jelmer Vernooij <jelmer@jelmer.uk>
5
6
#          John Carr <john.carr@unrouted.co.uk>
6
7
#
7
8
# This program is free software; you can redistribute it and/or modify
16
17
#
17
18
# You should have received a copy of the GNU General Public License
18
19
# 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
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
21
 
21
22
 
22
23
"""A GIT branch and repository format implementation for bzr."""
24
25
import os
25
26
import sys
26
27
 
27
 
import bzrlib
28
 
import bzrlib.api
29
 
from bzrlib import bzrdir, errors as bzr_errors
30
 
from bzrlib.foreign import foreign_vcs_registry
31
 
from bzrlib.lockable_files import TransportLock
32
 
from bzrlib.transport import register_lazy_transport
33
 
from bzrlib.commands import plugin_cmds
34
 
from bzrlib.trace import warning
35
 
 
36
 
MINIMUM_DULWICH_VERSION = (0, 1, 0)
37
 
COMPATIBLE_BZR_VERSIONS = [(1, 11, 0), (1, 12, 0)]
 
28
dulwich_minimum_version = (0, 19, 11)
 
29
 
 
30
from .. import (  # noqa: F401
 
31
    __version__ as breezy_version,
 
32
    errors as brz_errors,
 
33
    trace,
 
34
    urlutils,
 
35
    version_info,
 
36
    )
 
37
 
 
38
from ..controldir import (
 
39
    ControlDirFormat,
 
40
    Prober,
 
41
    format_registry,
 
42
    network_format_registry as controldir_network_format_registry,
 
43
    )
 
44
 
 
45
from ..transport import (
 
46
    register_lazy_transport,
 
47
    register_transport_proto,
 
48
    transport_server_registry,
 
49
    )
 
50
from ..commands import (
 
51
    plugin_cmds,
 
52
    )
 
53
 
38
54
 
39
55
if getattr(sys, "frozen", None):
40
56
    # allow import additional libs from ./_lib for bzr.exe only
41
 
    sys.path.append(os.path.normpath(os.path.join(os.path.dirname(__file__), '_lib')))
 
57
    sys.path.append(os.path.normpath(
 
58
        os.path.join(os.path.dirname(__file__), '_lib')))
 
59
 
 
60
 
 
61
def import_dulwich():
 
62
    try:
 
63
        from dulwich import __version__ as dulwich_version
 
64
    except ImportError:
 
65
        raise brz_errors.DependencyNotPresent(
 
66
            "dulwich",
 
67
            "bzr-git: Please install dulwich, https://www.dulwich.io/")
 
68
    else:
 
69
        if dulwich_version < dulwich_minimum_version:
 
70
            raise brz_errors.DependencyNotPresent(
 
71
                "dulwich",
 
72
                "bzr-git: Dulwich is too old; at least %d.%d.%d is required" %
 
73
                dulwich_minimum_version)
 
74
 
42
75
 
43
76
_versions_checked = False
 
77
 
 
78
 
44
79
def lazy_check_versions():
45
80
    global _versions_checked
46
81
    if _versions_checked:
47
82
        return
 
83
    import_dulwich()
48
84
    _versions_checked = True
49
 
    try:
50
 
        from dulwich import __version__ as dulwich_version
51
 
    except ImportError:
52
 
        raise ImportError("bzr-git: Please install dulwich, https://launchpad.net/dulwich")
53
 
    else:
54
 
        if dulwich_version < MINIMUM_DULWICH_VERSION:
55
 
            raise ImportError("bzr-git: Dulwich is too old; at least %d.%d.%d is required" % MINIMUM_DULWICH_VERSION)
56
 
 
57
 
bzrlib.api.require_any_api(bzrlib, COMPATIBLE_BZR_VERSIONS)
58
 
 
59
 
bzrdir.format_registry.register_lazy('git', 
60
 
    "bzrlib.plugins.git.dir", "LocalGitBzrDirFormat",
61
 
    help='GIT repository.', native=False, experimental=True,
62
 
    )
63
 
 
64
 
try:
65
 
    from bzrlib.revisionspec import revspec_registry
66
 
    revspec_registry.register_lazy("git:", "bzrlib.plugins.git.revspec", 
67
 
        "RevisionSpec_git")
68
 
except ImportError:
69
 
    lazy_check_versions()
70
 
    from bzrlib.revisionspec import SPEC_TYPES
71
 
    from bzrlib.plugins.git.revspec import RevisionSpec_git
72
 
    SPEC_TYPES.append(RevisionSpec_git)
73
 
 
74
 
class GitBzrDirFormat(bzrdir.BzrDirFormat):
75
 
    _lock_class = TransportLock
76
 
 
77
 
    def is_supported(self):
78
 
        return True
79
 
 
80
 
 
81
 
class LocalGitBzrDirFormat(GitBzrDirFormat):
82
 
    """The .git directory control format."""
83
 
 
84
 
    @classmethod
85
 
    def _known_formats(self):
86
 
        return set([LocalGitBzrDirFormat()])
87
 
 
88
 
    def open(self, transport, _found=None):
89
 
        """Open this directory.
90
 
 
91
 
        """
92
 
        import dulwich as git
93
 
        # we dont grok readonly - git isn't integrated with transport.
94
 
        url = transport.base
95
 
        if url.startswith('readonly+'):
96
 
            url = url[len('readonly+'):]
97
 
 
98
 
        try:
99
 
            gitrepo = git.repo.Repo(transport.local_abspath("."))
100
 
        except bzr_errors.NotLocalUrl:
101
 
            raise bzr_errors.NotBranchError(path=transport.base)
102
 
        from bzrlib.plugins.git.dir import LocalGitDir, GitLockableFiles, GitLock
103
 
        lockfiles = GitLockableFiles(transport, GitLock())
104
 
        return LocalGitDir(transport, lockfiles, gitrepo, self)
105
 
 
106
 
    @classmethod
107
 
    def probe_transport(klass, transport):
108
 
        """Our format is present if the transport ends in '.not/'."""
109
 
        from bzrlib.transport.local import LocalTransport
110
 
 
111
 
        if not isinstance(transport, LocalTransport):
112
 
            raise bzr_errors.NotBranchError(path=transport.base)
113
 
 
114
 
        # This should quickly filter out most things that are not 
115
 
        # git repositories, saving us the trouble from loading dulwich.
116
 
        if not transport.has(".git") and not transport.has("objects"):
117
 
            raise bzr_errors.NotBranchError(path=transport.base)
118
 
 
119
 
        import dulwich as git
120
 
        format = klass()
121
 
        try:
122
 
            format.open(transport)
123
 
            return format
124
 
        except git.errors.NotGitRepository, e:
125
 
            raise bzr_errors.NotBranchError(path=transport.base)
126
 
        raise bzr_errors.NotBranchError(path=transport.base)
127
 
 
128
 
    def get_format_description(self):
129
 
        return "Local Git Repository"
130
 
 
131
 
    def get_format_string(self):
132
 
        return "Local Git Repository"
133
 
 
134
 
    def initialize_on_transport(self, transport):
135
 
        from bzrlib.transport.local import LocalTransport
136
 
 
137
 
        if not isinstance(transport, LocalTransport):
138
 
            raise NotImplementedError(self.initialize, 
139
 
                "Can't create Git Repositories/branches on "
140
 
                "non-local transports")
141
 
 
142
 
        from dulwich.repo import Repo
143
 
        Repo.create(transport.local_abspath(".")) 
144
 
        return self.open(transport)
145
 
 
146
 
    def is_supported(self):
147
 
        return True
148
 
 
149
 
 
150
 
class RemoteGitBzrDirFormat(GitBzrDirFormat):
151
 
    """The .git directory control format."""
152
 
 
153
 
    @classmethod
154
 
    def _known_formats(self):
155
 
        return set([RemoteGitBzrDirFormat()])
156
 
 
157
 
    def open(self, transport, _found=None):
158
 
        """Open this directory.
159
 
 
160
 
        """
161
 
        from bzrlib.plugins.git.remote import RemoteGitDir, GitSmartTransport
162
 
        if not isinstance(transport, GitSmartTransport):
163
 
            raise bzr_errors.NotBranchError(transport.base)
164
 
        # we dont grok readonly - git isn't integrated with transport.
165
 
        url = transport.base
166
 
        if url.startswith('readonly+'):
167
 
            url = url[len('readonly+'):]
168
 
 
169
 
        from bzrlib.plugins.git.dir import GitLockableFiles, GitLock
170
 
        lockfiles = GitLockableFiles(transport, GitLock())
171
 
        return RemoteGitDir(transport, lockfiles, self)
172
 
 
173
 
    @classmethod
174
 
    def probe_transport(klass, transport):
175
 
        """Our format is present if the transport ends in '.not/'."""
 
85
 
 
86
 
 
87
format_registry.register_lazy(
 
88
    'git', __name__ + ".dir", "LocalGitControlDirFormat",
 
89
    help='GIT repository.', native=False, experimental=False)
 
90
 
 
91
format_registry.register_lazy(
 
92
    'git-bare', __name__ + ".dir", "BareLocalGitControlDirFormat",
 
93
    help='Bare GIT repository (no working tree).', native=False,
 
94
    experimental=False)
 
95
 
 
96
from ..revisionspec import (RevisionSpec_dwim, revspec_registry)
 
97
revspec_registry.register_lazy("git:", __name__ + ".revspec",
 
98
                               "RevisionSpec_git")
 
99
RevisionSpec_dwim.append_possible_lazy_revspec(
 
100
    __name__ + ".revspec", "RevisionSpec_git")
 
101
 
 
102
 
 
103
class LocalGitProber(Prober):
 
104
 
 
105
    @classmethod
 
106
    def priority(klass, transport):
 
107
        return 10
 
108
 
 
109
    def probe_transport(self, transport):
 
110
        try:
 
111
            external_url = transport.external_url()
 
112
        except brz_errors.InProcessTransport:
 
113
            raise brz_errors.NotBranchError(path=transport.base)
 
114
        if (external_url.startswith("http:") or
 
115
                external_url.startswith("https:")):
 
116
            # Already handled by RemoteGitProber
 
117
            raise brz_errors.NotBranchError(path=transport.base)
 
118
        if urlutils.split(transport.base)[1] == ".git":
 
119
            raise brz_errors.NotBranchError(path=transport.base)
 
120
        if not transport.has_any(['objects', '.git/objects', '.git']):
 
121
            raise brz_errors.NotBranchError(path=transport.base)
 
122
        lazy_check_versions()
 
123
        from .dir import (
 
124
            BareLocalGitControlDirFormat,
 
125
            LocalGitControlDirFormat,
 
126
            )
 
127
        if transport.has_any(['.git/objects', '.git']):
 
128
            return LocalGitControlDirFormat()
 
129
        if transport.has('info') and transport.has('objects'):
 
130
            return BareLocalGitControlDirFormat()
 
131
        raise brz_errors.NotBranchError(path=transport.base)
 
132
 
 
133
    @classmethod
 
134
    def known_formats(cls):
 
135
        from .dir import (
 
136
            BareLocalGitControlDirFormat,
 
137
            LocalGitControlDirFormat,
 
138
            )
 
139
        return [BareLocalGitControlDirFormat(), LocalGitControlDirFormat()]
 
140
 
 
141
 
 
142
def user_agent_for_github():
 
143
    # GitHub requires we lie. https://github.com/dulwich/dulwich/issues/562
 
144
    return "git/Breezy/%s" % breezy_version
 
145
 
 
146
 
 
147
def is_github_url(url):
 
148
    (scheme, user, password, host, port,
 
149
     path) = urlutils.parse_url(url)
 
150
    return host in ("github.com", "gopkg.in")
 
151
 
 
152
 
 
153
class RemoteGitProber(Prober):
 
154
 
 
155
    @classmethod
 
156
    def priority(klass, transport):
 
157
        # This is a surprisingly good heuristic to determine whether this
 
158
        # prober is more likely to succeed than the Bazaar one.
 
159
        if 'git' in transport.base:
 
160
            return -15
 
161
        return -10
 
162
 
 
163
    def probe_http_transport(self, transport):
 
164
        # This function intentionally doesn't use any of the support code under
 
165
        # breezy.git, since it's called for every repository that's
 
166
        # accessed over HTTP, whether it's Git, Bzr or something else.
 
167
        # Importing Dulwich and the other support code adds unnecessray slowdowns.
 
168
        base_url = urlutils.strip_segment_parameters(transport.external_url())
 
169
        url = urlutils.URL.from_string(base_url)
 
170
        url.user = url.quoted_user = None
 
171
        url.password = url.quoted_password = None
 
172
        host = url.host
 
173
        url = urlutils.join(str(url), "info/refs") + "?service=git-upload-pack"
 
174
        headers = {"Content-Type": "application/x-git-upload-pack-request",
 
175
                   "Accept": "application/x-git-upload-pack-result",
 
176
                   }
 
177
        if is_github_url(url):
 
178
            # GitHub requires we lie.
 
179
            # https://github.com/dulwich/dulwich/issues/562
 
180
            headers["User-Agent"] = user_agent_for_github()
 
181
        elif host == "bazaar.launchpad.net":
 
182
            # Don't attempt Git probes against bazaar.launchpad.net; pad.lv/1744830
 
183
            raise brz_errors.NotBranchError(transport.base)
 
184
        resp = transport.request('GET', url, headers=headers)
 
185
        if resp.status in (404, 405):
 
186
            raise brz_errors.NotBranchError(transport.base)
 
187
        elif resp.status != 200:
 
188
            raise brz_errors.InvalidHttpResponse(
 
189
                url, 'Unable to handle http code %d' % resp.status)
 
190
 
 
191
        ct = resp.getheader("Content-Type")
 
192
        if ct and ct.startswith("application/x-git"):
 
193
            from .remote import RemoteGitControlDirFormat
 
194
            return RemoteGitControlDirFormat()
 
195
        elif not ct:
 
196
            from .dir import (
 
197
                BareLocalGitControlDirFormat,
 
198
                )
 
199
            ret = BareLocalGitControlDirFormat()
 
200
            ret._refs_text = resp.read()
 
201
            return ret
 
202
        raise brz_errors.NotBranchError(transport.base)
 
203
 
 
204
    def probe_transport(self, transport):
 
205
        try:
 
206
            external_url = transport.external_url()
 
207
        except brz_errors.InProcessTransport:
 
208
            raise brz_errors.NotBranchError(path=transport.base)
 
209
 
 
210
        if (external_url.startswith("http:") or
 
211
                external_url.startswith("https:")):
 
212
            return self.probe_http_transport(transport)
 
213
 
 
214
        if (not external_url.startswith("git://") and
 
215
                not external_url.startswith("git+")):
 
216
            raise brz_errors.NotBranchError(transport.base)
 
217
 
176
218
        # little ugly, but works
177
 
        format = klass()
178
 
        from bzrlib.plugins.git.remote import GitSmartTransport
179
 
        if not isinstance(transport, GitSmartTransport):
180
 
            raise bzr_errors.NotBranchError(transport.base)
181
 
        # The only way to know a path exists and contains a valid repository 
182
 
        # is to do a request against it:
183
 
        try:
184
 
            transport.fetch_pack(lambda x: [], None, lambda x: None, 
185
 
                                 lambda x: mutter("git: %s" % x))
186
 
        except errors.git_errors.GitProtocolError:
187
 
            raise bzr_errors.NotBranchError(path=transport.base)
 
219
        from .remote import (
 
220
            GitSmartTransport,
 
221
            RemoteGitControlDirFormat,
 
222
            )
 
223
        if isinstance(transport, GitSmartTransport):
 
224
            return RemoteGitControlDirFormat()
 
225
        raise brz_errors.NotBranchError(path=transport.base)
 
226
 
 
227
    @classmethod
 
228
    def known_formats(cls):
 
229
        from .remote import RemoteGitControlDirFormat
 
230
        return [RemoteGitControlDirFormat()]
 
231
 
 
232
 
 
233
ControlDirFormat.register_prober(LocalGitProber)
 
234
ControlDirFormat.register_prober(RemoteGitProber)
 
235
 
 
236
register_transport_proto(
 
237
    'git://', help="Access using the Git smart server protocol.")
 
238
register_transport_proto(
 
239
    'git+ssh://',
 
240
    help="Access using the Git smart server protocol over SSH.")
 
241
 
 
242
register_lazy_transport("git://", __name__ + '.remote',
 
243
                        'TCPGitSmartTransport')
 
244
register_lazy_transport("git+ssh://", __name__ + '.remote',
 
245
                        'SSHGitSmartTransport')
 
246
 
 
247
 
 
248
plugin_cmds.register_lazy("cmd_git_import", [], __name__ + ".commands")
 
249
plugin_cmds.register_lazy("cmd_git_object", ["git-objects", "git-cat"],
 
250
                          __name__ + ".commands")
 
251
plugin_cmds.register_lazy("cmd_git_refs", [], __name__ + ".commands")
 
252
plugin_cmds.register_lazy("cmd_git_apply", [], __name__ + ".commands")
 
253
plugin_cmds.register_lazy("cmd_git_push_pristine_tar_deltas",
 
254
                          ['git-push-pristine-tar', 'git-push-pristine'],
 
255
                          __name__ + ".commands")
 
256
 
 
257
 
 
258
def extract_git_foreign_revid(rev):
 
259
    try:
 
260
        foreign_revid = rev.foreign_revid
 
261
    except AttributeError:
 
262
        from .mapping import mapping_registry
 
263
        foreign_revid, mapping = \
 
264
            mapping_registry.parse_revision_id(rev.revision_id)
 
265
        return foreign_revid
 
266
    else:
 
267
        from .mapping import foreign_vcs_git
 
268
        if rev.mapping.vcs == foreign_vcs_git:
 
269
            return foreign_revid
188
270
        else:
189
 
            return format
190
 
        raise bzr_errors.NotBranchError(path=transport.base)
191
 
 
192
 
    def get_format_description(self):
193
 
        return "Remote Git Repository"
194
 
 
195
 
    def get_format_string(self):
196
 
        return "Remote Git Repository"
197
 
 
198
 
    def initialize_on_transport(self, transport):
199
 
        raise bzr_errors.UninitializableFormat(self)
200
 
 
201
 
 
202
 
bzrdir.BzrDirFormat.register_control_format(LocalGitBzrDirFormat)
203
 
bzrdir.BzrDirFormat.register_control_format(RemoteGitBzrDirFormat)
204
 
 
205
 
register_lazy_transport("git://", 'bzrlib.plugins.git.remote',
206
 
                        'GitSmartTransport')
207
 
 
208
 
foreign_vcs_registry.register_lazy("git", 
209
 
                        "bzrlib.plugins.git.mapping", 
210
 
                        "foreign_git",
211
 
                        "Stupid content tracker")
212
 
 
213
 
plugin_cmds.register_lazy("cmd_git_serve", [], "bzrlib.plugins.git.commands")
214
 
plugin_cmds.register_lazy("cmd_git_import", [], "bzrlib.plugins.git.commands")
 
271
            raise brz_errors.InvalidRevisionId(rev.revision_id, None)
 
272
 
 
273
 
 
274
def update_stanza(rev, stanza):
 
275
    try:
 
276
        git_commit = extract_git_foreign_revid(rev)
 
277
    except brz_errors.InvalidRevisionId:
 
278
        pass
 
279
    else:
 
280
        stanza.add("git-commit", git_commit)
 
281
 
 
282
 
 
283
from ..hooks import install_lazy_named_hook
 
284
install_lazy_named_hook(
 
285
    "breezy.version_info_formats.format_rio",
 
286
    "RioVersionInfoBuilder.hooks", "revision", update_stanza,
 
287
    "git commits")
 
288
 
 
289
transport_server_registry.register_lazy(
 
290
    'git', __name__ + '.server', 'serve_git',
 
291
    'Git Smart server protocol over TCP. (default port: 9418)')
 
292
 
 
293
transport_server_registry.register_lazy(
 
294
    'git-receive-pack', __name__ + '.server',
 
295
    'serve_git_receive_pack',
 
296
    help='Git Smart server receive pack command. (inetd mode only)')
 
297
transport_server_registry.register_lazy(
 
298
    'git-upload-pack', __name__ + 'git.server',
 
299
    'serve_git_upload_pack',
 
300
    help='Git Smart server upload pack command. (inetd mode only)')
 
301
 
 
302
from ..repository import (
 
303
    format_registry as repository_format_registry,
 
304
    network_format_registry as repository_network_format_registry,
 
305
    )
 
306
repository_network_format_registry.register_lazy(
 
307
    b'git', __name__ + '.repository', 'GitRepositoryFormat')
 
308
 
 
309
register_extra_lazy_repository_format = getattr(repository_format_registry,
 
310
                                                "register_extra_lazy")
 
311
register_extra_lazy_repository_format(__name__ + '.repository',
 
312
                                      'GitRepositoryFormat')
 
313
 
 
314
from ..branch import (
 
315
    network_format_registry as branch_network_format_registry,
 
316
    )
 
317
branch_network_format_registry.register_lazy(
 
318
    b'git', __name__ + '.branch', 'LocalGitBranchFormat')
 
319
 
 
320
 
 
321
from ..branch import (
 
322
    format_registry as branch_format_registry,
 
323
    )
 
324
branch_format_registry.register_extra_lazy(
 
325
    __name__ + '.branch',
 
326
    'LocalGitBranchFormat',
 
327
    )
 
328
branch_format_registry.register_extra_lazy(
 
329
    __name__ + '.remote',
 
330
    'RemoteGitBranchFormat',
 
331
    )
 
332
 
 
333
 
 
334
from ..workingtree import (
 
335
    format_registry as workingtree_format_registry,
 
336
    )
 
337
workingtree_format_registry.register_extra_lazy(
 
338
    __name__ + '.workingtree',
 
339
    'GitWorkingTreeFormat',
 
340
    )
 
341
 
 
342
controldir_network_format_registry.register_lazy(
 
343
    b'git', __name__ + ".dir", "GitControlDirFormat")
 
344
 
 
345
 
 
346
from ..diff import format_registry as diff_format_registry
 
347
diff_format_registry.register_lazy(
 
348
    'git', __name__ + '.send',
 
349
    'GitDiffTree', 'Git am-style diff format')
 
350
 
 
351
from ..send import (
 
352
    format_registry as send_format_registry,
 
353
    )
 
354
send_format_registry.register_lazy('git', __name__ + '.send',
 
355
                                   'send_git', 'Git am-style diff format')
 
356
 
 
357
from ..directory_service import directories
 
358
directories.register_lazy('github:', __name__ + '.directory',
 
359
                          'GitHubDirectory',
 
360
                          'GitHub directory.')
 
361
directories.register_lazy('git@github.com:', __name__ + '.directory',
 
362
                          'GitHubDirectory',
 
363
                          'GitHub directory.')
 
364
 
 
365
from ..help_topics import (
 
366
    topic_registry,
 
367
    )
 
368
topic_registry.register_lazy(
 
369
    'git', __name__ + '.help', 'help_git', 'Using Bazaar with Git')
 
370
 
 
371
from ..foreign import (
 
372
    foreign_vcs_registry,
 
373
    )
 
374
foreign_vcs_registry.register_lazy(
 
375
    "git", __name__ + ".mapping", "foreign_vcs_git", "Stupid content tracker")
 
376
 
 
377
 
 
378
def update_git_cache(repository, revid):
 
379
    """Update the git cache after a local commit."""
 
380
    if getattr(repository, "_git", None) is not None:
 
381
        return  # No need to update cache for git repositories
 
382
 
 
383
    if not repository.control_transport.has("git"):
 
384
        return  # No existing cache, don't bother updating
 
385
    try:
 
386
        lazy_check_versions()
 
387
    except brz_errors.DependencyNotPresent as e:
 
388
        # dulwich is probably missing. silently ignore
 
389
        trace.mutter("not updating git map for %r: %s",
 
390
                     repository, e)
 
391
 
 
392
    from .object_store import BazaarObjectStore
 
393
    store = BazaarObjectStore(repository)
 
394
    with store.lock_write():
 
395
        try:
 
396
            parent_revisions = set(repository.get_parent_map([revid])[revid])
 
397
        except KeyError:
 
398
            # Isn't this a bit odd - how can a revision that was just committed
 
399
            # be missing?
 
400
            return
 
401
        missing_revisions = store._missing_revisions(parent_revisions)
 
402
        if not missing_revisions:
 
403
            store._cache.idmap.start_write_group()
 
404
            try:
 
405
                # Only update if the cache was up to date previously
 
406
                store._update_sha_map_revision(revid)
 
407
            except BaseException:
 
408
                store._cache.idmap.abort_write_group()
 
409
                raise
 
410
            else:
 
411
                store._cache.idmap.commit_write_group()
 
412
 
 
413
 
 
414
def post_commit_update_cache(local_branch, master_branch, old_revno, old_revid,
 
415
                             new_revno, new_revid):
 
416
    if local_branch is not None:
 
417
        update_git_cache(local_branch.repository, new_revid)
 
418
    update_git_cache(master_branch.repository, new_revid)
 
419
 
 
420
 
 
421
def loggerhead_git_hook(branch_app, environ):
 
422
    branch = branch_app.branch
 
423
    config_stack = branch.get_config_stack()
 
424
    if config_stack.get('http_git'):
 
425
        return None
 
426
    from .server import git_http_hook
 
427
    return git_http_hook(branch, environ['REQUEST_METHOD'],
 
428
                         environ['PATH_INFO'])
 
429
 
 
430
 
 
431
install_lazy_named_hook("breezy.branch",
 
432
                        "Branch.hooks", "post_commit",
 
433
                        post_commit_update_cache, "git cache")
 
434
install_lazy_named_hook("breezy.plugins.loggerhead.apps.branch",
 
435
                        "BranchWSGIApp.hooks", "controller",
 
436
                        loggerhead_git_hook, "git support")
 
437
 
 
438
 
 
439
from ..config import (
 
440
    option_registry,
 
441
    Option,
 
442
    bool_from_store,
 
443
    )
 
444
 
 
445
option_registry.register(
 
446
    Option('git.http',
 
447
           default=None, from_unicode=bool_from_store, invalid='warning',
 
448
           help='''\
 
449
Allow fetching of Git packs over HTTP.
 
450
 
 
451
This enables support for fetching Git packs over HTTP in Loggerhead.
 
452
'''))
 
453
 
215
454
 
216
455
def test_suite():
217
 
    from bzrlib.plugins.git import tests
 
456
    from . import tests
218
457
    return tests.test_suite()