Skip to content

Commit 95b0c60

Browse files
felipecgitster
authored andcommitted
remote-bzr: add support for bzr repos
In bazaar, a repository can contain multiple branches, and previously we were supporting only one branch at a time. Now we fetch them all. Signed-off-by: Felipe Contreras <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5df4fad commit 95b0c60

File tree

2 files changed

+138
-56
lines changed

2 files changed

+138
-56
lines changed

contrib/remote-helpers/git-remote-bzr

Lines changed: 102 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import bzrlib.generate_ids
2727
import bzrlib.transport
2828
import bzrlib.errors
2929
import bzrlib.ui
30+
import bzrlib.urlutils
3031

3132
import sys
3233
import os
@@ -250,12 +251,13 @@ def export_files(tree, files):
250251

251252
return final
252253

253-
def export_branch(branch, name):
254+
def export_branch(repo, name):
254255
global prefix
255256

256257
ref = '%s/heads/%s' % (prefix, name)
257258
tip = marks.get_tip(name)
258259

260+
branch = branches[name]
259261
repo = branch.repository
260262

261263
branch.lock_read()
@@ -323,7 +325,7 @@ def export_branch(branch, name):
323325

324326
count += 1
325327
if (count % 100 == 0):
326-
print "progress revision %s (%d/%d)" % (revid, count, len(revs))
328+
print "progress revision %s '%s' (%d/%d)" % (revid, name, count, len(revs))
327329
print "#############################################################"
328330

329331
branch.unlock()
@@ -348,7 +350,7 @@ def export_tag(repo, name):
348350
def do_import(parser):
349351
global dirname
350352

351-
branch = parser.repo
353+
repo = parser.repo
352354
path = os.path.join(dirname, 'marks-git')
353355

354356
print "feature done"
@@ -362,10 +364,10 @@ def do_import(parser):
362364
ref = parser[1]
363365
if ref.startswith('refs/heads/'):
364366
name = ref[len('refs/heads/'):]
365-
export_branch(branch, name)
367+
export_branch(repo, name)
366368
if ref.startswith('refs/tags/'):
367369
name = ref[len('refs/tags/'):]
368-
export_tag(branch, name)
370+
export_tag(repo, name)
369371
parser.next()
370372

371373
print 'done'
@@ -551,8 +553,11 @@ def parse_commit(parser):
551553
ref = parser[1]
552554
parser.next()
553555

554-
if ref != 'refs/heads/master':
555-
die("bzr doesn't support multiple branches; use 'master'")
556+
if ref.startswith('refs/heads/'):
557+
name = ref[len('refs/heads/'):]
558+
branch = branches[name]
559+
else:
560+
die('unknown ref')
556561

557562
commit_mark = parser.get_mark()
558563
parser.next()
@@ -588,8 +593,6 @@ def parse_commit(parser):
588593
path = c_style_unescape(path).decode('utf-8')
589594
files[path] = f
590595

591-
branch = parser.repo
592-
593596
committer, date, tz = committer
594597
parents = [str(mark_to_rev(p)) for p in parents]
595598
revid = bzrlib.generate_ids.gen_revision_id(committer, date)
@@ -621,9 +624,6 @@ def parse_reset(parser):
621624
ref = parser[1]
622625
parser.next()
623626

624-
if ref != 'refs/heads/master':
625-
die("bzr doesn't support multiple branches; use 'master'")
626-
627627
# ugh
628628
if parser.check('commit'):
629629
parse_commit(parser)
@@ -636,7 +636,7 @@ def parse_reset(parser):
636636
parsed_refs[ref] = mark_to_rev(from_mark)
637637

638638
def do_export(parser):
639-
global parsed_refs, dirname, peer
639+
global parsed_refs, dirname
640640

641641
parser.next()
642642

@@ -654,23 +654,24 @@ def do_export(parser):
654654
else:
655655
die('unhandled export command: %s' % line)
656656

657-
branch = parser.repo
658-
659657
for ref, revid in parsed_refs.iteritems():
660-
if ref == 'refs/heads/master':
661-
branch.generate_revision_history(revid, marks.get_tip('master'))
662-
if peer:
663-
try:
664-
branch.push(peer, stop_revision=revid)
665-
except bzrlib.errors.DivergedBranches:
666-
print "error %s non-fast forward" % ref
667-
continue
658+
name = ref[len('refs/heads/'):]
659+
branch = branches[name]
660+
branch.generate_revision_history(revid, marks.get_tip(name))
668661

662+
if name in peers:
663+
peer = peers[name]
669664
try:
670-
wt = branch.bzrdir.open_workingtree()
671-
wt.update()
672-
except bzrlib.errors.NoWorkingTree:
673-
pass
665+
peer.bzrdir.push_branch(branch, revision_id=revid)
666+
except bzrlib.errors.DivergedBranches:
667+
print "error %s non-fast forward" % ref
668+
continue
669+
670+
try:
671+
wt = branch.bzrdir.open_workingtree()
672+
wt.update()
673+
except bzrlib.errors.NoWorkingTree:
674+
pass
674675

675676
print "ok %s" % ref
676677

@@ -697,9 +698,15 @@ def ref_is_valid(name):
697698

698699
def do_list(parser):
699700
global tags
700-
print "? refs/heads/%s" % 'master'
701701

702-
branch = parser.repo
702+
master_branch = None
703+
704+
for name in branches:
705+
if not master_branch:
706+
master_branch = name
707+
print "? refs/heads/%s" % name
708+
709+
branch = branches[master_branch]
703710
branch.lock_read()
704711
for tag, revid in branch.tags.get_tag_dict().items():
705712
try:
@@ -711,41 +718,77 @@ def do_list(parser):
711718
print "? refs/tags/%s" % tag
712719
tags[tag] = revid
713720
branch.unlock()
714-
print "@refs/heads/%s HEAD" % 'master'
721+
722+
print "@refs/heads/%s HEAD" % master_branch
715723
print
716724

725+
def get_remote_branch(origin, remote_branch, name):
726+
global dirname, peers
727+
728+
branch_path = os.path.join(dirname, 'clone', name)
729+
if os.path.exists(branch_path):
730+
# pull
731+
d = bzrlib.bzrdir.BzrDir.open(branch_path)
732+
branch = d.open_branch()
733+
try:
734+
branch.pull(remote_branch, [], None, False)
735+
except bzrlib.errors.DivergedBranches:
736+
# use remote branch for now
737+
return remote_branch
738+
else:
739+
# clone
740+
d = origin.sprout(branch_path, None,
741+
hardlink=True, create_tree_if_local=False,
742+
force_new_repo=False,
743+
source_branch=remote_branch)
744+
branch = d.open_branch()
745+
746+
return branch
747+
717748
def get_repo(url, alias):
718-
global dirname, peer
749+
global dirname, peer, branches
719750

751+
normal_url = bzrlib.urlutils.normalize_url(url)
720752
origin = bzrlib.bzrdir.BzrDir.open(url)
721-
branch = origin.open_branch()
722-
723-
if not isinstance(origin.transport, bzrlib.transport.local.LocalTransport):
724-
clone_path = os.path.join(dirname, 'clone')
725-
remote_branch = branch
726-
if os.path.exists(clone_path):
727-
# pull
728-
d = bzrlib.bzrdir.BzrDir.open(clone_path)
729-
branch = d.open_branch()
730-
try:
731-
result = branch.pull(remote_branch, [], None, False)
732-
except bzrlib.errors.DivergedBranches:
733-
# use remote branch for now
734-
peer = None
735-
return remote_branch
753+
is_local = isinstance(origin.transport, bzrlib.transport.local.LocalTransport)
754+
755+
clone_path = os.path.join(dirname, 'clone')
756+
757+
try:
758+
repo = origin.open_repository()
759+
except bzrlib.errors.NoRepositoryPresent:
760+
# branch
761+
762+
name = 'master'
763+
branch = origin.open_branch()
764+
765+
if not is_local:
766+
if not os.path.exists(clone_path):
767+
os.mkdir(clone_path)
768+
peers[name] = branch
769+
branches[name] = get_remote_branch(origin, branch, name)
736770
else:
737-
# clone
738-
d = origin.sprout(clone_path, None,
739-
hardlink=True, create_tree_if_local=False,
740-
source_branch=remote_branch)
741-
branch = d.open_branch()
742-
branch.bind(remote_branch)
743-
744-
peer = remote_branch
771+
branches[name] = branch
772+
773+
return branch.repository
745774
else:
746-
peer = None
775+
# repository
747776

748-
return branch
777+
if not is_local and not os.path.exists(clone_path):
778+
clonedir = bzrlib.bzrdir.BzrDir.create(clone_path)
779+
780+
for branch in repo.find_branches():
781+
782+
name = repo.user_transport.relpath(branch.base)
783+
name = name if name != '' else 'master'
784+
785+
if not is_local:
786+
peers[name] = branch
787+
branches[name] = get_remote_branch(origin, branch, name)
788+
else:
789+
branches[name] = branch
790+
791+
return repo
749792

750793
def fix_path(alias, orig_url):
751794
url = urlparse.urlparse(orig_url, 'file')
@@ -762,6 +805,7 @@ def main(args):
762805
global parsed_refs
763806
global files_cache
764807
global is_tmp
808+
global branches, peers
765809

766810
alias = args[1]
767811
url = args[2]
@@ -772,6 +816,8 @@ def main(args):
772816
parsed_refs = {}
773817
files_cache = {}
774818
marks = None
819+
branches = {}
820+
peers = {}
775821

776822
if alias[5:] == url:
777823
is_tmp = True

contrib/remote-helpers/test-bzr.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,4 +264,40 @@ test_expect_success 'pushing a merge' '
264264
test_cmp expected actual
265265
'
266266

267+
cat > expected <<EOF
268+
origin/HEAD
269+
origin/branch
270+
origin/trunk
271+
EOF
272+
273+
test_expect_success 'proper bzr repo' '
274+
mkdir -p tmp && cd tmp &&
275+
test_when_finished "cd .. && rm -rf tmp" &&
276+
277+
bzr init-repo bzrrepo &&
278+
279+
bzr init bzrrepo/trunk &&
280+
(
281+
cd bzrrepo/trunk &&
282+
echo one >> content &&
283+
bzr add content &&
284+
bzr commit -m one
285+
) &&
286+
287+
bzr branch bzrrepo/trunk bzrrepo/branch &&
288+
(
289+
cd bzrrepo/branch &&
290+
echo two >> content &&
291+
bzr commit -m one
292+
) &&
293+
294+
git clone "bzr::$PWD/bzrrepo" gitrepo &&
295+
(
296+
cd gitrepo &&
297+
git for-each-ref --format "%(refname:short)" refs/remotes/origin > ../actual
298+
) &&
299+
300+
test_cmp ../expected actual
301+
'
302+
267303
test_done

0 commit comments

Comments
 (0)