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