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