/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,
0.200.513 by Jelmer Vernooij
Fix imports.
27
    bzrdir,
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
28
    config,
0.200.446 by Jelmer Vernooij
Support new 'local' argument.
29
    errors,
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
30
    repository,
0.200.19 by John Arbash Meinel
More refactoring. Add some direct tests for GitModel.
31
    revision,
0.200.82 by Jelmer Vernooij
Support listing tags.
32
    tag,
0.230.1 by Jelmer Vernooij
Support lightweight checkouts.
33
    transport,
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
34
    )
0.200.261 by Jelmer Vernooij
More formatting fixes.
35
from bzrlib.decorators import (
36
    needs_read_lock,
37
    )
38
from bzrlib.trace import (
0.200.342 by Jelmer Vernooij
Report git sha during pull.
39
    is_quiet,
0.200.261 by Jelmer Vernooij
More formatting fixes.
40
    mutter,
41
    )
42
0.200.513 by Jelmer Vernooij
Fix imports.
43
from bzrlib.plugins.git import (
44
    get_rich_root_format,
45
    )
0.200.386 by Jelmer Vernooij
Move config to a separate file, support BranchConfig.username().
46
from bzrlib.plugins.git.config import (
47
    GitBranchConfig,
48
    )
0.200.278 by Jelmer Vernooij
Update branch head appropriately during dpull.
49
from bzrlib.plugins.git.errors import (
0.200.472 by Jelmer Vernooij
Fix printing error when user attempts to push into git.
50
    NoPushSupport,
0.200.278 by Jelmer Vernooij
Update branch head appropriately during dpull.
51
    NoSuchRef,
52
    )
0.200.261 by Jelmer Vernooij
More formatting fixes.
53
0.238.5 by Jelmer Vernooij
Remove old backwards compatibility code.
54
from bzrlib.foreign import ForeignBranch
0.200.388 by Jelmer Vernooij
Support bzr 1.14 as well.
55
0.200.261 by Jelmer Vernooij
More formatting fixes.
56
0.200.648 by Jelmer Vernooij
Fix tag handling when encountering packed refs.
57
def extract_tags(refs):
0.200.462 by Jelmer Vernooij
Import tags when pulling.
58
    ret = {}
59
    for k,v in refs.iteritems():
60
        if k.startswith("refs/tags/") and not k.endswith("^{}"):
61
            v = refs.get(k+"^{}", v)
0.200.648 by Jelmer Vernooij
Fix tag handling when encountering packed refs.
62
            ret[k[len("refs/tags/"):]] = v
0.200.462 by Jelmer Vernooij
Import tags when pulling.
63
    return ret
64
65
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
66
class GitPullResult(branch.PullResult):
67
68
    def _lookup_revno(self, revid):
69
        assert isinstance(revid, str), "was %r" % revid
70
        # Try in source branch first, it'll be faster
71
        return self.target_branch.revision_id_to_revno(revid)
72
73
    @property
74
    def old_revno(self):
75
        return self._lookup_revno(self.old_revid)
76
77
    @property
78
    def new_revno(self):
79
        return self._lookup_revno(self.new_revid)
80
81
0.200.261 by Jelmer Vernooij
More formatting fixes.
82
class LocalGitTagDict(tag.BasicTags):
83
    """Dictionary with tags in a local repository."""
0.200.82 by Jelmer Vernooij
Support listing tags.
84
0.200.89 by Jelmer Vernooij
Support sprouting branches.
85
    def __init__(self, branch):
86
        self.branch = branch
87
        self.repository = branch.repository
0.200.82 by Jelmer Vernooij
Support listing tags.
88
89
    def get_tag_dict(self):
90
        ret = {}
0.200.648 by Jelmer Vernooij
Fix tag handling when encountering packed refs.
91
        for k,v in extract_tags(self.repository._git.get_refs()).iteritems():
0.200.609 by Jelmer Vernooij
Cope with tags pointing at nonexisting objects.
92
            try:
0.200.647 by Jelmer Vernooij
Fix use of packed refs.
93
                obj = self.repository._git[v]
0.200.609 by Jelmer Vernooij
Cope with tags pointing at nonexisting objects.
94
            except KeyError:
95
                mutter("Tag %s points at unknown object %s, ignoring", v, obj)
96
                continue
0.200.194 by Jelmer Vernooij
Look for commit object in heavyweight tags.
97
            while isinstance(obj, Tag):
98
                v = obj.object[1]
0.200.647 by Jelmer Vernooij
Fix use of packed refs.
99
                obj = self.repository._git[v]
0.200.194 by Jelmer Vernooij
Look for commit object in heavyweight tags.
100
            if not isinstance(obj, Commit):
0.200.261 by Jelmer Vernooij
More formatting fixes.
101
                mutter("Tag %s points at object %r that is not a commit, "
102
                       "ignoring", k, obj)
0.200.194 by Jelmer Vernooij
Look for commit object in heavyweight tags.
103
                continue
0.200.180 by Jelmer Vernooij
Simplify tag handling.
104
            ret[k] = self.branch.mapping.revision_id_foreign_to_bzr(v)
0.200.82 by Jelmer Vernooij
Support listing tags.
105
        return ret
106
0.200.711 by Jelmer Vernooij
Support merging tags to a local Git repository.
107
    def _set_tag_dict(self, to_dict):
108
        extra = set(self.repository._git.get_refs().keys())
109
        for k, revid in to_dict.iteritems():
110
            name = "refs/tags/%s" % k
111
            if name in extra:
112
                extra.remove(name)
113
            self.set_tag(k, revid)
114
        for name in extra:
115
            if name.startswith("refs/tags/"):
116
                del self.repository._git[name]
117
        
0.200.86 by Jelmer Vernooij
Clearer error when setting tags.
118
    def set_tag(self, name, revid):
0.200.480 by Jelmer Vernooij
Cope with API changes in Dulwich.
119
        self.repository._git.refs["refs/tags/%s" % name], _ = \
0.200.462 by Jelmer Vernooij
Import tags when pulling.
120
            self.branch.mapping.revision_id_bzr_to_foreign(revid)
0.200.86 by Jelmer Vernooij
Clearer error when setting tags.
121
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
122
0.239.1 by Jelmer Vernooij
Avoid re-connecting to fetch tags we already know.
123
class DictTagDict(LocalGitTagDict):
124
125
126
    def __init__(self, branch, tags):
127
        super(DictTagDict, self).__init__(branch)
128
        self._tags = tags
129
130
    def get_tag_dict(self):
131
        return self._tags
132
133
134
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
135
class GitBranchFormat(branch.BranchFormat):
136
0.200.70 by Jelmer Vernooij
Implement GitBranchFormat.get_format_description.
137
    def get_format_description(self):
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
138
        return 'Git Branch'
139
0.243.1 by Jelmer Vernooij
Use foreign branch testing infrastructure.
140
    def network_name(self):
141
        return "git"
142
0.200.82 by Jelmer Vernooij
Support listing tags.
143
    def supports_tags(self):
144
        return True
145
0.243.1 by Jelmer Vernooij
Use foreign branch testing infrastructure.
146
    def get_foreign_tests_branch_factory(self):
147
        from bzrlib.plugins.git.tests.test_branch import ForeignTestsBranchFactory
148
        return ForeignTestsBranchFactory()
149
0.200.246 by Jelmer Vernooij
Cope with API changes in 1.13.
150
    def make_tags(self, branch):
0.228.3 by Jelmer Vernooij
Fix tags when fetching from remotes.
151
        if getattr(branch.repository, "get_refs", None) is not None:
152
            from bzrlib.plugins.git.remote import RemoteGitTagDict
153
            return RemoteGitTagDict(branch)
0.200.261 by Jelmer Vernooij
More formatting fixes.
154
        else:
155
            return LocalGitTagDict(branch)
0.200.246 by Jelmer Vernooij
Cope with API changes in 1.13.
156
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
157
0.200.388 by Jelmer Vernooij
Support bzr 1.14 as well.
158
class GitBranch(ForeignBranch):
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
159
    """An adapter to git repositories for bzr Branch objects."""
160
0.239.1 by Jelmer Vernooij
Avoid re-connecting to fetch tags we already know.
161
    def __init__(self, bzrdir, repository, name, lockfiles, tagsdict=None):
0.200.82 by Jelmer Vernooij
Support listing tags.
162
        self.repository = repository
0.200.246 by Jelmer Vernooij
Cope with API changes in 1.13.
163
        self._format = GitBranchFormat()
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
164
        self.control_files = lockfiles
0.200.59 by Jelmer Vernooij
Add more tests, fix revision history.
165
        self.bzrdir = bzrdir
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
166
        super(GitBranch, self).__init__(repository.get_mapping())
0.239.1 by Jelmer Vernooij
Avoid re-connecting to fetch tags we already know.
167
        if tagsdict is not None:
168
            self.tags = DictTagDict(self, tagsdict)
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
169
        self.name = name
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
170
        self._head = None
0.200.630 by Jelmer Vernooij
Fix base url of Git branches - use the working tree path rather than the control directory path.
171
        self.base = bzrdir.root_transport.base
0.200.722 by Jelmer Vernooij
Implement GitDir.list_branches() and support name argument to open_branch.
172
        if self.name != "HEAD":
173
            self.base += ",%s" % self.name
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
174
0.239.8 by Jelmer Vernooij
Support checkouts.
175
    def _get_checkout_format(self):
176
        """Return the most suitable metadir for a checkout of this branch.
177
        Weaves are used if this branch's repository uses weaves.
178
        """
179
        return get_rich_root_format()
180
0.238.3 by Jelmer Vernooij
Remove svn references, prefer git send format when submitting changes against a git branch.
181
    def get_child_submit_format(self):
182
        """Return the preferred format of submissions to this branch."""
183
        ret = self.get_config().get_user_option("child_submit_format")
184
        if ret is not None:
185
            return ret
186
        return "git"
187
0.200.293 by Jelmer Vernooij
Fix branch nicks.
188
    def _get_nick(self, local=False, possible_master_transports=None):
189
        """Find the nick name for this branch.
190
191
        :return: Branch nick
192
        """
193
        return self.name
194
0.200.331 by Jelmer Vernooij
Add stub for setting nick function.
195
    def _set_nick(self, nick):
196
        raise NotImplementedError
197
198
    nick = property(_get_nick, _set_nick)
0.200.293 by Jelmer Vernooij
Fix branch nicks.
199
0.200.412 by Jelmer Vernooij
Implement GitBranch.__repr__.
200
    def __repr__(self):
201
        return "%s(%r, %r)" % (self.__class__.__name__, self.repository.base, self.name)
202
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
203
    def generate_revision_history(self, revid, old_revid=None):
204
        # FIXME: Check that old_revid is in the ancestry of revid
205
        newhead, self.mapping = self.mapping.revision_id_bzr_to_foreign(revid)
206
        self._set_head(newhead)
207
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
208
    def lock_write(self):
209
        self.control_files.lock_write()
210
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
211
    def get_stacked_on_url(self):
212
        # Git doesn't do stacking (yet...)
0.200.631 by Jelmer Vernooij
Raise proper exception in Branch.get_stacked_on_url().
213
        raise errors.UnstackableBranchFormat(self._format, self.base)
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
214
215
    def get_parent(self):
216
        """See Branch.get_parent()."""
0.200.312 by Jelmer Vernooij
Add notes about parent locations.
217
        # 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.
218
        return None
219
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
220
    def set_parent(self, url):
0.200.312 by Jelmer Vernooij
Add notes about parent locations.
221
        # FIXME: Set "origin" url in .git/config ?
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
222
        pass
223
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
224
    def lock_read(self):
225
        self.control_files.lock_read()
226
0.200.432 by Jelmer Vernooij
Support Branch.is_locked, required for loggerhead.
227
    def is_locked(self):
228
        return self.control_files.is_locked()
229
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
230
    def unlock(self):
231
        self.control_files.unlock()
232
233
    def get_physical_lock_status(self):
234
        return False
235
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
236
    @needs_read_lock
237
    def last_revision(self):
238
        # perhaps should escape this ?
0.200.57 by Jelmer Vernooij
Fix more tests.
239
        if self.head is None:
0.200.19 by John Arbash Meinel
More refactoring. Add some direct tests for GitModel.
240
            return revision.NULL_REVISION
0.200.112 by Jelmer Vernooij
Fix the build.
241
        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.
242
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
243
    def _basic_push(self, target, overwrite=False, stop_revision=None):
244
        return branch.InterBranch.get(self, target)._basic_push(
245
            overwrite, stop_revision)
246
0.200.692 by Jelmer Vernooij
Refuse pulling into non-rich-root branches rather than erroring out with an AttributeError.
247
0.200.465 by Jelmer Vernooij
Use dulwich standard functionality for finding missing revisions.
248
class LocalGitBranch(GitBranch):
249
    """A local Git branch."""
250
0.200.763 by Jelmer Vernooij
Provide proper colocated branch support.
251
    def __init__(self, bzrdir, repository, name, lockfiles, tagsdict=None):
252
        super(LocalGitBranch, self).__init__(bzrdir, repository, name, 
253
              lockfiles, tagsdict)
0.200.769 by Jelmer Vernooij
Cope with open_branch() actually checking whether there is a branch present.
254
        if not name in repository._git.get_refs().keys():
0.200.763 by Jelmer Vernooij
Provide proper colocated branch support.
255
            raise errors.NotBranchError(self.base)
256
0.200.261 by Jelmer Vernooij
More formatting fixes.
257
    def create_checkout(self, to_location, revision_id=None, lightweight=False,
258
        accelerator_tree=None, hardlink=False):
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
259
        if lightweight:
0.230.1 by Jelmer Vernooij
Support lightweight checkouts.
260
            t = transport.get_transport(to_location)
261
            t.ensure_base()
262
            format = self._get_checkout_format()
263
            checkout = format.initialize_on_transport(t)
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
264
            from_branch = branch.BranchReferenceFormat().initialize(checkout,
0.230.1 by Jelmer Vernooij
Support lightweight checkouts.
265
                self)
266
            tree = checkout.create_workingtree(revision_id,
267
                from_branch=from_branch, hardlink=hardlink)
268
            return tree
269
        else:
270
            return self._create_heavyweight_checkout(to_location, revision_id,
0.200.261 by Jelmer Vernooij
More formatting fixes.
271
            hardlink)
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
272
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
273
    def _create_heavyweight_checkout(self, to_location, revision_id=None,
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
274
                                     hardlink=False):
275
        """Create a new heavyweight checkout of this branch.
276
277
        :param to_location: URL of location to create the new checkout in.
278
        :param revision_id: Revision that should be the tip of the checkout.
279
        :param hardlink: Whether to hardlink
280
        :return: WorkingTree object of checkout.
281
        """
0.200.513 by Jelmer Vernooij
Fix imports.
282
        checkout_branch = bzrdir.BzrDir.create_branch_convenience(
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
283
            to_location, force_new_tree=False, format=get_rich_root_format())
284
        checkout = checkout_branch.bzrdir
285
        checkout_branch.bind(self)
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
286
        # pull up to the specified revision_id to set the initial
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
287
        # branch tip correctly, and seed it with history.
288
        checkout_branch.pull(self, stop_revision=revision_id)
289
        return checkout.create_workingtree(revision_id, hardlink=hardlink)
290
0.200.57 by Jelmer Vernooij
Fix more tests.
291
    def _gen_revision_history(self):
0.200.58 by Jelmer Vernooij
Fix remaining tests.
292
        if self.head is None:
293
            return []
0.200.261 by Jelmer Vernooij
More formatting fixes.
294
        ret = list(self.repository.iter_reverse_revision_history(
295
            self.last_revision()))
0.200.59 by Jelmer Vernooij
Add more tests, fix revision history.
296
        ret.reverse()
0.200.57 by Jelmer Vernooij
Fix more tests.
297
        return ret
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
298
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
299
    def _get_head(self):
0.200.480 by Jelmer Vernooij
Cope with API changes in Dulwich.
300
        try:
301
            return self.repository._git.ref(self.name)
302
        except KeyError:
303
            return None
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
304
0.200.507 by Jelmer Vernooij
Implement set_last_revision{_info,}.
305
    def set_last_revision_info(self, revno, revid):
306
        self.set_last_revision(revid)
307
308
    def set_last_revision(self, revid):
0.200.523 by Jelmer Vernooij
Fix undefined error.
309
        (newhead, self.mapping) = self.mapping.revision_id_bzr_to_foreign(
0.200.507 by Jelmer Vernooij
Implement set_last_revision{_info,}.
310
                revid)
0.200.523 by Jelmer Vernooij
Fix undefined error.
311
        self.head = newhead
0.200.507 by Jelmer Vernooij
Implement set_last_revision{_info,}.
312
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
313
    def _set_head(self, value):
314
        self._head = value
0.200.480 by Jelmer Vernooij
Cope with API changes in Dulwich.
315
        self.repository._git.refs[self.name] = self._head
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
316
        self._clear_cached_state()
317
318
    head = property(_get_head, _set_head)
319
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
320
    def get_config(self):
321
        return GitBranchConfig(self)
322
323
    def get_push_location(self):
324
        """See Branch.get_push_location."""
325
        push_loc = self.get_config().get_user_option('push_location')
326
        return push_loc
327
328
    def set_push_location(self, location):
329
        """See Branch.set_push_location."""
0.200.19 by John Arbash Meinel
More refactoring. Add some direct tests for GitModel.
330
        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.
331
                                          store=config.STORE_LOCATION)
0.200.43 by David Allouche
Ultra-experimental support for "bzr pull". No test. No sanity.
332
333
    def supports_tags(self):
0.200.82 by Jelmer Vernooij
Support listing tags.
334
        return True
0.200.96 by Jelmer Vernooij
Fix branch.
335
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
336
0.200.342 by Jelmer Vernooij
Report git sha during pull.
337
class GitBranchPullResult(branch.PullResult):
338
339
    def report(self, to_file):
340
        if not is_quiet():
341
            if self.old_revid == self.new_revid:
342
                to_file.write('No revisions to pull.\n')
0.200.728 by Jelmer Vernooij
Fix pulling when all revisions are already in the repo.
343
            elif self.new_git_head is not None:
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
344
                to_file.write('Now on revision %d (git sha: %s).\n' %
0.200.342 by Jelmer Vernooij
Report git sha during pull.
345
                        (self.new_revno, self.new_git_head))
0.200.728 by Jelmer Vernooij
Fix pulling when all revisions are already in the repo.
346
            else:
347
                to_file.write('Now on revision %d.\n' % (self.new_revno,))
0.200.342 by Jelmer Vernooij
Report git sha during pull.
348
        self._show_tag_conficts(to_file)
349
350
0.200.504 by Jelmer Vernooij
Lazily find revno's for git branches.
351
class GitBranchPushResult(branch.BranchPushResult):
352
353
    def _lookup_revno(self, revid):
354
        assert isinstance(revid, str), "was %r" % revid
355
        # Try in source branch first, it'll be faster
356
        try:
357
            return self.source_branch.revision_id_to_revno(revid)
0.200.523 by Jelmer Vernooij
Fix undefined error.
358
        except errors.NoSuchRevision:
0.200.504 by Jelmer Vernooij
Lazily find revno's for git branches.
359
            # FIXME: Check using graph.find_distance_to_null() ?
360
            return self.target_branch.revision_id_to_revno(revid)
361
362
    @property
363
    def old_revno(self):
364
        return self._lookup_revno(self.old_revid)
365
366
    @property
367
    def new_revno(self):
368
        return self._lookup_revno(self.new_revid)
369
370
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
371
class InterFromGitBranch(branch.GenericInterBranch):
0.200.261 by Jelmer Vernooij
More formatting fixes.
372
    """InterBranch implementation that pulls from Git into bzr."""
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
373
374
    @classmethod
0.200.692 by Jelmer Vernooij
Refuse pulling into non-rich-root branches rather than erroring out with an AttributeError.
375
    def _get_interrepo(self, source, target):
376
        return repository.InterRepository.get(source.repository,
377
            target.repository)
378
379
    @classmethod
380
    def is_compatible(cls, source, target):
381
        return (isinstance(source, GitBranch) and
382
                not isinstance(target, GitBranch) and
383
                (getattr(cls._get_interrepo(source, target), "fetch_objects", None) is not None))
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
384
0.247.7 by Michael Hudson
preserve the interface of update_revisions()
385
    def _update_revisions(self, stop_revision=None, overwrite=False,
0.247.2 by Michael Hudson
this works for my tests, but i'm pretty sure it's wrong in general
386
        graph=None, limit=None):
0.247.7 by Michael Hudson
preserve the interface of update_revisions()
387
        """Like InterBranch.update_revisions(), but with additions.
388
389
        Compared to the `update_revisions()` below, this function takes a
390
        `limit` argument that limits how many git commits will be converted
391
        and returns the new git head.
392
        """
0.200.692 by Jelmer Vernooij
Refuse pulling into non-rich-root branches rather than erroring out with an AttributeError.
393
        interrepo = self._get_interrepo(self.source, self.target)
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
394
        def determine_wants(heads):
395
            if not self.source.name in heads:
0.200.278 by Jelmer Vernooij
Update branch head appropriately during dpull.
396
                raise NoSuchRef(self.source.name, heads.keys())
0.200.314 by Jelmer Vernooij
Support stop_revision.
397
            if stop_revision is not None:
0.200.728 by Jelmer Vernooij
Fix pulling when all revisions are already in the repo.
398
                self._last_revid = stop_revision
0.247.6 by Michael Hudson
away with underscore prefixed local variables
399
                head, mapping = self.source.repository.lookup_bzr_revision_id(
0.200.316 by Jelmer Vernooij
Fix formatting.
400
                    stop_revision)
0.200.314 by Jelmer Vernooij
Support stop_revision.
401
            else:
0.247.6 by Michael Hudson
away with underscore prefixed local variables
402
                head = heads[self.source.name]
0.200.728 by Jelmer Vernooij
Fix pulling when all revisions are already in the repo.
403
                self._last_revid = self.source.mapping.revision_id_foreign_to_bzr(
0.247.6 by Michael Hudson
away with underscore prefixed local variables
404
                    head)
0.200.728 by Jelmer Vernooij
Fix pulling when all revisions are already in the repo.
405
            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.
406
                return []
0.247.6 by Michael Hudson
away with underscore prefixed local variables
407
            return [head]
0.248.5 by Jelmer Vernooij
Reformatting, fix dpush.
408
        pack_hint, head = interrepo.fetch_objects(
0.247.2 by Michael Hudson
this works for my tests, but i'm pretty sure it's wrong in general
409
            determine_wants, self.source.mapping, limit=limit)
0.248.5 by Jelmer Vernooij
Reformatting, fix dpush.
410
        if pack_hint is not None and self.target.repository._format.pack_compresses:
411
            self.target.repository.pack(hint=pack_hint)
0.200.728 by Jelmer Vernooij
Fix pulling when all revisions are already in the repo.
412
        if head is not None:
413
            self._last_revid = self.source.mapping.revision_id_foreign_to_bzr(head)
0.200.313 by Jelmer Vernooij
Support overwrite parameter.
414
        if overwrite:
0.200.314 by Jelmer Vernooij
Support stop_revision.
415
            prev_last_revid = None
0.200.313 by Jelmer Vernooij
Support overwrite parameter.
416
        else:
0.200.314 by Jelmer Vernooij
Support stop_revision.
417
            prev_last_revid = self.target.last_revision()
0.248.5 by Jelmer Vernooij
Reformatting, fix dpush.
418
        self.target.generate_revision_history(self._last_revid,
419
            prev_last_revid)
0.247.6 by Michael Hudson
away with underscore prefixed local variables
420
        return head
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
421
0.200.726 by Jelmer Vernooij
Factor out conversion of branch names to refs.
422
    def update_revisions(self, stop_revision=None, overwrite=False,
423
                         graph=None):
0.247.7 by Michael Hudson
preserve the interface of update_revisions()
424
        """See InterBranch.update_revisions()."""
425
        self._update_revisions(stop_revision, overwrite, graph)
426
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
427
    def pull(self, overwrite=False, stop_revision=None,
428
             possible_transports=None, _hook_master=None, run_hooks=True,
0.247.2 by Michael Hudson
this works for my tests, but i'm pretty sure it's wrong in general
429
             _override_hook_target=None, local=False, limit=None):
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
430
        """See Branch.pull.
431
432
        :param _hook_master: Private parameter - set the branch to
433
            be supplied as the master to pull hooks.
434
        :param run_hooks: Private parameter - if false, this branch
435
            is being called because it's the master of the primary branch,
436
            so it should not run its hooks.
437
        :param _override_hook_target: Private parameter - set the branch to be
438
            supplied as the target_branch to pull hooks.
0.247.2 by Michael Hudson
this works for my tests, but i'm pretty sure it's wrong in general
439
        :param limit: Only import this many revisons.  `None`, the default,
440
            means import all revisions.
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
441
        """
0.200.446 by Jelmer Vernooij
Support new 'local' argument.
442
        # This type of branch can't be bound.
443
        if local:
444
            raise errors.LocalRequiresBoundBranch()
0.200.342 by Jelmer Vernooij
Report git sha during pull.
445
        result = GitBranchPullResult()
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
446
        result.source_branch = self.source
447
        if _override_hook_target is None:
448
            result.target_branch = self.target
449
        else:
450
            result.target_branch = _override_hook_target
451
        self.source.lock_read()
452
        try:
453
            # We assume that during 'pull' the target repository is closer than
454
            # the source one.
455
            graph = self.target.repository.get_graph(self.source.repository)
0.200.726 by Jelmer Vernooij
Factor out conversion of branch names to refs.
456
            (result.old_revno, result.old_revid) = \
457
                self.target.last_revision_info()
0.247.7 by Michael Hudson
preserve the interface of update_revisions()
458
            result.new_git_head = self._update_revisions(
0.247.6 by Michael Hudson
away with underscore prefixed local variables
459
                stop_revision, overwrite=overwrite, graph=graph, limit=limit)
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
460
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
461
                overwrite)
0.200.726 by Jelmer Vernooij
Factor out conversion of branch names to refs.
462
            (result.new_revno, result.new_revid) = \
463
                self.target.last_revision_info()
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
464
            if _hook_master:
465
                result.master_branch = _hook_master
466
                result.local_branch = result.target_branch
467
            else:
468
                result.master_branch = result.target_branch
469
                result.local_branch = None
470
            if run_hooks:
471
                for hook in branch.Branch.hooks['post_pull']:
472
                    hook(result)
473
        finally:
474
            self.source.unlock()
475
        return result
476
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
477
    def _basic_push(self, overwrite=False, stop_revision=None):
478
        result = branch.BranchPushResult()
479
        result.source_branch = self.source
480
        result.target_branch = self.target
0.200.505 by Jelmer Vernooij
Remove duplicate code.
481
        graph = self.target.repository.get_graph(self.source.repository)
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
482
        result.old_revno, result.old_revid = self.target.last_revision_info()
0.247.8 by Michael Hudson
incredibly minor tweak
483
        result.new_git_head = self._update_revisions(
0.247.3 by Michael Hudson
oh, so it wasn't (particularly) wrong, but it was a bit obscure
484
            stop_revision, overwrite=overwrite, graph=graph)
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
485
        result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
486
            overwrite)
487
        result.new_revno, result.new_revid = self.target.last_revision_info()
488
        return result
489
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
490
0.200.512 by Jelmer Vernooij
Support pushing git->git.
491
class InterGitBranch(branch.GenericInterBranch):
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
492
    """InterBranch implementation that pulls between Git branches."""
493
0.200.512 by Jelmer Vernooij
Support pushing git->git.
494
495
class InterGitLocalRemoteBranch(InterGitBranch):
496
    """InterBranch that copies from a local to a remote git branch."""
497
498
    @classmethod
499
    def is_compatible(self, source, target):
500
        from bzrlib.plugins.git.remote import RemoteGitBranch
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
501
        return (isinstance(source, LocalGitBranch) and
0.200.512 by Jelmer Vernooij
Support pushing git->git.
502
                isinstance(target, RemoteGitBranch))
503
504
    def _basic_push(self, overwrite=False, stop_revision=None):
505
        result = GitBranchPushResult()
506
        result.source_branch = self.source
507
        result.target_branch = self.target
508
        if stop_revision is None:
509
            stop_revision = self.source.last_revision()
510
        # FIXME: Check for diverged branches
511
        def get_changed_refs(old_refs):
0.200.544 by Jelmer Vernooij
Support pushing from git -> empty git repo.
512
            result.old_revid = self.target.mapping.revision_id_foreign_to_bzr(old_refs.get("refs/heads/master", "0" * 40))
0.200.650 by Jelmer Vernooij
Use standard names for lookup functions.
513
            refs = { "refs/heads/master": self.source.repository.lookup_bzr_revision_id(stop_revision)[0] }
0.200.512 by Jelmer Vernooij
Support pushing git->git.
514
            result.new_revid = stop_revision
515
            for name, sha in self.source.repository._git.refs.as_dict("refs/tags").iteritems():
516
                refs["refs/tags/%s" % name] = sha
517
            return refs
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
518
        self.target.repository.send_pack(get_changed_refs,
0.200.726 by Jelmer Vernooij
Factor out conversion of branch names to refs.
519
            self.source.repository._git.object_store.generate_pack_contents)
0.200.512 by Jelmer Vernooij
Support pushing git->git.
520
        return result
521
522
523
class InterGitRemoteLocalBranch(InterGitBranch):
524
    """InterBranch that copies from a remote to a local git branch."""
525
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
526
    @classmethod
527
    def is_compatible(self, source, target):
528
        from bzrlib.plugins.git.remote import RemoteGitBranch
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
529
        return (isinstance(source, RemoteGitBranch) and
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
530
                isinstance(target, LocalGitBranch))
531
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
532
    def _basic_push(self, overwrite=False, stop_revision=None):
533
        result = branch.BranchPushResult()
534
        result.source_branch = self.source
535
        result.target_branch = self.target
536
        result.old_revid = self.target.last_revision()
537
        refs, stop_revision = self.update_refs(stop_revision)
538
        self.target.generate_revision_history(stop_revision, result.old_revid)
539
        self.update_tags(refs)
0.200.505 by Jelmer Vernooij
Remove duplicate code.
540
        result.new_revid = self.target.last_revision()
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
541
        return result
542
543
    def update_tags(self, refs):
0.200.648 by Jelmer Vernooij
Fix tag handling when encountering packed refs.
544
        for name, v in extract_tags(refs).iteritems():
545
            revid = self.target.mapping.revision_id_foreign_to_bzr(v)
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
546
            self.target.tags.set_tag(name, revid)
547
548
    def update_refs(self, stop_revision=None):
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
549
        interrepo = repository.InterRepository.get(self.source.repository,
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
550
            self.target.repository)
551
        if stop_revision is None:
552
            refs = interrepo.fetch_refs(branches=["HEAD"])
553
            stop_revision = self.target.mapping.revision_id_foreign_to_bzr(refs["HEAD"])
554
        else:
555
            refs = interrepo.fetch_refs(revision_id=stop_revision)
556
        return refs, stop_revision
557
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
558
    def pull(self, stop_revision=None, overwrite=False,
0.200.732 by Jelmer Vernooij
Support run_hooks argument to InterGitRemoteLocalBranch.pull().
559
        possible_transports=None, run_hooks=True,local=False):
0.200.446 by Jelmer Vernooij
Support new 'local' argument.
560
        # This type of branch can't be bound.
561
        if local:
562
            raise errors.LocalRequiresBoundBranch()
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
563
        result = GitPullResult()
564
        result.source_branch = self.source
565
        result.target_branch = self.target
566
        result.old_revid = self.target.last_revision()
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
567
        refs, stop_revision = self.update_refs(stop_revision)
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
568
        self.target.generate_revision_history(stop_revision, result.old_revid)
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
569
        self.update_tags(refs)
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
570
        result.new_revid = self.target.last_revision()
571
        return result
572
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
573
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
574
class InterToGitBranch(branch.InterBranch):
575
    """InterBranch implementation that pulls from Git into bzr."""
576
0.200.631 by Jelmer Vernooij
Raise proper exception in Branch.get_stacked_on_url().
577
    @staticmethod
578
    def _get_branch_formats_to_test():
579
        return None, None
580
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
581
    @classmethod
582
    def is_compatible(self, source, target):
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
583
        return (not isinstance(source, GitBranch) and
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
584
                isinstance(target, GitBranch))
585
0.200.542 by Jelmer Vernooij
Proper error for push in 1.14.
586
    def update_revisions(self, *args, **kwargs):
587
        raise NoPushSupport()
588
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
589
    def push(self, overwrite=True, stop_revision=None,
0.200.472 by Jelmer Vernooij
Fix printing error when user attempts to push into git.
590
             _override_hook_source_branch=None):
591
        raise NoPushSupport()
592
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
593
    def lossy_push(self, stop_revision=None):
0.200.504 by Jelmer Vernooij
Lazily find revno's for git branches.
594
        result = GitBranchPushResult()
0.200.503 by Jelmer Vernooij
Remove dpull, return BranchPushResult in lossy_push.
595
        result.source_branch = self.source
596
        result.target_branch = self.target
0.239.14 by Jelmer Vernooij
Cope with pushing to (not yet) existing branches.
597
        try:
598
            result.old_revid = self.target.last_revision()
599
        except NoSuchRef:
600
            result.old_revid = revision.NULL_REVISION
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
601
        if stop_revision is None:
602
            stop_revision = self.source.last_revision()
603
        # FIXME: Check for diverged branches
604
        refs = { "refs/heads/master": stop_revision }
605
        for name, revid in self.source.tags.get_tag_dict().iteritems():
606
            if self.source.repository.has_revision(revid):
607
                refs["refs/tags/%s" % name] = revid
608
        revidmap, new_refs = self.target.repository.dfetch_refs(
609
            self.source.repository, refs)
610
        if revidmap != {}:
611
            self.target.generate_revision_history(revidmap[stop_revision])
0.200.520 by Jelmer Vernooij
Proper output from dpush.
612
            result.new_revid = revidmap[stop_revision]
613
        else:
614
            result.new_revid = result.old_revid
0.200.503 by Jelmer Vernooij
Remove dpull, return BranchPushResult in lossy_push.
615
        result.revidmap = revidmap
616
        return result
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
617
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
618
619
branch.InterBranch.register_optimiser(InterGitRemoteLocalBranch)
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
620
branch.InterBranch.register_optimiser(InterFromGitBranch)
621
branch.InterBranch.register_optimiser(InterToGitBranch)
0.200.512 by Jelmer Vernooij
Support pushing git->git.
622
branch.InterBranch.register_optimiser(InterGitLocalRemoteBranch)