/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
1
# Copyright (C) 2007 Canonical Ltd
0.200.252 by Jelmer Vernooij
Clarify history, copyright.
2
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18
"""An adapter between a Git Branch and a Bazaar Branch"""
19
0.200.261 by Jelmer Vernooij
More formatting fixes.
20
from dulwich.objects import (
21
    Commit,
22
    Tag,
23
    )
24
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
25
from bzrlib import (
26
    branch,
27
    config,
0.200.327 by Jelmer Vernooij
merge new bzr-foreign.
28
    foreign,
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
29
    repository,
0.200.19 by John Arbash Meinel
More refactoring. Add some direct tests for GitModel.
30
    revision,
0.200.82 by Jelmer Vernooij
Support listing tags.
31
    tag,
0.230.1 by Jelmer Vernooij
Support lightweight checkouts.
32
    transport,
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
33
    )
0.200.261 by Jelmer Vernooij
More formatting fixes.
34
from bzrlib.decorators import (
35
    needs_read_lock,
36
    )
37
from bzrlib.trace import (
0.200.342 by Jelmer Vernooij
Report git sha during pull.
38
    is_quiet,
0.200.261 by Jelmer Vernooij
More formatting fixes.
39
    mutter,
40
    )
41
0.200.386 by Jelmer Vernooij
Move config to a separate file, support BranchConfig.username().
42
from bzrlib.plugins.git.config import (
43
    GitBranchConfig,
44
    )
0.200.278 by Jelmer Vernooij
Update branch head appropriately during dpull.
45
from bzrlib.plugins.git.errors import (
46
    NoSuchRef,
47
    )
0.200.261 by Jelmer Vernooij
More formatting fixes.
48
0.200.388 by Jelmer Vernooij
Support bzr 1.14 as well.
49
try:
50
    from bzrlib.foreign import ForeignBranch
51
except ImportError:
52
    class ForeignBranch(branch.Branch):
53
        def __init__(self, mapping):
54
            self.mapping = mapping
55
            super(ForeignBranch, self).__init__()
56
0.200.261 by Jelmer Vernooij
More formatting fixes.
57
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
58
class GitPullResult(branch.PullResult):
59
60
    def _lookup_revno(self, revid):
61
        assert isinstance(revid, str), "was %r" % revid
62
        # Try in source branch first, it'll be faster
63
        return self.target_branch.revision_id_to_revno(revid)
64
65
    @property
66
    def old_revno(self):
67
        return self._lookup_revno(self.old_revid)
68
69
    @property
70
    def new_revno(self):
71
        return self._lookup_revno(self.new_revid)
72
73
0.200.261 by Jelmer Vernooij
More formatting fixes.
74
class LocalGitTagDict(tag.BasicTags):
75
    """Dictionary with tags in a local repository."""
0.200.82 by Jelmer Vernooij
Support listing tags.
76
0.200.89 by Jelmer Vernooij
Support sprouting branches.
77
    def __init__(self, branch):
78
        self.branch = branch
79
        self.repository = branch.repository
0.200.82 by Jelmer Vernooij
Support listing tags.
80
81
    def get_tag_dict(self):
82
        ret = {}
0.200.180 by Jelmer Vernooij
Simplify tag handling.
83
        for k,v in self.repository._git.tags.iteritems():
0.200.194 by Jelmer Vernooij
Look for commit object in heavyweight tags.
84
            obj = self.repository._git.get_object(v)
85
            while isinstance(obj, Tag):
86
                v = obj.object[1]
87
                obj = self.repository._git.get_object(v)
88
            if not isinstance(obj, Commit):
0.200.261 by Jelmer Vernooij
More formatting fixes.
89
                mutter("Tag %s points at object %r that is not a commit, "
90
                       "ignoring", k, obj)
0.200.194 by Jelmer Vernooij
Look for commit object in heavyweight tags.
91
                continue
0.200.180 by Jelmer Vernooij
Simplify tag handling.
92
            ret[k] = self.branch.mapping.revision_id_foreign_to_bzr(v)
0.200.82 by Jelmer Vernooij
Support listing tags.
93
        return ret
94
0.200.86 by Jelmer Vernooij
Clearer error when setting tags.
95
    def set_tag(self, name, revid):
0.200.181 by Jelmer Vernooij
Support setting tags.
96
        self.repository._git.tags[name] = revid
0.200.86 by Jelmer Vernooij
Clearer error when setting tags.
97
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
98
99
class GitBranchFormat(branch.BranchFormat):
100
0.200.70 by Jelmer Vernooij
Implement GitBranchFormat.get_format_description.
101
    def get_format_description(self):
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
102
        return 'Git Branch'
103
0.200.82 by Jelmer Vernooij
Support listing tags.
104
    def supports_tags(self):
105
        return True
106
0.200.246 by Jelmer Vernooij
Cope with API changes in 1.13.
107
    def make_tags(self, branch):
0.228.3 by Jelmer Vernooij
Fix tags when fetching from remotes.
108
        if getattr(branch.repository, "get_refs", None) is not None:
109
            from bzrlib.plugins.git.remote import RemoteGitTagDict
110
            return RemoteGitTagDict(branch)
0.200.261 by Jelmer Vernooij
More formatting fixes.
111
        else:
112
            return LocalGitTagDict(branch)
0.200.246 by Jelmer Vernooij
Cope with API changes in 1.13.
113
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
114
0.200.388 by Jelmer Vernooij
Support bzr 1.14 as well.
115
class GitBranch(ForeignBranch):
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
116
    """An adapter to git repositories for bzr Branch objects."""
117
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
118
    def __init__(self, bzrdir, repository, name, head, lockfiles):
0.200.82 by Jelmer Vernooij
Support listing tags.
119
        self.repository = repository
0.200.246 by Jelmer Vernooij
Cope with API changes in 1.13.
120
        self._format = GitBranchFormat()
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
121
        self.control_files = lockfiles
0.200.59 by Jelmer Vernooij
Add more tests, fix revision history.
122
        self.bzrdir = bzrdir
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
123
        super(GitBranch, self).__init__(repository.get_mapping())
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
124
        self.name = name
0.200.57 by Jelmer Vernooij
Fix more tests.
125
        self.head = head
0.200.143 by Jelmer Vernooij
Reoncile InterGitRepository objects.
126
        self.base = bzrdir.transport.base
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
127
0.200.293 by Jelmer Vernooij
Fix branch nicks.
128
    def _get_nick(self, local=False, possible_master_transports=None):
129
        """Find the nick name for this branch.
130
131
        :return: Branch nick
132
        """
133
        return self.name
134
0.200.331 by Jelmer Vernooij
Add stub for setting nick function.
135
    def _set_nick(self, nick):
136
        raise NotImplementedError
137
138
    nick = property(_get_nick, _set_nick)
0.200.293 by Jelmer Vernooij
Fix branch nicks.
139
0.200.412 by Jelmer Vernooij
Implement GitBranch.__repr__.
140
    def __repr__(self):
141
        return "%s(%r, %r)" % (self.__class__.__name__, self.repository.base, self.name)
142
0.200.211 by Jelmer Vernooij
Add basic infrastructure for dpush.
143
    def dpull(self, source, stop_revision=None):
144
        if stop_revision is None:
145
            stop_revision = source.last_revision()
146
        # FIXME: Check for diverged branches
0.200.433 by Jelmer Vernooij
dpush tags too.
147
        refs = { "refs/heads/master": stop_revision }
148
        for name, revid in source.tags.get_tag_dict().iteritems():
0.200.434 by Jelmer Vernooij
Only attempt to push revisions that actually exist in the source branch.
149
            if source.repository.has_revision(revid):
150
                refs["refs/tags/%s" % name] = revid
0.200.438 by Jelmer Vernooij
Somewhat fix dpushing to remote repos.
151
        revidmap, new_refs = self.repository.dfetch_refs(source.repository, 
0.200.433 by Jelmer Vernooij
dpush tags too.
152
                refs)
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
153
        if revidmap != {}:
154
            self.generate_revision_history(revidmap[stop_revision])
0.200.438 by Jelmer Vernooij
Somewhat fix dpushing to remote repos.
155
        return revidmap
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
156
157
    def generate_revision_history(self, revid, old_revid=None):
158
        # FIXME: Check that old_revid is in the ancestry of revid
159
        newhead, self.mapping = self.mapping.revision_id_bzr_to_foreign(revid)
160
        self._set_head(newhead)
161
162
    def _set_head(self, head):
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
163
        self.head = head
0.200.278 by Jelmer Vernooij
Update branch head appropriately during dpull.
164
        self.repository._git.set_ref(self.name, self.head)
0.200.211 by Jelmer Vernooij
Add basic infrastructure for dpush.
165
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
166
    def lock_write(self):
167
        self.control_files.lock_write()
168
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
169
    def get_stacked_on_url(self):
170
        # Git doesn't do stacking (yet...)
171
        return None
172
173
    def get_parent(self):
174
        """See Branch.get_parent()."""
0.200.312 by Jelmer Vernooij
Add notes about parent locations.
175
        # FIXME: Set "origin" url from .git/config ?
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
176
        return None
177
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
178
    def set_parent(self, url):
0.200.312 by Jelmer Vernooij
Add notes about parent locations.
179
        # FIXME: Set "origin" url in .git/config ?
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
180
        pass
181
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
182
    def lock_read(self):
183
        self.control_files.lock_read()
184
0.200.432 by Jelmer Vernooij
Support Branch.is_locked, required for loggerhead.
185
    def is_locked(self):
186
        return self.control_files.is_locked()
187
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
188
    def unlock(self):
189
        self.control_files.unlock()
190
191
    def get_physical_lock_status(self):
192
        return False
193
194
 
195
class LocalGitBranch(GitBranch):
0.200.261 by Jelmer Vernooij
More formatting fixes.
196
    """A local Git branch."""
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
197
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
198
    @needs_read_lock
199
    def last_revision(self):
200
        # perhaps should escape this ?
0.200.57 by Jelmer Vernooij
Fix more tests.
201
        if self.head is None:
0.200.19 by John Arbash Meinel
More refactoring. Add some direct tests for GitModel.
202
            return revision.NULL_REVISION
0.200.112 by Jelmer Vernooij
Fix the build.
203
        return self.mapping.revision_id_foreign_to_bzr(self.head)
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
204
0.230.1 by Jelmer Vernooij
Support lightweight checkouts.
205
    def _get_checkout_format(self):
206
        """Return the most suitable metadir for a checkout of this branch.
207
        Weaves are used if this branch's repository uses weaves.
208
        """
209
        format = self.repository.bzrdir.checkout_metadir()
210
        format.set_branch_format(self._format)
211
        return format
212
0.200.261 by Jelmer Vernooij
More formatting fixes.
213
    def create_checkout(self, to_location, revision_id=None, lightweight=False,
214
        accelerator_tree=None, hardlink=False):
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
215
        if lightweight:
0.230.1 by Jelmer Vernooij
Support lightweight checkouts.
216
            t = transport.get_transport(to_location)
217
            t.ensure_base()
218
            format = self._get_checkout_format()
219
            checkout = format.initialize_on_transport(t)
220
            from_branch = branch.BranchReferenceFormat().initialize(checkout, 
221
                self)
222
            tree = checkout.create_workingtree(revision_id,
223
                from_branch=from_branch, hardlink=hardlink)
224
            return tree
225
        else:
226
            return self._create_heavyweight_checkout(to_location, revision_id,
0.200.261 by Jelmer Vernooij
More formatting fixes.
227
            hardlink)
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
228
229
    def _create_heavyweight_checkout(self, to_location, revision_id=None, 
230
                                     hardlink=False):
231
        """Create a new heavyweight checkout of this branch.
232
233
        :param to_location: URL of location to create the new checkout in.
234
        :param revision_id: Revision that should be the tip of the checkout.
235
        :param hardlink: Whether to hardlink
236
        :return: WorkingTree object of checkout.
237
        """
238
        checkout_branch = BzrDir.create_branch_convenience(
239
            to_location, force_new_tree=False, format=get_rich_root_format())
240
        checkout = checkout_branch.bzrdir
241
        checkout_branch.bind(self)
242
        # pull up to the specified revision_id to set the initial 
243
        # branch tip correctly, and seed it with history.
244
        checkout_branch.pull(self, stop_revision=revision_id)
245
        return checkout.create_workingtree(revision_id, hardlink=hardlink)
246
0.200.57 by Jelmer Vernooij
Fix more tests.
247
    def _gen_revision_history(self):
0.200.58 by Jelmer Vernooij
Fix remaining tests.
248
        if self.head is None:
249
            return []
0.200.261 by Jelmer Vernooij
More formatting fixes.
250
        ret = list(self.repository.iter_reverse_revision_history(
251
            self.last_revision()))
0.200.59 by Jelmer Vernooij
Add more tests, fix revision history.
252
        ret.reverse()
0.200.57 by Jelmer Vernooij
Fix more tests.
253
        return ret
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
254
255
    def get_config(self):
256
        return GitBranchConfig(self)
257
258
    def get_push_location(self):
259
        """See Branch.get_push_location."""
260
        push_loc = self.get_config().get_user_option('push_location')
261
        return push_loc
262
263
    def set_push_location(self, location):
264
        """See Branch.set_push_location."""
0.200.19 by John Arbash Meinel
More refactoring. Add some direct tests for GitModel.
265
        self.get_config().set_user_option('push_location', location,
0.217.54 by John Carr
set_user_option breaks - doesnt have a local option in BranchConfig. Follow the bzr.dev syntax instead.
266
                                          store=config.STORE_LOCATION)
0.200.43 by David Allouche
Ultra-experimental support for "bzr pull". No test. No sanity.
267
268
    def supports_tags(self):
0.200.82 by Jelmer Vernooij
Support listing tags.
269
        return True
0.200.96 by Jelmer Vernooij
Fix branch.
270
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
271
0.200.342 by Jelmer Vernooij
Report git sha during pull.
272
class GitBranchPullResult(branch.PullResult):
273
274
    def report(self, to_file):
275
        if not is_quiet():
276
            if self.old_revid == self.new_revid:
277
                to_file.write('No revisions to pull.\n')
278
            else:
279
                to_file.write('Now on revision %d (git sha: %s).\n' % 
280
                        (self.new_revno, self.new_git_head))
281
        self._show_tag_conficts(to_file)
282
283
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
284
class InterGitGenericBranch(branch.InterBranch):
0.200.261 by Jelmer Vernooij
More formatting fixes.
285
    """InterBranch implementation that pulls from Git into bzr."""
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
286
287
    @classmethod
288
    def is_compatible(self, source, target):
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
289
        return (isinstance(source, GitBranch) and 
290
                not isinstance(target, GitBranch))
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
291
292
    def update_revisions(self, stop_revision=None, overwrite=False,
293
        graph=None):
294
        """See InterBranch.update_revisions()."""
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
295
        interrepo = repository.InterRepository.get(self.source.repository, 
296
            self.target.repository)
0.200.342 by Jelmer Vernooij
Report git sha during pull.
297
        self._head = None
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
298
        self._last_revid = None
299
        def determine_wants(heads):
300
            if not self.source.name in heads:
0.200.278 by Jelmer Vernooij
Update branch head appropriately during dpull.
301
                raise NoSuchRef(self.source.name, heads.keys())
0.200.314 by Jelmer Vernooij
Support stop_revision.
302
            if stop_revision is not None:
303
                self._last_revid = stop_revision
0.200.342 by Jelmer Vernooij
Report git sha during pull.
304
                self._head, mapping = self.source.repository.lookup_git_revid(
0.200.316 by Jelmer Vernooij
Fix formatting.
305
                    stop_revision)
0.200.314 by Jelmer Vernooij
Support stop_revision.
306
            else:
0.200.342 by Jelmer Vernooij
Report git sha during pull.
307
                self._head = heads[self.source.name]
0.200.316 by Jelmer Vernooij
Fix formatting.
308
                self._last_revid = \
0.200.342 by Jelmer Vernooij
Report git sha during pull.
309
                    self.source.mapping.revision_id_foreign_to_bzr(self._head)
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
310
            if self.target.repository.has_revision(self._last_revid):
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
311
                return []
0.200.342 by Jelmer Vernooij
Report git sha during pull.
312
            return [self._head]
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
313
        interrepo.fetch_objects(determine_wants, self.source.mapping)
0.200.313 by Jelmer Vernooij
Support overwrite parameter.
314
        if overwrite:
0.200.314 by Jelmer Vernooij
Support stop_revision.
315
            prev_last_revid = None
0.200.313 by Jelmer Vernooij
Support overwrite parameter.
316
        else:
0.200.314 by Jelmer Vernooij
Support stop_revision.
317
            prev_last_revid = self.target.last_revision()
318
        self.target.generate_revision_history(self._last_revid, prev_last_revid)
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
319
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
320
    def pull(self, overwrite=False, stop_revision=None,
321
             possible_transports=None, _hook_master=None, run_hooks=True,
322
             _override_hook_target=None):
323
        """See Branch.pull.
324
325
        :param _hook_master: Private parameter - set the branch to
326
            be supplied as the master to pull hooks.
327
        :param run_hooks: Private parameter - if false, this branch
328
            is being called because it's the master of the primary branch,
329
            so it should not run its hooks.
330
        :param _override_hook_target: Private parameter - set the branch to be
331
            supplied as the target_branch to pull hooks.
332
        """
0.200.342 by Jelmer Vernooij
Report git sha during pull.
333
        result = GitBranchPullResult()
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
334
        result.source_branch = self.source
335
        if _override_hook_target is None:
336
            result.target_branch = self.target
337
        else:
338
            result.target_branch = _override_hook_target
339
        self.source.lock_read()
340
        try:
341
            # We assume that during 'pull' the target repository is closer than
342
            # the source one.
343
            graph = self.target.repository.get_graph(self.source.repository)
344
            result.old_revno, result.old_revid = \
345
                self.target.last_revision_info()
0.200.342 by Jelmer Vernooij
Report git sha during pull.
346
            self.update_revisions(stop_revision, overwrite=overwrite, 
347
                graph=graph)
348
            result.new_git_head = self._head
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
349
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
350
                overwrite)
351
            result.new_revno, result.new_revid = self.target.last_revision_info()
352
            if _hook_master:
353
                result.master_branch = _hook_master
354
                result.local_branch = result.target_branch
355
            else:
356
                result.master_branch = result.target_branch
357
                result.local_branch = None
358
            if run_hooks:
359
                for hook in branch.Branch.hooks['post_pull']:
360
                    hook(result)
361
        finally:
362
            self.source.unlock()
363
        return result
364
365
366
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
367
368
branch.InterBranch.register_optimiser(InterGitGenericBranch)
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
369
370
371
class InterGitRemoteLocalBranch(branch.InterBranch):
372
    """InterBranch implementation that pulls between Git branches."""
373
374
    @classmethod
375
    def is_compatible(self, source, target):
376
        from bzrlib.plugins.git.remote import RemoteGitBranch
377
        return (isinstance(source, RemoteGitBranch) and 
378
                isinstance(target, LocalGitBranch))
379
380
    def pull(self, stop_revision=None, overwrite=False, 
381
        possible_transports=None):
382
        result = GitPullResult()
383
        result.source_branch = self.source
384
        result.target_branch = self.target
385
        interrepo = repository.InterRepository.get(self.source.repository, 
386
            self.target.repository)
387
        result.old_revid = self.target.last_revision()
388
        if stop_revision is None:
389
            stop_revision = self.source.last_revision()
390
        interrepo.fetch(revision_id=stop_revision)
391
        self.target.generate_revision_history(stop_revision, result.old_revid)
392
        result.new_revid = self.target.last_revision()
393
        return result
394
395
396
branch.InterBranch.register_optimiser(InterGitRemoteLocalBranch)