Mercurial > hgsubversion
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. |