@@ -27,6 +27,7 @@ import bzrlib.generate_ids
2727import bzrlib .transport
2828import bzrlib .errors
2929import bzrlib .ui
30+ import bzrlib .urlutils
3031
3132import sys
3233import 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):
348350def 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
638638def 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
698699def 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+
717748def 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
750793def 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
0 commit comments