127
140
class GitBranch(ForeignBranch):
128
141
"""An adapter to git repositories for bzr Branch objects."""
130
def __init__(self, bzrdir, repository, name, lockfiles):
143
def __init__(self, bzrdir, repository, name, lockfiles, tagsdict=None):
131
144
self.repository = repository
132
145
self._format = GitBranchFormat()
133
146
self.control_files = lockfiles
134
147
self.bzrdir = bzrdir
135
148
super(GitBranch, self).__init__(repository.get_mapping())
149
if tagsdict is not None:
150
self.tags = DictTagDict(self, tagsdict)
137
152
self._head = None
138
153
self.base = bzrdir.transport.base
155
def _get_checkout_format(self):
156
"""Return the most suitable metadir for a checkout of this branch.
157
Weaves are used if this branch's repository uses weaves.
159
return get_rich_root_format()
161
def get_child_submit_format(self):
162
"""Return the preferred format of submissions to this branch."""
163
ret = self.get_config().get_user_option("child_submit_format")
140
168
def _get_nick(self, local=False, possible_master_transports=None):
141
169
"""Find the nick name for this branch.
195
220
return revision.NULL_REVISION
196
221
return self.mapping.revision_id_foreign_to_bzr(self.head)
223
def _basic_push(self, target, overwrite=False, stop_revision=None):
224
return branch.InterBranch.get(self, target)._basic_push(
225
overwrite, stop_revision)
199
228
class LocalGitBranch(GitBranch):
200
229
"""A local Git branch."""
202
def _get_checkout_format(self):
203
"""Return the most suitable metadir for a checkout of this branch.
204
Weaves are used if this branch's repository uses weaves.
206
format = self.repository.bzrdir.checkout_metadir()
207
format.set_branch_format(self._format)
210
231
def create_checkout(self, to_location, revision_id=None, lightweight=False,
211
232
accelerator_tree=None, hardlink=False):
291
320
self._show_tag_conficts(to_file)
294
class InterFromGitBranch(branch.InterBranch):
323
class GitBranchPushResult(branch.BranchPushResult):
325
def _lookup_revno(self, revid):
326
assert isinstance(revid, str), "was %r" % revid
327
# Try in source branch first, it'll be faster
329
return self.source_branch.revision_id_to_revno(revid)
330
except errors.NoSuchRevision:
331
# FIXME: Check using graph.find_distance_to_null() ?
332
return self.target_branch.revision_id_to_revno(revid)
336
return self._lookup_revno(self.old_revid)
340
return self._lookup_revno(self.new_revid)
343
class InterFromGitBranch(branch.GenericInterBranch):
295
344
"""InterBranch implementation that pulls from Git into bzr."""
375
424
self.source.unlock()
379
class InterGitRemoteLocalBranch(branch.InterBranch):
427
def _basic_push(self, overwrite=False, stop_revision=None):
428
result = branch.BranchPushResult()
429
result.source_branch = self.source
430
result.target_branch = self.target
431
graph = self.target.repository.get_graph(self.source.repository)
432
result.old_revno, result.old_revid = self.target.last_revision_info()
433
self.update_revisions(stop_revision, overwrite=overwrite,
435
result.new_git_head = self._head
436
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
438
result.new_revno, result.new_revid = self.target.last_revision_info()
442
class InterGitBranch(branch.GenericInterBranch):
380
443
"""InterBranch implementation that pulls between Git branches."""
446
class InterGitLocalRemoteBranch(InterGitBranch):
447
"""InterBranch that copies from a local to a remote git branch."""
450
def is_compatible(self, source, target):
451
from bzrlib.plugins.git.remote import RemoteGitBranch
452
return (isinstance(source, LocalGitBranch) and
453
isinstance(target, RemoteGitBranch))
455
def _basic_push(self, overwrite=False, stop_revision=None):
456
result = GitBranchPushResult()
457
result.source_branch = self.source
458
result.target_branch = self.target
459
if stop_revision is None:
460
stop_revision = self.source.last_revision()
461
# FIXME: Check for diverged branches
462
def get_changed_refs(old_refs):
463
result.old_revid = self.target.mapping.revision_id_foreign_to_bzr(old_refs.get("refs/heads/master", "0" * 40))
464
refs = { "refs/heads/master": self.source.repository.lookup_git_revid(stop_revision)[0] }
465
result.new_revid = stop_revision
466
for name, sha in self.source.repository._git.refs.as_dict("refs/tags").iteritems():
467
refs["refs/tags/%s" % name] = sha
469
self.target.repository.send_pack(get_changed_refs,
470
self.source.repository._git.object_store.generate_pack_contents)
474
class InterGitRemoteLocalBranch(InterGitBranch):
475
"""InterBranch that copies from a remote to a local git branch."""
383
478
def is_compatible(self, source, target):
384
479
from bzrlib.plugins.git.remote import RemoteGitBranch
385
480
return (isinstance(source, RemoteGitBranch) and
386
481
isinstance(target, LocalGitBranch))
483
def _basic_push(self, overwrite=False, stop_revision=None):
484
result = branch.BranchPushResult()
485
result.source_branch = self.source
486
result.target_branch = self.target
487
result.old_revid = self.target.last_revision()
488
refs, stop_revision = self.update_refs(stop_revision)
489
self.target.generate_revision_history(stop_revision, result.old_revid)
490
self.update_tags(refs)
491
result.new_revid = self.target.last_revision()
494
def update_tags(self, refs):
495
for name, revid in extract_tags(refs, self.target.mapping).iteritems():
496
self.target.tags.set_tag(name, revid)
498
def update_refs(self, stop_revision=None):
499
interrepo = repository.InterRepository.get(self.source.repository,
500
self.target.repository)
501
if stop_revision is None:
502
refs = interrepo.fetch_refs(branches=["HEAD"])
503
stop_revision = self.target.mapping.revision_id_foreign_to_bzr(refs["HEAD"])
505
refs = interrepo.fetch_refs(revision_id=stop_revision)
506
return refs, stop_revision
388
508
def pull(self, stop_revision=None, overwrite=False,
389
509
possible_transports=None, local=False):
390
510
# This type of branch can't be bound.
393
513
result = GitPullResult()
394
514
result.source_branch = self.source
395
515
result.target_branch = self.target
396
interrepo = repository.InterRepository.get(self.source.repository,
397
self.target.repository)
398
516
result.old_revid = self.target.last_revision()
399
if stop_revision is None:
400
refs = interrepo.fetch_refs(branches=["HEAD"])
401
stop_revision = self.target.mapping.revision_id_foreign_to_bzr(refs["HEAD"])
403
refs = interrepo.fetch_refs(revision_id=stop_revision)
517
refs, stop_revision = self.update_refs(stop_revision)
404
518
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)
519
self.update_tags(refs)
407
520
result.new_revid = self.target.last_revision()
416
529
return (not isinstance(source, GitBranch) and
417
530
isinstance(target, GitBranch))
532
def update_revisions(self, *args, **kwargs):
533
raise NoPushSupport()
419
535
def push(self, overwrite=True, stop_revision=None,
420
536
_override_hook_source_branch=None):
421
537
raise NoPushSupport()
423
539
def lossy_push(self, stop_revision=None):
540
result = GitBranchPushResult()
541
result.source_branch = self.source
542
result.target_branch = self.target
544
result.old_revid = self.target.last_revision()
546
result.old_revid = revision.NULL_REVISION
424
547
if stop_revision is None:
425
548
stop_revision = self.source.last_revision()
426
549
# FIXME: Check for diverged branches