141
156
def __repr__(self):
142
157
return "%s(%r, %r)" % (self.__class__.__name__, self.repository.base, self.name)
144
def dpull(self, source, stop_revision=None):
145
if stop_revision is None:
146
stop_revision = source.last_revision()
147
# FIXME: Check for diverged branches
148
refs = { "refs/heads/master": stop_revision }
149
for name, revid in source.tags.get_tag_dict().iteritems():
150
if source.repository.has_revision(revid):
151
refs["refs/tags/%s" % name] = revid
152
revidmap, new_refs = self.repository.dfetch_refs(source.repository,
155
self.generate_revision_history(revidmap[stop_revision])
158
159
def generate_revision_history(self, revid, old_revid=None):
159
160
# FIXME: Check that old_revid is in the ancestry of revid
160
161
newhead, self.mapping = self.mapping.revision_id_bzr_to_foreign(revid)
252
257
def _get_head(self):
253
return self.repository._git.ref(self.name)
259
return self.repository._git.ref(self.name)
263
def set_last_revision_info(self, revno, revid):
264
self.set_last_revision(revid)
266
def set_last_revision(self, revid):
267
(newhead, self.mapping) = self.mapping.revision_id_bzr_to_foreign(
255
271
def _set_head(self, value):
256
272
self._head = value
257
self.repository._git.set_ref(self.name, self._head)
273
self.repository._git.refs[self.name] = self._head
258
274
self._clear_cached_state()
260
276
head = property(_get_head, _set_head)
288
304
self._show_tag_conficts(to_file)
291
class InterGitGenericBranch(branch.InterBranch):
307
class GitBranchPushResult(branch.BranchPushResult):
309
def _lookup_revno(self, revid):
310
assert isinstance(revid, str), "was %r" % revid
311
# Try in source branch first, it'll be faster
313
return self.source_branch.revision_id_to_revno(revid)
314
except errors.NoSuchRevision:
315
# FIXME: Check using graph.find_distance_to_null() ?
316
return self.target_branch.revision_id_to_revno(revid)
320
return self._lookup_revno(self.old_revid)
324
return self._lookup_revno(self.new_revid)
327
class InterFromGitBranch(branch.GenericInterBranch):
292
328
"""InterBranch implementation that pulls from Git into bzr."""
372
408
self.source.unlock()
378
branch.InterBranch.register_optimiser(InterGitGenericBranch)
381
class InterGitRemoteLocalBranch(branch.InterBranch):
411
def _basic_push(self, overwrite=False, stop_revision=None):
412
result = branch.BranchPushResult()
413
result.source_branch = self.source
414
result.target_branch = self.target
415
graph = self.target.repository.get_graph(self.source.repository)
416
result.old_revno, result.old_revid = self.target.last_revision_info()
417
self.update_revisions(stop_revision, overwrite=overwrite,
419
result.new_git_head = self._head
420
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
422
result.new_revno, result.new_revid = self.target.last_revision_info()
426
class InterGitBranch(branch.GenericInterBranch):
382
427
"""InterBranch implementation that pulls between Git branches."""
430
class InterGitLocalRemoteBranch(InterGitBranch):
431
"""InterBranch that copies from a local to a remote git branch."""
434
def is_compatible(self, source, target):
435
from bzrlib.plugins.git.remote import RemoteGitBranch
436
return (isinstance(source, LocalGitBranch) and
437
isinstance(target, RemoteGitBranch))
439
def _basic_push(self, overwrite=False, stop_revision=None):
440
result = GitBranchPushResult()
441
result.source_branch = self.source
442
result.target_branch = self.target
443
if stop_revision is None:
444
stop_revision = self.source.last_revision()
445
# FIXME: Check for diverged branches
446
def get_changed_refs(old_refs):
447
result.old_revid = self.target.mapping.revision_id_foreign_to_bzr(old_refs.get("refs/heads/master", "0" * 40))
448
refs = { "refs/heads/master": self.source.repository.lookup_git_revid(stop_revision)[0] }
449
result.new_revid = stop_revision
450
for name, sha in self.source.repository._git.refs.as_dict("refs/tags").iteritems():
451
refs["refs/tags/%s" % name] = sha
453
self.target.repository.send_pack(get_changed_refs,
454
self.source.repository._git.object_store.generate_pack_contents)
458
class InterGitRemoteLocalBranch(InterGitBranch):
459
"""InterBranch that copies from a remote to a local git branch."""
385
462
def is_compatible(self, source, target):
386
463
from bzrlib.plugins.git.remote import RemoteGitBranch
387
464
return (isinstance(source, RemoteGitBranch) and
388
465
isinstance(target, LocalGitBranch))
467
def _basic_push(self, overwrite=False, stop_revision=None):
468
result = branch.BranchPushResult()
469
result.source_branch = self.source
470
result.target_branch = self.target
471
result.old_revid = self.target.last_revision()
472
refs, stop_revision = self.update_refs(stop_revision)
473
self.target.generate_revision_history(stop_revision, result.old_revid)
474
self.update_tags(refs)
475
result.new_revid = self.target.last_revision()
478
def update_tags(self, refs):
479
for name, revid in extract_tags(refs, self.target.mapping).iteritems():
480
self.target.tags.set_tag(name, revid)
482
def update_refs(self, stop_revision=None):
483
interrepo = repository.InterRepository.get(self.source.repository,
484
self.target.repository)
485
if stop_revision is None:
486
refs = interrepo.fetch_refs(branches=["HEAD"])
487
stop_revision = self.target.mapping.revision_id_foreign_to_bzr(refs["HEAD"])
489
refs = interrepo.fetch_refs(revision_id=stop_revision)
490
return refs, stop_revision
390
492
def pull(self, stop_revision=None, overwrite=False,
391
493
possible_transports=None, local=False):
392
494
# This type of branch can't be bound.
395
497
result = GitPullResult()
396
498
result.source_branch = self.source
397
499
result.target_branch = self.target
398
interrepo = repository.InterRepository.get(self.source.repository,
399
self.target.repository)
500
result.old_revid = self.target.last_revision()
501
refs, stop_revision = self.update_refs(stop_revision)
502
self.target.generate_revision_history(stop_revision, result.old_revid)
503
self.update_tags(refs)
504
result.new_revid = self.target.last_revision()
508
class InterToGitBranch(branch.InterBranch):
509
"""InterBranch implementation that pulls from Git into bzr."""
512
def is_compatible(self, source, target):
513
return (not isinstance(source, GitBranch) and
514
isinstance(target, GitBranch))
516
def update_revisions(self, *args, **kwargs):
517
raise NoPushSupport()
519
def push(self, overwrite=True, stop_revision=None,
520
_override_hook_source_branch=None):
521
raise NoPushSupport()
523
def lossy_push(self, stop_revision=None):
524
result = GitBranchPushResult()
525
result.source_branch = self.source
526
result.target_branch = self.target
400
527
result.old_revid = self.target.last_revision()
401
528
if stop_revision is None:
402
refs = interrepo.fetch_refs(branches=["HEAD"])
403
stop_revision = self.target.mapping.revision_id_foreign_to_bzr(refs["HEAD"])
529
stop_revision = self.source.last_revision()
530
# FIXME: Check for diverged branches
531
refs = { "refs/heads/master": stop_revision }
532
for name, revid in self.source.tags.get_tag_dict().iteritems():
533
if self.source.repository.has_revision(revid):
534
refs["refs/tags/%s" % name] = revid
535
revidmap, new_refs = self.target.repository.dfetch_refs(
536
self.source.repository, refs)
538
self.target.generate_revision_history(revidmap[stop_revision])
539
result.new_revid = revidmap[stop_revision]
405
refs = interrepo.fetch_refs(revision_id=stop_revision)
406
self.target.generate_revision_history(stop_revision, result.old_revid)
407
result.new_revid = self.target.last_revision()
541
result.new_revid = result.old_revid
542
result.revidmap = revidmap
411
546
branch.InterBranch.register_optimiser(InterGitRemoteLocalBranch)
547
branch.InterBranch.register_optimiser(InterFromGitBranch)
548
branch.InterBranch.register_optimiser(InterToGitBranch)
549
branch.InterBranch.register_optimiser(InterGitLocalRemoteBranch)