comparison fetch_command.py @ 203:907c160c6289

Refactor branch handling to be much more dynamic (and hopefully robust). This should allow fixing of several outstanding issues with branch handling. Note that this is a *massive* change to one of the oldest parts of hgsubversion, so it might introduce bugs not caught by the testsuite.
author Augie Fackler <durin42@gmail.com>
date Mon, 02 Mar 2009 23:58:38 -0600
parents 2e8c527f0456
children a360ddc97719 2165461d2dd8
comparison
equal deleted inserted replaced
202:125cf3cb7bee 203:907c160c6289
67 raise merc_util.Abort('Revision skipping at repository initialization ' 67 raise merc_util.Abort('Revision skipping at repository initialization '
68 'remains unimplemented.') 68 'remains unimplemented.')
69 69
70 # start converting revisions 70 # start converting revisions
71 for r in svn.revisions(start=start): 71 for r in svn.revisions(start=start):
72 valid = False 72 valid = True
73 hg_editor.update_branch_tag_map_for_rev(r) 73 hg_editor.update_branch_tag_map_for_rev(r)
74 for p in r.paths: 74 for p in r.paths:
75 if hg_editor._is_path_valid(p): 75 if hg_editor._is_path_valid(p):
76 valid = True 76 valid = True
77 break 77 break
222 Return a tuple (files, filectxfn) where 'files' is the list of all files 222 Return a tuple (files, filectxfn) where 'files' is the list of all files
223 in the branch at the given revision, and 'filectxfn' is a memctx compatible 223 in the branch at the given revision, and 'filectxfn' is a memctx compatible
224 callable to retrieve individual file information. Raise BadPatchApply upon 224 callable to retrieve individual file information. Raise BadPatchApply upon
225 error. 225 error.
226 """ 226 """
227 def make_diff_path(b): 227 def make_diff_path(branch):
228 if b == None: 228 if branch == 'trunk' or branch is None:
229 return 'trunk' 229 return 'trunk'
230 return 'branches/' + b 230 elif branch.startswith('../'):
231 231 return branch[3:]
232 return 'branches/%s' % branch
232 parent_rev, br_p = hg_editor.get_parent_svn_branch_and_rev(r.revnum, branch) 233 parent_rev, br_p = hg_editor.get_parent_svn_branch_and_rev(r.revnum, branch)
233 diff_path = make_diff_path(branch) 234 diff_path = make_diff_path(branch)
234 try: 235 try:
235 if br_p == branch: 236 if br_p == branch:
236 # letting patch handle binaries sounded 237 # letting patch handle binaries sounded
552 553
553 return files, filectxfn 554 return files, filectxfn
554 555
555 def stupid_svn_server_pull_rev(ui, svn, hg_editor, r): 556 def stupid_svn_server_pull_rev(ui, svn, hg_editor, r):
556 # this server fails at replay 557 # this server fails at replay
557 branches = hg_editor.branches_in_paths(r.paths) 558 branches = hg_editor.branches_in_paths(r.paths, r.revnum, svn.checkpath, svn.list_files)
558 deleted_branches = {} 559 deleted_branches = {}
560 brpaths = branches.values()
561 bad_branch_paths = {}
562 for br, bp in branches.iteritems():
563 bad_branch_paths[br] = []
564
565 # This next block might be needed, but for now I'm omitting it until it can be
566 # proven necessary.
567 # for bad in brpaths:
568 # if bad.startswith(bp) and len(bad) > len(bp):
569 # bad_branch_paths[br].append(bad[len(bp)+1:])
570
571 # We've go a branch that contains other branches. We have to be careful to
572 # get results similar to real replay in this case.
573 for existingbr in hg_editor.branches:
574 bad = hg_editor._remotename(existingbr)
575 if bad.startswith(bp) and len(bad) > len(bp):
576 bad_branch_paths[br].append(bad[len(bp)+1:])
577 for p in r.paths:
578 if hg_editor._is_path_tag(p):
579 continue
580 branch = hg_editor._localname(p)
581 if r.paths[p].action == 'R' and branch in hg_editor.branches:
582 branchedits = sorted(filter(lambda x: x[0][1] == branch and x[0][0] < r.revnum,
583 hg_editor.revmap.iteritems()), reverse=True)
584 is_closed = False
585 if len(branchedits) > 0:
586 branchtip = branchedits[0][1]
587 for child in hg_editor.repo[branchtip].children():
588 if child.branch() == 'closed-branches':
589 is_closed = True
590 break
591 if not is_closed:
592 deleted_branches[branch] = branchtip
559 date = r.date.replace('T', ' ').replace('Z', '').split('.')[0] 593 date = r.date.replace('T', ' ').replace('Z', '').split('.')[0]
560 date += ' -0000' 594 date += ' -0000'
561 check_deleted_branches = set() 595 check_deleted_branches = set()
562 for b in branches: 596 for b in branches:
563 parentctx = hg_editor.repo[hg_editor.get_parent_revision(r.revnum, b)] 597 parentctx = hg_editor.repo[hg_editor.get_parent_revision(r.revnum, b)]
587 if path == '.hgsvnexternals': 621 if path == '.hgsvnexternals':
588 if not externals: 622 if not externals:
589 raise IOError() 623 raise IOError()
590 return context.memfilectx(path=path, data=externals.write(), 624 return context.memfilectx(path=path, data=externals.write(),
591 islink=False, isexec=False, copied=None) 625 islink=False, isexec=False, copied=None)
626 for bad in bad_branch_paths[b]:
627 if path.startswith(bad):
628 raise IOError()
592 return filectxfn2(repo, memctx, path) 629 return filectxfn2(repo, memctx, path)
593 630
594 extra = util.build_extra(r.revnum, b, svn.uuid, svn.subdir) 631 extra = util.build_extra(r.revnum, b, svn.uuid, svn.subdir)
595 if '' in files_touched: 632 if '' in files_touched:
596 files_touched.remove('') 633 files_touched.remove('')
597 excluded = [f for f in files_touched 634 excluded = [f for f in files_touched
598 if not hg_editor._is_file_included(f)] 635 if not hg_editor._is_file_included(f)]
599 for f in excluded: 636 for f in excluded:
600 files_touched.remove(f) 637 files_touched.remove(f)
601 if parentctx.node() != node.nullid or files_touched: 638 if parentctx.node() != node.nullid or files_touched:
602 # TODO(augie) remove this debug code? Or maybe it's sane to have it. 639 # TODO(augie) remove this debug code? Or maybe it's sane to have it.
610 filectxfn, 647 filectxfn,
611 hg_editor.authorforsvnauthor(r.author), 648 hg_editor.authorforsvnauthor(r.author),
612 date, 649 date,
613 extra) 650 extra)
614 ha = hg_editor.repo.commitctx(current_ctx) 651 ha = hg_editor.repo.commitctx(current_ctx)
652 branch = extra.get('branch', None)
653 if not branch in hg_editor.branches:
654 hg_editor.branches[branch] = None, 0, r.revnum
615 hg_editor.add_to_revmap(r.revnum, b, ha) 655 hg_editor.add_to_revmap(r.revnum, b, ha)
616 hg_editor._save_metadata() 656 hg_editor._save_metadata()
617 util.describe_commit(ui, ha, b) 657 util.describe_commit(ui, ha, b)
618 # These are branches which would have an 'R' status in svn log. This means they were 658 # These are branches which would have an 'R' status in svn log. This means they were
619 # replaced by some other branch, so we need to verify they get marked as closed. 659 # replaced by some other branch, so we need to verify they get marked as closed.