/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.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
172
0.239.8 by Jelmer Vernooij
Support checkouts.
173
    def _get_checkout_format(self):
174
        """Return the most suitable metadir for a checkout of this branch.
175
        Weaves are used if this branch's repository uses weaves.
176
        """
177
        return get_rich_root_format()
178
0.238.3 by Jelmer Vernooij
Remove svn references, prefer git send format when submitting changes against a git branch.
179
    def get_child_submit_format(self):
180
        """Return the preferred format of submissions to this branch."""
181
        ret = self.get_config().get_user_option("child_submit_format")
182
        if ret is not None:
183
            return ret
184
        return "git"
185
0.200.293 by Jelmer Vernooij
Fix branch nicks.
186
    def _get_nick(self, local=False, possible_master_transports=None):
187
        """Find the nick name for this branch.
188
189
        :return: Branch nick
190
        """
191
        return self.name
192
0.200.331 by Jelmer Vernooij
Add stub for setting nick function.
193
    def _set_nick(self, nick):
194
        raise NotImplementedError
195
196
    nick = property(_get_nick, _set_nick)
0.200.293 by Jelmer Vernooij
Fix branch nicks.
197
0.200.412 by Jelmer Vernooij
Implement GitBranch.__repr__.
198
    def __repr__(self):
199
        return "%s(%r, %r)" % (self.__class__.__name__, self.repository.base, self.name)
200
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
201
    def generate_revision_history(self, revid, old_revid=None):
202
        # FIXME: Check that old_revid is in the ancestry of revid
203
        newhead, self.mapping = self.mapping.revision_id_bzr_to_foreign(revid)
204
        self._set_head(newhead)
205
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
206
    def lock_write(self):
207
        self.control_files.lock_write()
208
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
209
    def get_stacked_on_url(self):
210
        # Git doesn't do stacking (yet...)
0.200.631 by Jelmer Vernooij
Raise proper exception in Branch.get_stacked_on_url().
211
        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.
212
213
    def get_parent(self):
214
        """See Branch.get_parent()."""
0.200.312 by Jelmer Vernooij
Add notes about parent locations.
215
        # 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.
216
        return None
217
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
218
    def set_parent(self, url):
0.200.312 by Jelmer Vernooij
Add notes about parent locations.
219
        # FIXME: Set "origin" url in .git/config ?
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
220
        pass
221
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
222
    def lock_read(self):
223
        self.control_files.lock_read()
224
0.200.432 by Jelmer Vernooij
Support Branch.is_locked, required for loggerhead.
225
    def is_locked(self):
226
        return self.control_files.is_locked()
227
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
228
    def unlock(self):
229
        self.control_files.unlock()
230
231
    def get_physical_lock_status(self):
232
        return False
233
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
234
    @needs_read_lock
235
    def last_revision(self):
236
        # perhaps should escape this ?
0.200.57 by Jelmer Vernooij
Fix more tests.
237
        if self.head is None:
0.200.19 by John Arbash Meinel
More refactoring. Add some direct tests for GitModel.
238
            return revision.NULL_REVISION
0.200.112 by Jelmer Vernooij
Fix the build.
239
        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.
240
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
241
    def _basic_push(self, target, overwrite=False, stop_revision=None):
242
        return branch.InterBranch.get(self, target)._basic_push(
243
            overwrite, stop_revision)
244
0.200.692 by Jelmer Vernooij
Refuse pulling into non-rich-root branches rather than erroring out with an AttributeError.
245
0.200.465 by Jelmer Vernooij
Use dulwich standard functionality for finding missing revisions.
246
class LocalGitBranch(GitBranch):
247
    """A local Git branch."""
248
0.200.261 by Jelmer Vernooij
More formatting fixes.
249
    def create_checkout(self, to_location, revision_id=None, lightweight=False,
250
        accelerator_tree=None, hardlink=False):
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
251
        if lightweight:
0.230.1 by Jelmer Vernooij
Support lightweight checkouts.
252
            t = transport.get_transport(to_location)
253
            t.ensure_base()
254
            format = self._get_checkout_format()
255
            checkout = format.initialize_on_transport(t)
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
256
            from_branch = branch.BranchReferenceFormat().initialize(checkout,
0.230.1 by Jelmer Vernooij
Support lightweight checkouts.
257
                self)
258
            tree = checkout.create_workingtree(revision_id,
259
                from_branch=from_branch, hardlink=hardlink)
260
            return tree
261
        else:
262
            return self._create_heavyweight_checkout(to_location, revision_id,
0.200.261 by Jelmer Vernooij
More formatting fixes.
263
            hardlink)
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
264
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
265
    def _create_heavyweight_checkout(self, to_location, revision_id=None,
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
266
                                     hardlink=False):
267
        """Create a new heavyweight checkout of this branch.
268
269
        :param to_location: URL of location to create the new checkout in.
270
        :param revision_id: Revision that should be the tip of the checkout.
271
        :param hardlink: Whether to hardlink
272
        :return: WorkingTree object of checkout.
273
        """
0.200.513 by Jelmer Vernooij
Fix imports.
274
        checkout_branch = bzrdir.BzrDir.create_branch_convenience(
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
275
            to_location, force_new_tree=False, format=get_rich_root_format())
276
        checkout = checkout_branch.bzrdir
277
        checkout_branch.bind(self)
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
278
        # 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.
279
        # branch tip correctly, and seed it with history.
280
        checkout_branch.pull(self, stop_revision=revision_id)
281
        return checkout.create_workingtree(revision_id, hardlink=hardlink)
282
0.200.57 by Jelmer Vernooij
Fix more tests.
283
    def _gen_revision_history(self):
0.200.58 by Jelmer Vernooij
Fix remaining tests.
284
        if self.head is None:
285
            return []
0.200.261 by Jelmer Vernooij
More formatting fixes.
286
        ret = list(self.repository.iter_reverse_revision_history(
287
            self.last_revision()))
0.200.59 by Jelmer Vernooij
Add more tests, fix revision history.
288
        ret.reverse()
0.200.57 by Jelmer Vernooij
Fix more tests.
289
        return ret
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
290
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
291
    def _get_head(self):
0.200.480 by Jelmer Vernooij
Cope with API changes in Dulwich.
292
        try:
293
            return self.repository._git.ref(self.name)
294
        except KeyError:
295
            return None
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
296
0.200.507 by Jelmer Vernooij
Implement set_last_revision{_info,}.
297
    def set_last_revision_info(self, revno, revid):
298
        self.set_last_revision(revid)
299
300
    def set_last_revision(self, revid):
0.200.523 by Jelmer Vernooij
Fix undefined error.
301
        (newhead, self.mapping) = self.mapping.revision_id_bzr_to_foreign(
0.200.507 by Jelmer Vernooij
Implement set_last_revision{_info,}.
302
                revid)
0.200.523 by Jelmer Vernooij
Fix undefined error.
303
        self.head = newhead
0.200.507 by Jelmer Vernooij
Implement set_last_revision{_info,}.
304
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
305
    def _set_head(self, value):
306
        self._head = value
0.200.480 by Jelmer Vernooij
Cope with API changes in Dulwich.
307
        self.repository._git.refs[self.name] = self._head
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
308
        self._clear_cached_state()
309
310
    head = property(_get_head, _set_head)
311
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
312
    def get_config(self):
313
        return GitBranchConfig(self)
314
315
    def get_push_location(self):
316
        """See Branch.get_push_location."""
317
        push_loc = self.get_config().get_user_option('push_location')
318
        return push_loc
319
320
    def set_push_location(self, location):
321
        """See Branch.set_push_location."""
0.200.19 by John Arbash Meinel
More refactoring. Add some direct tests for GitModel.
322
        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.
323
                                          store=config.STORE_LOCATION)
0.200.43 by David Allouche
Ultra-experimental support for "bzr pull". No test. No sanity.
324
325
    def supports_tags(self):
0.200.82 by Jelmer Vernooij
Support listing tags.
326
        return True
0.200.96 by Jelmer Vernooij
Fix branch.
327
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
328
0.200.342 by Jelmer Vernooij
Report git sha during pull.
329
class GitBranchPullResult(branch.PullResult):
330
331
    def report(self, to_file):
332
        if not is_quiet():
333
            if self.old_revid == self.new_revid:
334
                to_file.write('No revisions to pull.\n')
335
            else:
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
336
                to_file.write('Now on revision %d (git sha: %s).\n' %
0.200.342 by Jelmer Vernooij
Report git sha during pull.
337
                        (self.new_revno, self.new_git_head))
338
        self._show_tag_conficts(to_file)
339
340
0.200.504 by Jelmer Vernooij
Lazily find revno's for git branches.
341
class GitBranchPushResult(branch.BranchPushResult):
342
343
    def _lookup_revno(self, revid):
344
        assert isinstance(revid, str), "was %r" % revid
345
        # Try in source branch first, it'll be faster
346
        try:
347
            return self.source_branch.revision_id_to_revno(revid)
0.200.523 by Jelmer Vernooij
Fix undefined error.
348
        except errors.NoSuchRevision:
0.200.504 by Jelmer Vernooij
Lazily find revno's for git branches.
349
            # FIXME: Check using graph.find_distance_to_null() ?
350
            return self.target_branch.revision_id_to_revno(revid)
351
352
    @property
353
    def old_revno(self):
354
        return self._lookup_revno(self.old_revid)
355
356
    @property
357
    def new_revno(self):
358
        return self._lookup_revno(self.new_revid)
359
360
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
361
class InterFromGitBranch(branch.GenericInterBranch):
0.200.261 by Jelmer Vernooij
More formatting fixes.
362
    """InterBranch implementation that pulls from Git into bzr."""
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
363
364
    @classmethod
0.200.692 by Jelmer Vernooij
Refuse pulling into non-rich-root branches rather than erroring out with an AttributeError.
365
    def _get_interrepo(self, source, target):
366
        return repository.InterRepository.get(source.repository,
367
            target.repository)
368
369
    @classmethod
370
    def is_compatible(cls, source, target):
371
        return (isinstance(source, GitBranch) and
372
                not isinstance(target, GitBranch) and
373
                (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.
374
375
    def update_revisions(self, stop_revision=None, overwrite=False,
376
        graph=None):
377
        """See InterBranch.update_revisions()."""
0.200.692 by Jelmer Vernooij
Refuse pulling into non-rich-root branches rather than erroring out with an AttributeError.
378
        interrepo = self._get_interrepo(self.source, self.target)
0.200.342 by Jelmer Vernooij
Report git sha during pull.
379
        self._head = None
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
380
        self._last_revid = None
381
        def determine_wants(heads):
382
            if not self.source.name in heads:
0.200.278 by Jelmer Vernooij
Update branch head appropriately during dpull.
383
                raise NoSuchRef(self.source.name, heads.keys())
0.200.314 by Jelmer Vernooij
Support stop_revision.
384
            if stop_revision is not None:
385
                self._last_revid = stop_revision
0.200.650 by Jelmer Vernooij
Use standard names for lookup functions.
386
                self._head, mapping = self.source.repository.lookup_bzr_revision_id(
0.200.316 by Jelmer Vernooij
Fix formatting.
387
                    stop_revision)
0.200.314 by Jelmer Vernooij
Support stop_revision.
388
            else:
0.200.342 by Jelmer Vernooij
Report git sha during pull.
389
                self._head = heads[self.source.name]
0.200.316 by Jelmer Vernooij
Fix formatting.
390
                self._last_revid = \
0.200.342 by Jelmer Vernooij
Report git sha during pull.
391
                    self.source.mapping.revision_id_foreign_to_bzr(self._head)
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
392
            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.
393
                return []
0.200.342 by Jelmer Vernooij
Report git sha during pull.
394
            return [self._head]
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
395
        interrepo.fetch_objects(determine_wants, self.source.mapping)
0.200.313 by Jelmer Vernooij
Support overwrite parameter.
396
        if overwrite:
0.200.314 by Jelmer Vernooij
Support stop_revision.
397
            prev_last_revid = None
0.200.313 by Jelmer Vernooij
Support overwrite parameter.
398
        else:
0.200.314 by Jelmer Vernooij
Support stop_revision.
399
            prev_last_revid = self.target.last_revision()
400
        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.
401
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
402
    def pull(self, overwrite=False, stop_revision=None,
403
             possible_transports=None, _hook_master=None, run_hooks=True,
0.200.446 by Jelmer Vernooij
Support new 'local' argument.
404
             _override_hook_target=None, local=False):
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
405
        """See Branch.pull.
406
407
        :param _hook_master: Private parameter - set the branch to
408
            be supplied as the master to pull hooks.
409
        :param run_hooks: Private parameter - if false, this branch
410
            is being called because it's the master of the primary branch,
411
            so it should not run its hooks.
412
        :param _override_hook_target: Private parameter - set the branch to be
413
            supplied as the target_branch to pull hooks.
414
        """
0.200.446 by Jelmer Vernooij
Support new 'local' argument.
415
        # This type of branch can't be bound.
416
        if local:
417
            raise errors.LocalRequiresBoundBranch()
0.200.342 by Jelmer Vernooij
Report git sha during pull.
418
        result = GitBranchPullResult()
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
419
        result.source_branch = self.source
420
        if _override_hook_target is None:
421
            result.target_branch = self.target
422
        else:
423
            result.target_branch = _override_hook_target
424
        self.source.lock_read()
425
        try:
426
            # We assume that during 'pull' the target repository is closer than
427
            # the source one.
428
            graph = self.target.repository.get_graph(self.source.repository)
429
            result.old_revno, result.old_revid = \
430
                self.target.last_revision_info()
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
431
            self.update_revisions(stop_revision, overwrite=overwrite,
0.200.342 by Jelmer Vernooij
Report git sha during pull.
432
                graph=graph)
433
            result.new_git_head = self._head
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
434
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
435
                overwrite)
436
            result.new_revno, result.new_revid = self.target.last_revision_info()
437
            if _hook_master:
438
                result.master_branch = _hook_master
439
                result.local_branch = result.target_branch
440
            else:
441
                result.master_branch = result.target_branch
442
                result.local_branch = None
443
            if run_hooks:
444
                for hook in branch.Branch.hooks['post_pull']:
445
                    hook(result)
446
        finally:
447
            self.source.unlock()
448
        return result
449
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
450
    def _basic_push(self, overwrite=False, stop_revision=None):
451
        result = branch.BranchPushResult()
452
        result.source_branch = self.source
453
        result.target_branch = self.target
0.200.505 by Jelmer Vernooij
Remove duplicate code.
454
        graph = self.target.repository.get_graph(self.source.repository)
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
455
        result.old_revno, result.old_revid = self.target.last_revision_info()
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
456
        self.update_revisions(stop_revision, overwrite=overwrite, graph=graph)
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
457
        result.new_git_head = self._head
458
        result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
459
            overwrite)
460
        result.new_revno, result.new_revid = self.target.last_revision_info()
461
        return result
462
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
463
0.200.512 by Jelmer Vernooij
Support pushing git->git.
464
class InterGitBranch(branch.GenericInterBranch):
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
465
    """InterBranch implementation that pulls between Git branches."""
466
0.200.512 by Jelmer Vernooij
Support pushing git->git.
467
468
class InterGitLocalRemoteBranch(InterGitBranch):
469
    """InterBranch that copies from a local to a remote git branch."""
470
471
    @classmethod
472
    def is_compatible(self, source, target):
473
        from bzrlib.plugins.git.remote import RemoteGitBranch
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
474
        return (isinstance(source, LocalGitBranch) and
0.200.512 by Jelmer Vernooij
Support pushing git->git.
475
                isinstance(target, RemoteGitBranch))
476
477
    def _basic_push(self, overwrite=False, stop_revision=None):
478
        result = GitBranchPushResult()
479
        result.source_branch = self.source
480
        result.target_branch = self.target
481
        if stop_revision is None:
482
            stop_revision = self.source.last_revision()
483
        # FIXME: Check for diverged branches
484
        def get_changed_refs(old_refs):
0.200.544 by Jelmer Vernooij
Support pushing from git -> empty git repo.
485
            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.
486
            refs = { "refs/heads/master": self.source.repository.lookup_bzr_revision_id(stop_revision)[0] }
0.200.512 by Jelmer Vernooij
Support pushing git->git.
487
            result.new_revid = stop_revision
488
            for name, sha in self.source.repository._git.refs.as_dict("refs/tags").iteritems():
489
                refs["refs/tags/%s" % name] = sha
490
            return refs
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
491
        self.target.repository.send_pack(get_changed_refs,
0.200.512 by Jelmer Vernooij
Support pushing git->git.
492
                self.source.repository._git.object_store.generate_pack_contents)
493
        return result
494
495
496
class InterGitRemoteLocalBranch(InterGitBranch):
497
    """InterBranch that copies from a remote to a local git branch."""
498
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
499
    @classmethod
500
    def is_compatible(self, source, target):
501
        from bzrlib.plugins.git.remote import RemoteGitBranch
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
502
        return (isinstance(source, RemoteGitBranch) and
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
503
                isinstance(target, LocalGitBranch))
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
509
        result.old_revid = self.target.last_revision()
510
        refs, stop_revision = self.update_refs(stop_revision)
511
        self.target.generate_revision_history(stop_revision, result.old_revid)
512
        self.update_tags(refs)
0.200.505 by Jelmer Vernooij
Remove duplicate code.
513
        result.new_revid = self.target.last_revision()
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
514
        return result
515
516
    def update_tags(self, refs):
0.200.648 by Jelmer Vernooij
Fix tag handling when encountering packed refs.
517
        for name, v in extract_tags(refs).iteritems():
518
            revid = self.target.mapping.revision_id_foreign_to_bzr(v)
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
519
            self.target.tags.set_tag(name, revid)
520
521
    def update_refs(self, stop_revision=None):
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
522
        interrepo = repository.InterRepository.get(self.source.repository,
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
523
            self.target.repository)
524
        if stop_revision is None:
525
            refs = interrepo.fetch_refs(branches=["HEAD"])
526
            stop_revision = self.target.mapping.revision_id_foreign_to_bzr(refs["HEAD"])
527
        else:
528
            refs = interrepo.fetch_refs(revision_id=stop_revision)
529
        return refs, stop_revision
530
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
531
    def pull(self, stop_revision=None, overwrite=False,
0.200.446 by Jelmer Vernooij
Support new 'local' argument.
532
        possible_transports=None, local=False):
533
        # This type of branch can't be bound.
534
        if local:
535
            raise errors.LocalRequiresBoundBranch()
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
536
        result = GitPullResult()
537
        result.source_branch = self.source
538
        result.target_branch = self.target
539
        result.old_revid = self.target.last_revision()
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
540
        refs, stop_revision = self.update_refs(stop_revision)
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
541
        self.target.generate_revision_history(stop_revision, result.old_revid)
0.200.501 by Jelmer Vernooij
Support push from git into bzr.
542
        self.update_tags(refs)
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
543
        result.new_revid = self.target.last_revision()
544
        return result
545
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
546
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
547
class InterToGitBranch(branch.InterBranch):
548
    """InterBranch implementation that pulls from Git into bzr."""
549
0.200.631 by Jelmer Vernooij
Raise proper exception in Branch.get_stacked_on_url().
550
    @staticmethod
551
    def _get_branch_formats_to_test():
552
        return None, None
553
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
554
    @classmethod
555
    def is_compatible(self, source, target):
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
556
        return (not isinstance(source, GitBranch) and
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
557
                isinstance(target, GitBranch))
558
0.200.542 by Jelmer Vernooij
Proper error for push in 1.14.
559
    def update_revisions(self, *args, **kwargs):
560
        raise NoPushSupport()
561
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
562
    def push(self, overwrite=True, stop_revision=None,
0.200.472 by Jelmer Vernooij
Fix printing error when user attempts to push into git.
563
             _override_hook_source_branch=None):
564
        raise NoPushSupport()
565
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
566
    def lossy_push(self, stop_revision=None):
0.200.504 by Jelmer Vernooij
Lazily find revno's for git branches.
567
        result = GitBranchPushResult()
0.200.503 by Jelmer Vernooij
Remove dpull, return BranchPushResult in lossy_push.
568
        result.source_branch = self.source
569
        result.target_branch = self.target
0.239.14 by Jelmer Vernooij
Cope with pushing to (not yet) existing branches.
570
        try:
571
            result.old_revid = self.target.last_revision()
572
        except NoSuchRef:
573
            result.old_revid = revision.NULL_REVISION
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
574
        if stop_revision is None:
575
            stop_revision = self.source.last_revision()
576
        # FIXME: Check for diverged branches
577
        refs = { "refs/heads/master": stop_revision }
578
        for name, revid in self.source.tags.get_tag_dict().iteritems():
579
            if self.source.repository.has_revision(revid):
580
                refs["refs/tags/%s" % name] = revid
581
        revidmap, new_refs = self.target.repository.dfetch_refs(
582
            self.source.repository, refs)
583
        if revidmap != {}:
584
            self.target.generate_revision_history(revidmap[stop_revision])
0.200.520 by Jelmer Vernooij
Proper output from dpush.
585
            result.new_revid = revidmap[stop_revision]
586
        else:
587
            result.new_revid = result.old_revid
0.200.503 by Jelmer Vernooij
Remove dpull, return BranchPushResult in lossy_push.
588
        result.revidmap = revidmap
589
        return result
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
590
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
591
592
branch.InterBranch.register_optimiser(InterGitRemoteLocalBranch)
0.200.468 by Jelmer Vernooij
Move dpush logic onto InterBranch.
593
branch.InterBranch.register_optimiser(InterFromGitBranch)
594
branch.InterBranch.register_optimiser(InterToGitBranch)
0.200.512 by Jelmer Vernooij
Support pushing git->git.
595
branch.InterBranch.register_optimiser(InterGitLocalRemoteBranch)