282
330
class GitBranchPullResult(branch.PullResult):
333
super(GitBranchPullResult, self).__init__()
334
self.new_git_head = None
335
self._old_revno = None
336
self._new_revno = None
284
338
def report(self, to_file):
285
339
if not is_quiet():
286
340
if self.old_revid == self.new_revid:
287
341
to_file.write('No revisions to pull.\n')
289
to_file.write('Now on revision %d (git sha: %s).\n' %
342
elif self.new_git_head is not None:
343
to_file.write('Now on revision %d (git sha: %s).\n' %
290
344
(self.new_revno, self.new_git_head))
346
to_file.write('Now on revision %d.\n' % (self.new_revno,))
291
347
self._show_tag_conficts(to_file)
294
class InterFromGitBranch(branch.InterBranch):
349
def _lookup_revno(self, revid):
350
assert isinstance(revid, str), "was %r" % revid
351
# Try in source branch first, it'll be faster
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)
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)
363
def _set_old_revno(self, revno):
364
self._old_revno = revno
366
old_revno = property(_get_old_revno, _set_old_revno)
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)
373
def _set_new_revno(self, revno):
374
self._new_revno = revno
376
new_revno = property(_get_new_revno, _set_new_revno)
379
class GitBranchPushResult(branch.BranchPushResult):
381
def _lookup_revno(self, revid):
382
assert isinstance(revid, str), "was %r" % revid
383
# Try in source branch first, it'll be faster
385
return self.source_branch.revision_id_to_revno(revid)
386
except errors.NoSuchRevision:
387
# FIXME: Check using graph.find_distance_to_null() ?
388
return self.target_branch.revision_id_to_revno(revid)
392
return self._lookup_revno(self.old_revid)
396
return self._lookup_revno(self.new_revid)
399
class InterFromGitBranch(branch.GenericInterBranch):
295
400
"""InterBranch implementation that pulls from Git into bzr."""
298
def is_compatible(self, source, target):
299
return (isinstance(source, GitBranch) and
300
not isinstance(target, GitBranch))
302
def update_revisions(self, stop_revision=None, overwrite=False,
304
"""See InterBranch.update_revisions()."""
305
interrepo = repository.InterRepository.get(self.source.repository,
306
self.target.repository)
308
self._last_revid = None
403
def _get_interrepo(self, source, target):
404
return repository.InterRepository.get(source.repository,
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))
413
def _update_revisions(self, stop_revision=None, overwrite=False,
414
graph=None, limit=None):
415
"""Like InterBranch.update_revisions(), but with additions.
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.
421
interrepo = self._get_interrepo(self.source, self.target)
309
422
def determine_wants(heads):
310
if not self.source.name in heads:
311
raise NoSuchRef(self.source.name, heads.keys())
423
if not self.source.ref in heads:
424
raise NoSuchRef(self.source.ref, heads.keys())
312
425
if stop_revision is not None:
313
426
self._last_revid = stop_revision
314
self._head, mapping = self.source.repository.lookup_git_revid(
427
head, mapping = self.source.repository.lookup_bzr_revision_id(
317
self._head = heads[self.source.name]
319
self.source.mapping.revision_id_foreign_to_bzr(self._head)
430
head = heads[self.source.ref]
431
self._last_revid = self.source.mapping.revision_id_foreign_to_bzr(
320
433
if self.target.repository.has_revision(self._last_revid):
323
interrepo.fetch_objects(determine_wants, self.source.mapping)
436
pack_hint, head = interrepo.fetch_objects(
437
determine_wants, self.source.mapping, limit=limit)
438
if pack_hint is not None and self.target.repository._format.pack_compresses:
439
self.target.repository.pack(hint=pack_hint)
441
self._last_revid = self.source.mapping.revision_id_foreign_to_bzr(head)
325
443
prev_last_revid = None
327
445
prev_last_revid = self.target.last_revision()
328
self.target.generate_revision_history(self._last_revid, prev_last_revid)
446
self.target.generate_revision_history(self._last_revid,
450
def update_revisions(self, stop_revision=None, overwrite=False,
452
"""See InterBranch.update_revisions()."""
453
self._update_revisions(stop_revision, overwrite, graph)
330
455
def pull(self, overwrite=False, stop_revision=None,
331
456
possible_transports=None, _hook_master=None, run_hooks=True,
332
_override_hook_target=None, local=False):
457
_override_hook_target=None, local=False, limit=None):
333
458
"""See Branch.pull.
335
460
:param _hook_master: Private parameter - set the branch to
375
502
self.source.unlock()
379
class InterGitRemoteLocalBranch(branch.InterBranch):
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
graph = self.target.repository.get_graph(self.source.repository)
510
result.old_revno, result.old_revid = self.target.last_revision_info()
511
result.new_git_head = self._update_revisions(
512
stop_revision, overwrite=overwrite, graph=graph)
513
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
515
result.new_revno, result.new_revid = self.target.last_revision_info()
519
class InterGitBranch(branch.GenericInterBranch):
380
520
"""InterBranch implementation that pulls between Git branches."""
383
def is_compatible(self, source, target):
384
from bzrlib.plugins.git.remote import RemoteGitBranch
385
return (isinstance(source, RemoteGitBranch) and
523
class InterGitLocalRemoteBranch(InterGitBranch):
524
"""InterBranch that copies from a local to a remote git branch."""
527
def is_compatible(self, source, target):
528
from bzrlib.plugins.git.remote import RemoteGitBranch
529
return (isinstance(source, LocalGitBranch) and
530
isinstance(target, RemoteGitBranch))
532
def _basic_push(self, overwrite=False, stop_revision=None):
533
from dulwich.protocol import ZERO_SHA
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):
541
result.old_revid = self.target.mapping.revision_id_foreign_to_bzr(old_refs.get(self.target.ref, ZERO_SHA))
542
refs = { self.target.ref: self.source.repository.lookup_bzr_revision_id(stop_revision)[0] }
543
result.new_revid = stop_revision
544
for name, sha in self.source.repository._git.refs.as_dict("refs/tags").iteritems():
545
refs[tag_name_to_ref(name)] = sha
547
self.target.repository.send_pack(get_changed_refs,
548
self.source.repository._git.object_store.generate_pack_contents)
552
class InterGitRemoteLocalBranch(InterGitBranch):
553
"""InterBranch that copies from a remote to a local git branch."""
556
def is_compatible(self, source, target):
557
from bzrlib.plugins.git.remote import RemoteGitBranch
558
return (isinstance(source, RemoteGitBranch) and
386
559
isinstance(target, LocalGitBranch))
388
def pull(self, stop_revision=None, overwrite=False,
389
possible_transports=None, local=False):
390
# This type of branch can't be bound.
392
raise errors.LocalRequiresBoundBranch()
393
result = GitPullResult()
561
def _basic_push(self, overwrite=False, stop_revision=None):
562
result = branch.BranchPushResult()
394
563
result.source_branch = self.source
395
564
result.target_branch = self.target
396
interrepo = repository.InterRepository.get(self.source.repository,
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)
569
result.new_revid = self.target.last_revision()
572
def update_tags(self, refs):
573
for name, v in extract_tags(refs).iteritems():
574
revid = self.target.mapping.revision_id_foreign_to_bzr(v)
575
self.target.tags.set_tag(name, revid)
577
def update_refs(self, stop_revision=None):
578
interrepo = repository.InterRepository.get(self.source.repository,
397
579
self.target.repository)
398
result.old_revid = self.target.last_revision()
399
580
if stop_revision is None:
400
581
refs = interrepo.fetch_refs(branches=["HEAD"])
401
582
stop_revision = self.target.mapping.revision_id_foreign_to_bzr(refs["HEAD"])
403
584
refs = interrepo.fetch_refs(revision_id=stop_revision)
585
return refs, stop_revision
587
def pull(self, stop_revision=None, overwrite=False,
588
possible_transports=None, run_hooks=True,local=False):
589
# This type of branch can't be bound.
591
raise errors.LocalRequiresBoundBranch()
592
result = GitPullResult()
593
result.source_branch = self.source
594
result.target_branch = self.target
595
result.old_revid = self.target.last_revision()
596
refs, stop_revision = self.update_refs(stop_revision)
404
597
self.target.generate_revision_history(stop_revision, result.old_revid)
405
for name, revid in extract_tags(refs, self.target.mapping).iteritems():
406
self.target.tags.set_tag(name, revid)
598
self.update_tags(refs)
407
599
result.new_revid = self.target.last_revision()
411
603
class InterToGitBranch(branch.InterBranch):
412
604
"""InterBranch implementation that pulls from Git into bzr."""
607
def _get_branch_formats_to_test():
415
611
def is_compatible(self, source, target):
416
return (not isinstance(source, GitBranch) and
612
return (not isinstance(source, GitBranch) and
417
613
isinstance(target, GitBranch))
419
def push(self, overwrite=True, stop_revision=None,
420
_override_hook_source_branch=None):
615
def update_revisions(self, *args, **kwargs):
421
616
raise NoPushSupport()
423
def lossy_push(self, stop_revision=None):
618
def _get_new_refs(self, stop_revision=None):
424
619
if stop_revision is None:
425
620
stop_revision = self.source.last_revision()
426
# FIXME: Check for diverged branches
427
refs = { "refs/heads/master": stop_revision }
621
refs = { self.target.ref: stop_revision }
428
622
for name, revid in self.source.tags.get_tag_dict().iteritems():
429
623
if self.source.repository.has_revision(revid):
430
refs["refs/tags/%s" % name] = revid
431
revidmap, new_refs = self.target.repository.dfetch_refs(
624
refs[tag_name_to_ref(name)] = revid
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()
635
refs = dict(old_refs)
636
refs.update(self._get_new_refs(stop_revision))
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]
643
def push(self, overwrite=False, stop_revision=None,
644
_override_hook_source_branch=None):
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()
651
refs = dict(old_refs)
652
refs.update(self._get_new_refs(stop_revision))
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]
659
def lossy_push(self, stop_revision=None):
660
from dulwich.protocol import ZERO_SHA
661
result = GitBranchPushResult()
662
result.source_branch = self.source
663
result.target_branch = self.target
664
# FIXME: Check for diverged branches
665
refs = self._get_new_refs(stop_revision)
666
result.revidmap, old_refs, new_refs = self.target.repository.dfetch_refs(
432
667
self.source.repository, refs)
434
self.target.generate_revision_history(revidmap[stop_revision])
668
result.old_revid = self.target.mapping.revision_id_foreign_to_bzr(
669
old_refs.get(self.target.ref, ZERO_SHA))
670
result.new_revid = self.target.mapping.revision_id_foreign_to_bzr(
671
new_refs[self.target.ref])
438
675
branch.InterBranch.register_optimiser(InterGitRemoteLocalBranch)
439
676
branch.InterBranch.register_optimiser(InterFromGitBranch)
440
677
branch.InterBranch.register_optimiser(InterToGitBranch)
678
branch.InterBranch.register_optimiser(InterGitLocalRemoteBranch)