147
127
class GitBranch(ForeignBranch):
148
128
"""An adapter to git repositories for bzr Branch objects."""
150
def __init__(self, bzrdir, repository, name, lockfiles, tagsdict=None):
130
def __init__(self, bzrdir, repository, name, lockfiles):
151
131
self.repository = repository
152
132
self._format = GitBranchFormat()
153
133
self.control_files = lockfiles
154
134
self.bzrdir = bzrdir
155
135
super(GitBranch, self).__init__(repository.get_mapping())
156
if tagsdict is not None:
157
self.tags = DictTagDict(self, tagsdict)
159
137
self._head = None
160
self.base = bzrdir.root_transport.base
162
def _get_checkout_format(self):
163
"""Return the most suitable metadir for a checkout of this branch.
164
Weaves are used if this branch's repository uses weaves.
166
return get_rich_root_format()
168
def get_child_submit_format(self):
169
"""Return the preferred format of submissions to this branch."""
170
ret = self.get_config().get_user_option("child_submit_format")
138
self.base = bzrdir.transport.base
175
140
def _get_nick(self, local=False, possible_master_transports=None):
176
141
"""Find the nick name for this branch.
322
283
if self.old_revid == self.new_revid:
323
284
to_file.write('No revisions to pull.\n')
325
to_file.write('Now on revision %d (git sha: %s).\n' %
286
to_file.write('Now on revision %d (git sha: %s).\n' %
326
287
(self.new_revno, self.new_git_head))
327
288
self._show_tag_conficts(to_file)
330
class GitBranchPushResult(branch.BranchPushResult):
332
def _lookup_revno(self, revid):
333
assert isinstance(revid, str), "was %r" % revid
334
# Try in source branch first, it'll be faster
336
return self.source_branch.revision_id_to_revno(revid)
337
except errors.NoSuchRevision:
338
# FIXME: Check using graph.find_distance_to_null() ?
339
return self.target_branch.revision_id_to_revno(revid)
343
return self._lookup_revno(self.old_revid)
347
return self._lookup_revno(self.new_revid)
350
class InterFromGitBranch(branch.GenericInterBranch):
291
class InterFromGitBranch(branch.InterBranch):
351
292
"""InterBranch implementation that pulls from Git into bzr."""
354
def _get_interrepo(self, source, target):
355
return repository.InterRepository.get(source.repository,
359
def is_compatible(cls, source, target):
360
return (isinstance(source, GitBranch) and
361
not isinstance(target, GitBranch) and
362
(getattr(cls._get_interrepo(source, target), "fetch_objects", None) is not None))
295
def is_compatible(self, source, target):
296
return (isinstance(source, GitBranch) and
297
not isinstance(target, GitBranch))
364
299
def update_revisions(self, stop_revision=None, overwrite=False,
366
301
"""See InterBranch.update_revisions()."""
367
interrepo = self._get_interrepo(self.source, self.target)
302
interrepo = repository.InterRepository.get(self.source.repository,
303
self.target.repository)
368
304
self._head = None
369
305
self._last_revid = None
370
306
def determine_wants(heads):
436
372
self.source.unlock()
439
def _basic_push(self, overwrite=False, stop_revision=None):
440
result = branch.BranchPushResult()
441
result.source_branch = self.source
442
result.target_branch = self.target
443
graph = self.target.repository.get_graph(self.source.repository)
444
result.old_revno, result.old_revid = self.target.last_revision_info()
445
self.update_revisions(stop_revision, overwrite=overwrite, graph=graph)
446
result.new_git_head = self._head
447
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
449
result.new_revno, result.new_revid = self.target.last_revision_info()
453
class InterGitBranch(branch.GenericInterBranch):
376
class InterGitRemoteLocalBranch(branch.InterBranch):
454
377
"""InterBranch implementation that pulls between Git branches."""
457
class InterGitLocalRemoteBranch(InterGitBranch):
458
"""InterBranch that copies from a local to a remote git branch."""
461
def is_compatible(self, source, target):
462
from bzrlib.plugins.git.remote import RemoteGitBranch
463
return (isinstance(source, LocalGitBranch) and
464
isinstance(target, RemoteGitBranch))
466
def _basic_push(self, overwrite=False, stop_revision=None):
467
result = GitBranchPushResult()
468
result.source_branch = self.source
469
result.target_branch = self.target
470
if stop_revision is None:
471
stop_revision = self.source.last_revision()
472
# FIXME: Check for diverged branches
473
def get_changed_refs(old_refs):
474
result.old_revid = self.target.mapping.revision_id_foreign_to_bzr(old_refs.get("refs/heads/master", "0" * 40))
475
refs = { "refs/heads/master": self.source.repository.lookup_bzr_revision_id(stop_revision)[0] }
476
result.new_revid = stop_revision
477
for name, sha in self.source.repository._git.refs.as_dict("refs/tags").iteritems():
478
refs["refs/tags/%s" % name] = sha
480
self.target.repository.send_pack(get_changed_refs,
481
self.source.repository._git.object_store.generate_pack_contents)
485
class InterGitRemoteLocalBranch(InterGitBranch):
486
"""InterBranch that copies from a remote to a local git branch."""
489
def is_compatible(self, source, target):
490
from bzrlib.plugins.git.remote import RemoteGitBranch
491
return (isinstance(source, RemoteGitBranch) and
380
def is_compatible(self, source, target):
381
from bzrlib.plugins.git.remote import RemoteGitBranch
382
return (isinstance(source, RemoteGitBranch) and
492
383
isinstance(target, LocalGitBranch))
494
def _basic_push(self, overwrite=False, stop_revision=None):
495
result = branch.BranchPushResult()
385
def pull(self, stop_revision=None, overwrite=False,
386
possible_transports=None, local=False):
387
# This type of branch can't be bound.
389
raise errors.LocalRequiresBoundBranch()
390
result = GitPullResult()
496
391
result.source_branch = self.source
497
392
result.target_branch = self.target
393
interrepo = repository.InterRepository.get(self.source.repository,
394
self.target.repository)
498
395
result.old_revid = self.target.last_revision()
499
refs, stop_revision = self.update_refs(stop_revision)
500
self.target.generate_revision_history(stop_revision, result.old_revid)
501
self.update_tags(refs)
502
result.new_revid = self.target.last_revision()
505
def update_tags(self, refs):
506
for name, v in extract_tags(refs).iteritems():
507
revid = self.target.mapping.revision_id_foreign_to_bzr(v)
508
self.target.tags.set_tag(name, revid)
510
def update_refs(self, stop_revision=None):
511
interrepo = repository.InterRepository.get(self.source.repository,
512
self.target.repository)
513
396
if stop_revision is None:
514
397
refs = interrepo.fetch_refs(branches=["HEAD"])
515
398
stop_revision = self.target.mapping.revision_id_foreign_to_bzr(refs["HEAD"])
517
400
refs = interrepo.fetch_refs(revision_id=stop_revision)
518
return refs, stop_revision
520
def pull(self, stop_revision=None, overwrite=False,
521
possible_transports=None, local=False):
522
# This type of branch can't be bound.
524
raise errors.LocalRequiresBoundBranch()
525
result = GitPullResult()
526
result.source_branch = self.source
527
result.target_branch = self.target
528
result.old_revid = self.target.last_revision()
529
refs, stop_revision = self.update_refs(stop_revision)
530
401
self.target.generate_revision_history(stop_revision, result.old_revid)
531
self.update_tags(refs)
402
for name, revid in extract_tags(refs, self.target.mapping).iteritems():
403
self.target.tags.set_tag(name, revid)
532
404
result.new_revid = self.target.last_revision()
536
408
class InterToGitBranch(branch.InterBranch):
537
409
"""InterBranch implementation that pulls from Git into bzr."""
540
def _get_branch_formats_to_test():
544
412
def is_compatible(self, source, target):
545
return (not isinstance(source, GitBranch) and
413
return (not isinstance(source, GitBranch) and
546
414
isinstance(target, GitBranch))
548
def update_revisions(self, *args, **kwargs):
549
raise NoPushSupport()
551
def push(self, overwrite=True, stop_revision=None,
416
def push(self, overwrite=True, stop_revision=None,
552
417
_override_hook_source_branch=None):
553
418
raise NoPushSupport()
555
420
def lossy_push(self, stop_revision=None):
556
result = GitBranchPushResult()
557
result.source_branch = self.source
558
result.target_branch = self.target
560
result.old_revid = self.target.last_revision()
562
result.old_revid = revision.NULL_REVISION
563
421
if stop_revision is None:
564
422
stop_revision = self.source.last_revision()
565
423
# FIXME: Check for diverged branches