# HG changeset patch # User Patrick Mezard # Date 1264842063 -3600 # Node ID 460eb781d840e09e42447905b01dfe20e20110e1 # Parent 715d2e3e153bb9d36b7110110a7175e8983f4452 Handle subdirectory tags in stupid mode (issue119) Current solution add an alternate behaviour to svnmeta.split_branch_path(), which unfortunately looks like the expected behaviour. Other calls will be changed to make it the default behaviour. diff --git a/hgsubversion/stupid.py b/hgsubversion/stupid.py --- a/hgsubversion/stupid.py +++ b/hgsubversion/stupid.py @@ -103,25 +103,19 @@ def diff_branchrev(ui, svn, meta, branch callable to retrieve individual file information. Raise BadPatchApply upon error. """ - def make_diff_path(branch): - if meta.layout == 'single': - return '' - if branch == 'trunk' or branch is None: - return 'trunk' - elif branch.startswith('../'): - return branch[3:] - return 'branches/%s' % branch - parent_rev, br_p = meta.get_parent_svn_branch_and_rev(r.revnum, branch) try: - if br_p == branch: + prev, pbranch, ppath = meta.get_source_rev(ctx=parentctx) + except KeyError: + prev, pbranch, ppath = None, None, None + try: + if prev is None or pbranch == branch: # letting patch handle binaries sounded # cool, but it breaks patch in sad ways d = svn.get_unified_diff(branchpath, r.revnum, deleted=False, ignore_type=False) else: d = svn.get_unified_diff(branchpath, r.revnum, - other_path=make_diff_path(br_p), - other_rev=parent_rev, + other_path=ppath, other_rev=prev, deleted=True, ignore_type=True) if d: raise BadPatchApply('branch creation with mods') @@ -473,7 +467,7 @@ def branches_in_paths(meta, tbdelta, pat branches = {} paths_need_discovery = [] for p in paths: - relpath, branch, branchpath = meta.split_branch_path(p) + relpath, branch, branchpath = meta.split_branch_path(p, exacttag=True) if relpath is not None: branches[branch] = branchpath elif paths[p].action == 'D' and not meta.get_path_tag(p): @@ -572,14 +566,13 @@ def convert_rev(ui, meta, svn, r, tbdelt check_deleted_branches = set(tbdelta['branches'][1]) for b in branches: parentctx = meta.repo[meta.get_parent_revision(r.revnum, b)] - if parentctx.branch() != (b or 'default'): - check_deleted_branches.add(b) - + tag = meta.get_path_tag(meta.remotename(b)) kind = svn.checkpath(branches[b], r.revnum) if kind != 'd': - # Branch does not exist at this revision. Get parent revision and - # remove everything. - deleted_branches[b] = parentctx.node() + if not tag: + # Branch does not exist at this revision. Get parent + # revision and remove everything. + deleted_branches[b] = parentctx.node() continue try: @@ -615,6 +608,14 @@ def convert_rev(ui, meta, svn, r, tbdelt for f in excluded: files_touched.remove(f) + if b: + # Regular tag without modifications, it will be committed by + # svnmeta.committag(), we can skip the whole branch for now + if (tag and tag not in meta.tags and + b not in meta.branches + and b not in meta.repo.branchtags()): + continue + if parentctx.node() == node.nullid and not files_touched: meta.repo.ui.debug('skipping commit since parent is null and no files touched.\n') continue @@ -626,8 +627,6 @@ def convert_rev(ui, meta, svn, r, tbdelt assert f[0] != '/' extra = meta.genextra(r.revnum, b) - - tag = meta.get_path_tag(meta.remotename(b)) if tag: if parentctx.node() == node.nullid: continue diff --git a/hgsubversion/svnmeta.py b/hgsubversion/svnmeta.py --- a/hgsubversion/svnmeta.py +++ b/hgsubversion/svnmeta.py @@ -247,7 +247,7 @@ class SVNMeta(object): return tag return None - def split_branch_path(self, path, existing=True): + def split_branch_path(self, path, existing=True, exacttag=False): """Figure out which branch inside our repo this path represents, and also figure out which path inside that branch it is. @@ -256,6 +256,11 @@ class SVNMeta(object): If existing=True, will return None, None, None if the file isn't on some known branch. If existing=False, then it will guess what the branch would be if it were known. Server-side branch path should be relative to our subdirectory. + + If exacttag=True and path matches exactly a new or existing + tag, then return it as an empty relative path. Otherwise, + ignore the path and return (None, None, None). Only subpaths + of supplied tag path will be split. """ path = self.normalize(path) if self.layout == 'single': @@ -265,12 +270,20 @@ class SVNMeta(object): # consider the new tags when dispatching entries matched = [] for tags in (self.tags, self.addedtags): - matched += [t for t in tags if tag.startswith(t + '/')] + if exacttag: + matched += [t for t in tags + if (tag == t or tag.startswith(t + '/'))] + else: + matched += [t for t in tags if tag.startswith(t + '/')] if not matched: return None, None, None matched.sort(key=len, reverse=True) - brpath = tag[len(matched[0])+1:] - svrpath = path[:-(len(brpath)+1)] + if tag == matched[0]: + brpath = '' + svrpath = path + else: + brpath = tag[len(matched[0])+1:] + svrpath = path[:-(len(brpath)+1)] ln = self.localname(svrpath) return brpath, ln, svrpath test = '' diff --git a/tests/test_tags.py b/tests/test_tags.py --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -235,7 +235,7 @@ rename a tag diff = difflib.unified_diff(expected, output, 'expected', 'output') self.assert_(False, '\n' + '\n'.join(diff)) - def test_tagging_into_tag(self, expected=None, stupid=False): + def test_tagging_into_tag(self, stupid=False): expected = """\ node: hg=test@2:svn=branches/test@4 First tag. @@ -246,28 +246,10 @@ Weird tag. test-0.1: hg=test@1:svn=branches/test@3 test-0.1/test: hg=test@1:svn=branches/test@3 """ - self._test_tags('renametagdir.svndump', expected) + self._test_tags('renametagdir.svndump', expected, stupid=stupid) def test_tagging_into_tag_stupid(self): - # This test exposed existing flaws with tag handling in stupid mode. - # They will be resolved in the future. - expected = """\ -node: hg=test@2:svn=branches/test@4 -First tag. - test-0.1: hg=test@1:svn=branches/test@3 - -node: hg=test@4:svn=branches/test@4 -Weird tag. - test-0.1: hg=test@1:svn=branches/test@3 - test-0.1: hg=test@3:svn=tags/test-0.1@5 - -node: hg=test@5:svn=branches/test@5 -Weird tag. - test-0.1: hg=test@1:svn=branches/test@3 - test-0.1: hg=test@3:svn=tags/test-0.1@5 - test-0.1/test: hg=test@1:svn=branches/test@3 -""" - self._test_tags('renametagdir.svndump', expected, True) + self.test_tagging_into_tag(True) def suite():