/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to branch.py

  • Committer: Jelmer Vernooij
  • Date: 2009-05-16 21:13:17 UTC
  • mto: (0.200.527 trunk)
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@samba.org-20090516211317-a0s14tsrf2qusapf
Fix tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2007 Canonical Ltd
2
 
# Copyright (C) 2009-2010 Jelmer Vernooij <jelmer@samba.org>
 
2
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
27
27
    bzrdir,
28
28
    config,
29
29
    errors,
 
30
    foreign,
30
31
    repository,
31
32
    revision,
32
33
    tag,
35
36
from bzrlib.decorators import (
36
37
    needs_read_lock,
37
38
    )
38
 
from bzrlib.revision import (
39
 
    NULL_REVISION,
40
 
    )
41
39
from bzrlib.trace import (
42
40
    is_quiet,
43
41
    mutter,
44
42
    )
45
43
 
 
44
from bzrlib.plugins.git import (
 
45
    get_rich_root_format,
 
46
    )
46
47
from bzrlib.plugins.git.config import (
47
48
    GitBranchConfig,
48
49
    )
50
51
    NoPushSupport,
51
52
    NoSuchRef,
52
53
    )
53
 
from bzrlib.plugins.git.refs import (
54
 
    ref_to_branch_name,
55
 
    extract_tags,
56
 
    tag_name_to_ref,
57
 
    )
58
 
 
59
 
from bzrlib.foreign import ForeignBranch
 
54
 
 
55
try:
 
56
    from bzrlib.foreign import ForeignBranch
 
57
except ImportError:
 
58
    class ForeignBranch(branch.Branch):
 
59
        def __init__(self, mapping):
 
60
            self.mapping = mapping
 
61
            super(ForeignBranch, self).__init__()
 
62
 
 
63
 
 
64
def extract_tags(refs, mapping):
 
65
    ret = {}
 
66
    for k,v in refs.iteritems():
 
67
        if k.startswith("refs/tags/") and not k.endswith("^{}"):
 
68
            v = refs.get(k+"^{}", v)
 
69
            ret[k[len("refs/tags/"):]] = mapping.revision_id_foreign_to_bzr(v)
 
70
    return ret
60
71
 
61
72
 
62
73
class GitPullResult(branch.PullResult):
63
 
    """Result of a pull from a Git branch."""
64
74
 
65
75
    def _lookup_revno(self, revid):
66
76
        assert isinstance(revid, str), "was %r" % revid
85
95
 
86
96
    def get_tag_dict(self):
87
97
        ret = {}
88
 
        for k,v in extract_tags(self.repository._git.get_refs()).iteritems():
89
 
            try:
90
 
                obj = self.repository._git[v]
91
 
            except KeyError:
92
 
                mutter("Tag %s points at unknown object %s, ignoring", v, obj)
93
 
                continue
 
98
        for k,v in self.repository._git.refs.as_dict("refs/tags").iteritems():
 
99
            obj = self.repository._git.get_object(v)
94
100
            while isinstance(obj, Tag):
95
101
                v = obj.object[1]
96
 
                obj = self.repository._git[v]
 
102
                obj = self.repository._git.get_object(v)
97
103
            if not isinstance(obj, Commit):
98
104
                mutter("Tag %s points at object %r that is not a commit, "
99
105
                       "ignoring", k, obj)
100
106
                continue
101
 
            ret[k] = self.branch.lookup_foreign_revision_id(v)
 
107
            ret[k] = self.branch.mapping.revision_id_foreign_to_bzr(v)
102
108
        return ret
103
109
 
104
 
    def _set_tag_dict(self, to_dict):
105
 
        extra = set(self.repository._git.get_refs().keys())
106
 
        for k, revid in to_dict.iteritems():
107
 
            name = tag_name_to_ref(k)
108
 
            if name in extra:
109
 
                extra.remove(name)
110
 
            self.set_tag(k, revid)
111
 
        for name in extra:
112
 
            if name.startswith("refs/tags/"):
113
 
                del self.repository._git[name]
114
 
 
115
110
    def set_tag(self, name, revid):
116
 
        self.repository._git.refs[tag_name_to_ref(name)], _ = \
117
 
            self.branch.lookup_bzr_revision_id(revid)
118
 
 
119
 
 
120
 
class DictTagDict(LocalGitTagDict):
121
 
 
122
 
    def __init__(self, branch, tags):
123
 
        super(DictTagDict, self).__init__(branch)
124
 
        self._tags = tags
125
 
 
126
 
    def get_tag_dict(self):
127
 
        return self._tags
 
111
        self.repository._git.refs["refs/tags/%s" % name], _ = \
 
112
            self.branch.mapping.revision_id_bzr_to_foreign(revid)
128
113
 
129
114
 
130
115
class GitBranchFormat(branch.BranchFormat):
132
117
    def get_format_description(self):
133
118
        return 'Git Branch'
134
119
 
135
 
    def network_name(self):
136
 
        return "git"
137
 
 
138
120
    def supports_tags(self):
139
121
        return True
140
122
 
141
 
    def get_foreign_tests_branch_factory(self):
142
 
        from bzrlib.plugins.git.tests.test_branch import ForeignTestsBranchFactory
143
 
        return ForeignTestsBranchFactory()
144
 
 
145
123
    def make_tags(self, branch):
146
124
        if getattr(branch.repository, "get_refs", None) is not None:
147
125
            from bzrlib.plugins.git.remote import RemoteGitTagDict
150
128
            return LocalGitTagDict(branch)
151
129
 
152
130
 
153
 
class GitReadLock(object):
154
 
 
155
 
    def __init__(self, unlock):
156
 
        self.unlock = unlock
157
 
 
158
 
 
159
 
class GitWriteLock(object):
160
 
 
161
 
    def __init__(self, unlock):
162
 
        self.unlock = unlock
163
 
 
164
 
 
165
131
class GitBranch(ForeignBranch):
166
132
    """An adapter to git repositories for bzr Branch objects."""
167
133
 
168
 
    def __init__(self, bzrdir, repository, ref, lockfiles, tagsdict=None):
 
134
    def __init__(self, bzrdir, repository, name, lockfiles):
169
135
        self.repository = repository
170
136
        self._format = GitBranchFormat()
171
137
        self.control_files = lockfiles
172
138
        self.bzrdir = bzrdir
173
139
        super(GitBranch, self).__init__(repository.get_mapping())
174
 
        if tagsdict is not None:
175
 
            self.tags = DictTagDict(self, tagsdict)
176
 
        self.ref = ref
177
 
        self.name = ref_to_branch_name(ref)
 
140
        self.name = name
178
141
        self._head = None
179
 
        self.base = bzrdir.root_transport.base
180
 
 
181
 
    def _get_checkout_format(self):
182
 
        """Return the most suitable metadir for a checkout of this branch.
183
 
        Weaves are used if this branch's repository uses weaves.
184
 
        """
185
 
        return bzrdir.format_registry.make_bzrdir("default")
186
 
 
187
 
    def get_child_submit_format(self):
188
 
        """Return the preferred format of submissions to this branch."""
189
 
        ret = self.get_config().get_user_option("child_submit_format")
190
 
        if ret is not None:
191
 
            return ret
192
 
        return "git"
 
142
        self.base = bzrdir.transport.base
193
143
 
194
144
    def _get_nick(self, local=False, possible_master_transports=None):
195
145
        """Find the nick name for this branch.
196
146
 
197
147
        :return: Branch nick
198
148
        """
199
 
        return self.name or "HEAD"
 
149
        return self.name
200
150
 
201
151
    def _set_nick(self, nick):
202
152
        raise NotImplementedError
204
154
    nick = property(_get_nick, _set_nick)
205
155
 
206
156
    def __repr__(self):
207
 
        return "<%s(%r, %r)>" % (self.__class__.__name__, self.repository.base,
208
 
            self.ref or "HEAD")
 
157
        return "%s(%r, %r)" % (self.__class__.__name__, self.repository.base, self.name)
209
158
 
210
159
    def generate_revision_history(self, revid, old_revid=None):
211
160
        # FIXME: Check that old_revid is in the ancestry of revid
214
163
 
215
164
    def lock_write(self):
216
165
        self.control_files.lock_write()
217
 
        return GitWriteLock(self.unlock)
218
166
 
219
167
    def get_stacked_on_url(self):
220
168
        # Git doesn't do stacking (yet...)
221
 
        raise errors.UnstackableBranchFormat(self._format, self.base)
 
169
        return None
222
170
 
223
171
    def get_parent(self):
224
172
        """See Branch.get_parent()."""
231
179
 
232
180
    def lock_read(self):
233
181
        self.control_files.lock_read()
234
 
        return GitReadLock(self.unlock)
235
182
 
236
183
    def is_locked(self):
237
184
        return self.control_files.is_locked()
247
194
        # perhaps should escape this ?
248
195
        if self.head is None:
249
196
            return revision.NULL_REVISION
250
 
        return self.lookup_foreign_revision_id(self.head)
 
197
        return self.mapping.revision_id_foreign_to_bzr(self.head)
251
198
 
252
199
    def _basic_push(self, target, overwrite=False, stop_revision=None):
253
200
        return branch.InterBranch.get(self, target)._basic_push(
254
201
            overwrite, stop_revision)
255
202
 
256
 
    def lookup_foreign_revision_id(self, foreign_revid):
257
 
        return self.repository.lookup_foreign_revision_id(foreign_revid,
258
 
            self.mapping)
259
 
 
260
 
    def lookup_bzr_revision_id(self, revid):
261
 
        return self.repository.lookup_bzr_revision_id(
262
 
            revid, mapping=self.mapping)
263
 
 
264
 
 
 
203
 
265
204
class LocalGitBranch(GitBranch):
266
205
    """A local Git branch."""
267
206
 
268
 
    def __init__(self, bzrdir, repository, name, lockfiles, tagsdict=None):
269
 
        super(LocalGitBranch, self).__init__(bzrdir, repository, name,
270
 
              lockfiles, tagsdict)
271
 
        refs = repository._git.get_refs()
272
 
        if not (name in refs.keys() or "HEAD" in refs.keys()):
273
 
            raise errors.NotBranchError(self.base)
 
207
    def _get_checkout_format(self):
 
208
        """Return the most suitable metadir for a checkout of this branch.
 
209
        Weaves are used if this branch's repository uses weaves.
 
210
        """
 
211
        format = self.repository.bzrdir.checkout_metadir()
 
212
        format.set_branch_format(self._format)
 
213
        return format
274
214
 
275
215
    def create_checkout(self, to_location, revision_id=None, lightweight=False,
276
216
        accelerator_tree=None, hardlink=False):
279
219
            t.ensure_base()
280
220
            format = self._get_checkout_format()
281
221
            checkout = format.initialize_on_transport(t)
282
 
            from_branch = branch.BranchReferenceFormat().initialize(checkout,
 
222
            from_branch = branch.BranchReferenceFormat().initialize(checkout, 
283
223
                self)
284
224
            tree = checkout.create_workingtree(revision_id,
285
225
                from_branch=from_branch, hardlink=hardlink)
286
226
            return tree
287
227
        else:
288
228
            return self._create_heavyweight_checkout(to_location, revision_id,
289
 
                hardlink)
 
229
            hardlink)
290
230
 
291
 
    def _create_heavyweight_checkout(self, to_location, revision_id=None,
 
231
    def _create_heavyweight_checkout(self, to_location, revision_id=None, 
292
232
                                     hardlink=False):
293
233
        """Create a new heavyweight checkout of this branch.
294
234
 
298
238
        :return: WorkingTree object of checkout.
299
239
        """
300
240
        checkout_branch = bzrdir.BzrDir.create_branch_convenience(
301
 
            to_location, force_new_tree=False)
 
241
            to_location, force_new_tree=False, format=get_rich_root_format())
302
242
        checkout = checkout_branch.bzrdir
303
243
        checkout_branch.bind(self)
304
 
        # pull up to the specified revision_id to set the initial
 
244
        # pull up to the specified revision_id to set the initial 
305
245
        # branch tip correctly, and seed it with history.
306
246
        checkout_branch.pull(self, stop_revision=revision_id)
307
247
        return checkout.create_workingtree(revision_id, hardlink=hardlink)
316
256
 
317
257
    def _get_head(self):
318
258
        try:
319
 
            return self.repository._git.ref(self.ref or "HEAD")
 
259
            return self.repository._git.ref(self.name)
320
260
        except KeyError:
321
261
            return None
322
262
 
324
264
        self.set_last_revision(revid)
325
265
 
326
266
    def set_last_revision(self, revid):
327
 
        (newhead, self.mapping) = self.repository.lookup_bzr_revision_id(revid)
 
267
        (newhead, self.mapping) = self.mapping.revision_id_bzr_to_foreign(
 
268
                revid)
328
269
        self.head = newhead
329
270
 
330
271
    def _set_head(self, value):
331
272
        self._head = value
332
 
        self.repository._git.refs[self.ref or "HEAD"] = self._head
 
273
        self.repository._git.refs[self.name] = self._head
333
274
        self._clear_cached_state()
334
275
 
335
276
    head = property(_get_head, _set_head)
353
294
 
354
295
class GitBranchPullResult(branch.PullResult):
355
296
 
356
 
    def __init__(self):
357
 
        super(GitBranchPullResult, self).__init__()
358
 
        self.new_git_head = None
359
 
        self._old_revno = None
360
 
        self._new_revno = None
361
 
 
362
297
    def report(self, to_file):
363
298
        if not is_quiet():
364
299
            if self.old_revid == self.new_revid:
365
300
                to_file.write('No revisions to pull.\n')
366
 
            elif self.new_git_head is not None:
367
 
                to_file.write('Now on revision %d (git sha: %s).\n' %
 
301
            else:
 
302
                to_file.write('Now on revision %d (git sha: %s).\n' % 
368
303
                        (self.new_revno, self.new_git_head))
369
 
            else:
370
 
                to_file.write('Now on revision %d.\n' % (self.new_revno,))
371
304
        self._show_tag_conficts(to_file)
372
305
 
373
 
    def _lookup_revno(self, revid):
374
 
        assert isinstance(revid, str), "was %r" % revid
375
 
        # Try in source branch first, it'll be faster
376
 
        try:
377
 
            return self.source_branch.revision_id_to_revno(revid)
378
 
        except errors.NoSuchRevision:
379
 
            # FIXME: Check using graph.find_distance_to_null() ?
380
 
            return self.target_branch.revision_id_to_revno(revid)
381
 
 
382
 
    def _get_old_revno(self):
383
 
        if self._old_revno is not None:
384
 
            return self._old_revno
385
 
        return self._lookup_revno(self.old_revid)
386
 
 
387
 
    def _set_old_revno(self, revno):
388
 
        self._old_revno = revno
389
 
 
390
 
    old_revno = property(_get_old_revno, _set_old_revno)
391
 
 
392
 
    def _get_new_revno(self):
393
 
        if self._new_revno is not None:
394
 
            return self._new_revno
395
 
        return self._lookup_revno(self.new_revid)
396
 
 
397
 
    def _set_new_revno(self, revno):
398
 
        self._new_revno = revno
399
 
 
400
 
    new_revno = property(_get_new_revno, _set_new_revno)
401
 
 
402
306
 
403
307
class GitBranchPushResult(branch.BranchPushResult):
404
308
 
423
327
class InterFromGitBranch(branch.GenericInterBranch):
424
328
    """InterBranch implementation that pulls from Git into bzr."""
425
329
 
426
 
    @staticmethod
427
 
    def _get_branch_formats_to_test():
428
 
        return []
429
 
 
430
 
    @classmethod
431
 
    def _get_interrepo(self, source, target):
432
 
        return repository.InterRepository.get(source.repository,
433
 
            target.repository)
434
 
 
435
 
    @classmethod
436
 
    def is_compatible(cls, source, target):
437
 
        return (isinstance(source, GitBranch) and
438
 
                not isinstance(target, GitBranch) and
439
 
                (getattr(cls._get_interrepo(source, target), "fetch_objects", None) is not None))
440
 
 
441
 
    def _update_revisions(self, stop_revision=None, overwrite=False,
442
 
        graph=None, limit=None):
443
 
        """Like InterBranch.update_revisions(), but with additions.
444
 
 
445
 
        Compared to the `update_revisions()` below, this function takes a
446
 
        `limit` argument that limits how many git commits will be converted
447
 
        and returns the new git head.
448
 
        """
449
 
        interrepo = self._get_interrepo(self.source, self.target)
 
330
    @classmethod
 
331
    def is_compatible(self, source, target):
 
332
        return (isinstance(source, GitBranch) and 
 
333
                not isinstance(target, GitBranch))
 
334
 
 
335
    def update_revisions(self, stop_revision=None, overwrite=False,
 
336
        graph=None):
 
337
        """See InterBranch.update_revisions()."""
 
338
        interrepo = repository.InterRepository.get(self.source.repository, 
 
339
            self.target.repository)
 
340
        self._head = None
 
341
        self._last_revid = None
450
342
        def determine_wants(heads):
451
 
            if self.source.ref is not None and not self.source.ref in heads:
452
 
                raise NoSuchRef(self.source.ref, heads.keys())
 
343
            if not self.source.name in heads:
 
344
                raise NoSuchRef(self.source.name, heads.keys())
453
345
            if stop_revision is not None:
454
346
                self._last_revid = stop_revision
455
 
                head, mapping = self.source.repository.lookup_bzr_revision_id(
 
347
                self._head, mapping = self.source.repository.lookup_git_revid(
456
348
                    stop_revision)
457
349
            else:
458
 
                if self.source.ref is not None:
459
 
                    head = heads[self.source.ref]
460
 
                else:
461
 
                    head = heads["HEAD"]
462
 
                self._last_revid = self.source.lookup_foreign_revision_id(head)
 
350
                self._head = heads[self.source.name]
 
351
                self._last_revid = \
 
352
                    self.source.mapping.revision_id_foreign_to_bzr(self._head)
463
353
            if self.target.repository.has_revision(self._last_revid):
464
354
                return []
465
 
            return [head]
466
 
        pack_hint, head, refs = interrepo.fetch_objects(
467
 
            determine_wants, self.source.mapping, limit=limit)
468
 
        if (pack_hint is not None and
469
 
            self.target.repository._format.pack_compresses):
470
 
            self.target.repository.pack(hint=pack_hint)
471
 
        if head is not None:
472
 
            self._last_revid = self.source.lookup_foreign_revision_id(head)
 
355
            return [self._head]
 
356
        interrepo.fetch_objects(determine_wants, self.source.mapping)
473
357
        if overwrite:
474
358
            prev_last_revid = None
475
359
        else:
476
360
            prev_last_revid = self.target.last_revision()
477
 
        self.target.generate_revision_history(self._last_revid,
478
 
            prev_last_revid)
479
 
        return head
480
 
 
481
 
    def update_revisions(self, stop_revision=None, overwrite=False,
482
 
                         graph=None):
483
 
        """See InterBranch.update_revisions()."""
484
 
        self._update_revisions(stop_revision, overwrite, graph)
 
361
        self.target.generate_revision_history(self._last_revid, prev_last_revid)
485
362
 
486
363
    def pull(self, overwrite=False, stop_revision=None,
487
364
             possible_transports=None, _hook_master=None, run_hooks=True,
488
 
             _override_hook_target=None, local=False, limit=None):
 
365
             _override_hook_target=None, local=False):
489
366
        """See Branch.pull.
490
367
 
491
368
        :param _hook_master: Private parameter - set the branch to
495
372
            so it should not run its hooks.
496
373
        :param _override_hook_target: Private parameter - set the branch to be
497
374
            supplied as the target_branch to pull hooks.
498
 
        :param limit: Only import this many revisons.  `None`, the default,
499
 
            means import all revisions.
500
375
        """
501
376
        # This type of branch can't be bound.
502
377
        if local:
512
387
            # We assume that during 'pull' the target repository is closer than
513
388
            # the source one.
514
389
            graph = self.target.repository.get_graph(self.source.repository)
515
 
            (result.old_revno, result.old_revid) = \
 
390
            result.old_revno, result.old_revid = \
516
391
                self.target.last_revision_info()
517
 
            result.new_git_head = self._update_revisions(
518
 
                stop_revision, overwrite=overwrite, graph=graph, limit=limit)
 
392
            self.update_revisions(stop_revision, overwrite=overwrite, 
 
393
                graph=graph)
 
394
            result.new_git_head = self._head
519
395
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
520
396
                overwrite)
521
 
            (result.new_revno, result.new_revid) = \
522
 
                self.target.last_revision_info()
 
397
            result.new_revno, result.new_revid = self.target.last_revision_info()
523
398
            if _hook_master:
524
399
                result.master_branch = _hook_master
525
400
                result.local_branch = result.target_branch
539
414
        result.target_branch = self.target
540
415
        graph = self.target.repository.get_graph(self.source.repository)
541
416
        result.old_revno, result.old_revid = self.target.last_revision_info()
542
 
        result.new_git_head = self._update_revisions(
543
 
            stop_revision, overwrite=overwrite, graph=graph)
 
417
        self.update_revisions(stop_revision, overwrite=overwrite, 
 
418
            graph=graph)
 
419
        result.new_git_head = self._head
544
420
        result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
545
421
            overwrite)
546
422
        result.new_revno, result.new_revid = self.target.last_revision_info()
554
430
class InterGitLocalRemoteBranch(InterGitBranch):
555
431
    """InterBranch that copies from a local to a remote git branch."""
556
432
 
557
 
    @staticmethod
558
 
    def _get_branch_formats_to_test():
559
 
        return []
560
 
 
561
433
    @classmethod
562
434
    def is_compatible(self, source, target):
563
435
        from bzrlib.plugins.git.remote import RemoteGitBranch
564
 
        return (isinstance(source, LocalGitBranch) and
 
436
        return (isinstance(source, LocalGitBranch) and 
565
437
                isinstance(target, RemoteGitBranch))
566
438
 
567
439
    def _basic_push(self, overwrite=False, stop_revision=None):
568
 
        from dulwich.protocol import ZERO_SHA
569
440
        result = GitBranchPushResult()
570
441
        result.source_branch = self.source
571
442
        result.target_branch = self.target
573
444
            stop_revision = self.source.last_revision()
574
445
        # FIXME: Check for diverged branches
575
446
        def get_changed_refs(old_refs):
576
 
            result.old_revid = self.target.lookup_foreign_revision_id(old_refs.get(self.target.ref, ZERO_SHA))
577
 
            refs = { self.target.ref: self.source.repository.lookup_bzr_revision_id(stop_revision)[0] }
 
447
            result.old_revid = self.target.mapping.revision_id_foreign_to_bzr(old_refs["refs/heads/master"])
 
448
            refs = { "refs/heads/master": self.source.repository.lookup_git_revid(stop_revision)[0] }
578
449
            result.new_revid = stop_revision
579
450
            for name, sha in self.source.repository._git.refs.as_dict("refs/tags").iteritems():
580
 
                refs[tag_name_to_ref(name)] = sha
 
451
                refs["refs/tags/%s" % name] = sha
581
452
            return refs
582
 
        self.target.repository.send_pack(get_changed_refs,
583
 
            self.source.repository._git.object_store.generate_pack_contents)
 
453
        self.target.repository.send_pack(get_changed_refs, 
 
454
                self.source.repository._git.object_store.generate_pack_contents)
584
455
        return result
585
456
 
586
457
 
587
458
class InterGitRemoteLocalBranch(InterGitBranch):
588
459
    """InterBranch that copies from a remote to a local git branch."""
589
460
 
590
 
    @staticmethod
591
 
    def _get_branch_formats_to_test():
592
 
        return []
593
 
 
594
461
    @classmethod
595
462
    def is_compatible(self, source, target):
596
463
        from bzrlib.plugins.git.remote import RemoteGitBranch
597
 
        return (isinstance(source, RemoteGitBranch) and
 
464
        return (isinstance(source, RemoteGitBranch) and 
598
465
                isinstance(target, LocalGitBranch))
599
466
 
600
467
    def _basic_push(self, overwrite=False, stop_revision=None):
609
476
        return result
610
477
 
611
478
    def update_tags(self, refs):
612
 
        for name, v in extract_tags(refs).iteritems():
613
 
            revid = self.target.lookup_foreign_revision_id(v)
 
479
        for name, revid in extract_tags(refs, self.target.mapping).iteritems():
614
480
            self.target.tags.set_tag(name, revid)
615
481
 
616
482
    def update_refs(self, stop_revision=None):
617
 
        interrepo = repository.InterRepository.get(self.source.repository,
 
483
        interrepo = repository.InterRepository.get(self.source.repository, 
618
484
            self.target.repository)
619
485
        if stop_revision is None:
620
 
            refs = interrepo.fetch(branches=["HEAD"])
621
 
            stop_revision = self.target.lookup_foreign_revision_id(refs["HEAD"])
 
486
            refs = interrepo.fetch_refs(branches=["HEAD"])
 
487
            stop_revision = self.target.mapping.revision_id_foreign_to_bzr(refs["HEAD"])
622
488
        else:
623
 
            refs = interrepo.fetch(revision_id=stop_revision)
 
489
            refs = interrepo.fetch_refs(revision_id=stop_revision)
624
490
        return refs, stop_revision
625
491
 
626
 
    def pull(self, stop_revision=None, overwrite=False,
627
 
        possible_transports=None, run_hooks=True,local=False):
 
492
    def pull(self, stop_revision=None, overwrite=False, 
 
493
        possible_transports=None, local=False):
628
494
        # This type of branch can't be bound.
629
495
        if local:
630
496
            raise errors.LocalRequiresBoundBranch()
638
504
        result.new_revid = self.target.last_revision()
639
505
        return result
640
506
 
641
 
 
642
 
class InterToGitBranch(branch.GenericInterBranch):
 
507
    
 
508
class InterToGitBranch(branch.InterBranch):
643
509
    """InterBranch implementation that pulls from Git into bzr."""
644
510
 
645
 
    def __init__(self, source, target):
646
 
        super(InterToGitBranch, self).__init__(source, target)
647
 
        self.interrepo = repository.InterRepository.get(source.repository,
648
 
                                           target.repository)
649
 
 
650
 
    @staticmethod
651
 
    def _get_branch_formats_to_test():
652
 
        return []
653
 
 
654
511
    @classmethod
655
512
    def is_compatible(self, source, target):
656
 
        return (not isinstance(source, GitBranch) and
 
513
        return (not isinstance(source, GitBranch) and 
657
514
                isinstance(target, GitBranch))
658
515
 
659
 
    def update_revisions(self, *args, **kwargs):
 
516
    def push(self, overwrite=True, stop_revision=None, 
 
517
             _override_hook_source_branch=None):
660
518
        raise NoPushSupport()
661
519
 
662
 
    def _get_new_refs(self, stop_revision=None):
 
520
    def lossy_push(self, stop_revision=None):
 
521
        result = GitBranchPushResult()
 
522
        result.source_branch = self.source
 
523
        result.target_branch = self.target
 
524
        result.old_revid = self.target.last_revision()
663
525
        if stop_revision is None:
664
526
            stop_revision = self.source.last_revision()
665
 
        assert type(stop_revision) is str
666
 
        main_ref = self.target.ref or "refs/heads/master"
667
 
        refs = { main_ref: (None, stop_revision) }
 
527
        # FIXME: Check for diverged branches
 
528
        refs = { "refs/heads/master": stop_revision }
668
529
        for name, revid in self.source.tags.get_tag_dict().iteritems():
669
530
            if self.source.repository.has_revision(revid):
670
 
                refs[tag_name_to_ref(name)] = (None, revid)
671
 
        return refs, main_ref
672
 
 
673
 
    def pull(self, overwrite=False, stop_revision=None, local=False,
674
 
             possible_transports=None):
675
 
        from dulwich.protocol import ZERO_SHA
676
 
        result = GitBranchPullResult()
677
 
        result.source_branch = self.source
678
 
        result.target_branch = self.target
679
 
        new_refs, main_ref = self._get_new_refs(stop_revision)
680
 
        def update_refs(old_refs):
681
 
            refs = dict(old_refs)
682
 
            # FIXME: Check for diverged branches
683
 
            refs.update(new_refs)
684
 
            return refs
685
 
        old_refs, new_refs = self.interrepo.fetch_refs(update_refs)
686
 
        result.old_revid = self.target.lookup_foreign_revision_id(
687
 
            old_refs.get(main_ref, ZERO_SHA))
688
 
        result.new_revid = new_refs[main_ref]
689
 
        return result
690
 
 
691
 
    def push(self, overwrite=False, stop_revision=None,
692
 
             _override_hook_source_branch=None):
693
 
        from dulwich.protocol import ZERO_SHA
694
 
        result = GitBranchPushResult()
695
 
        result.source_branch = self.source
696
 
        result.target_branch = self.target
697
 
        new_refs, main_ref = self._get_new_refs(stop_revision)
698
 
        def update_refs(old_refs):
699
 
            refs = dict(old_refs)
700
 
            # FIXME: Check for diverged branches
701
 
            refs.update(new_refs)
702
 
            return refs
703
 
        old_refs, new_refs = self.interrepo.fetch_refs(update_refs)
704
 
        (result.old_revid, old_sha1) = old_refs.get(main_ref, (ZERO_SHA, NULL_REVISION))
705
 
        if result.old_revid is None:
706
 
            result.old_revid = self.target.lookup_foreign_revision_id(old_sha1)
707
 
        result.new_revid = new_refs[main_ref]
708
 
        return result
709
 
 
710
 
    def lossy_push(self, stop_revision=None):
711
 
        result = GitBranchPushResult()
712
 
        result.source_branch = self.source
713
 
        result.target_branch = self.target
714
 
        new_refs, main_ref = self._get_new_refs(stop_revision)
715
 
        def update_refs(old_refs):
716
 
            refs = dict(old_refs)
717
 
            # FIXME: Check for diverged branches
718
 
            refs.update(new_refs)
719
 
            return refs
720
 
        result.revidmap, old_refs, new_refs = self.interrepo.dfetch_refs(
721
 
            update_refs)
722
 
        result.old_revid = old_refs.get(self.target.ref, (None, NULL_REVISION))[1]
723
 
        result.new_revid = new_refs[main_ref][1]
 
531
                refs["refs/tags/%s" % name] = revid
 
532
        revidmap, new_refs = self.target.repository.dfetch_refs(
 
533
            self.source.repository, refs)
 
534
        if revidmap != {}:
 
535
            self.target.generate_revision_history(revidmap[stop_revision])
 
536
            result.new_revid = revidmap[stop_revision]
 
537
        else:
 
538
            result.new_revid = result.old_revid
 
539
        result.revidmap = revidmap
724
540
        return result
725
541
 
726
542