diff --git a/hgsubversion/editor.py b/hgsubversion/editor.py index f77458a1aa..763b355252 100644 --- a/hgsubversion/editor.py +++ b/hgsubversion/editor.py @@ -401,6 +401,10 @@ class HgEditor(svnwrap.Editor): br_path, branch = self.meta.split_branch_path(path)[:2] if br_path is not None: if not copyfrom_path and not br_path: + # This handles the case where a branch root is + # replaced without copy info. It will show up as a + # deletion and then an add. + self.meta.closebranches.discard(branch) self.current.emptybranches[branch] = True else: self.current.emptybranches[branch] = False diff --git a/hgsubversion/replay.py b/hgsubversion/replay.py index a273132cd9..2f44a5db92 100644 --- a/hgsubversion/replay.py +++ b/hgsubversion/replay.py @@ -97,7 +97,8 @@ def _convert_rev(ui, meta, svn, r, tbdelta, firstrun): p, b = meta.split_branch_path(f)[:2] if b not in branch_batches: branch_batches[b] = [] - branch_batches[b].append((p, f)) + if p: + branch_batches[b].append((p, f)) closebranches = {} for branch in tbdelta['branches'][1]: @@ -193,13 +194,14 @@ def _convert_rev(ui, meta, svn, r, tbdelta, firstrun): continue parent_ctx = meta.repo.changectx(ha) + files = [] def del_all_files(*args): raise IOError(errno.ENOENT, 'deleting all files') - # True here meant nuke all files, shouldn't happen with branch closing - if current.emptybranches[branch]: # pragma: no cover - raise hgutil.Abort('Empty commit to an open branch attempted. ' - 'Please report this issue.') + # True here means nuke all files. This happens when you + # replace a branch root with an empty directory + if current.emptybranches[branch]: + files = meta.repo[ha].files() extra = meta.genextra(rev.revnum, branch) meta.mapbranch(extra) @@ -207,7 +209,7 @@ def _convert_rev(ui, meta, svn, r, tbdelta, firstrun): current_ctx = context.memctx(meta.repo, (ha, node.nullid), util.getmessage(ui, rev), - [], + files, del_all_files, meta.authors[rev.author], date, diff --git a/hgsubversion/svnmeta.py b/hgsubversion/svnmeta.py index 190522ff9b..a619d8a029 100644 --- a/hgsubversion/svnmeta.py +++ b/hgsubversion/svnmeta.py @@ -490,8 +490,8 @@ class SVNMeta(object): # action of 'D'. We mark the branch as deleted. # 5. It's the parent directory of one or more # already-known branches, so we mark them as deleted. - # 6. It's a branch being replaced by another branch - the - # action will be 'R'. + # 6. It's a branch being replaced by another branch or a new + # directory - the action will be 'R'. fi, br = self.split_branch_path(p)[:2] if fi is not None: if fi == '': @@ -501,15 +501,16 @@ class SVNMeta(object): # Check the replacing source is not an ancestor # branch of the branch being replaced, this # would just be a revert. - cfi, cbr = self.split_branch_path( - paths[p].copyfrom_path, paths[p].copyfrom_rev)[:2] - if cfi == '': - cctx = self.repo[self.get_parent_revision( - paths[p].copyfrom_rev + 1, cbr)] - ctx = self.repo[self.get_parent_revision( - revision.revnum, br)] - if cctx and util.isancestor(ctx, cctx): - continue + if paths[p].copyfrom_path: + cfi, cbr = self.split_branch_path( + paths[p].copyfrom_path, paths[p].copyfrom_rev)[:2] + if cfi == '': + cctx = self.repo[self.get_parent_revision( + paths[p].copyfrom_rev + 1, cbr)] + ctx = self.repo[self.get_parent_revision( + revision.revnum, br)] + if cctx and util.isancestor(ctx, cctx): + continue parent = self._determine_parent_branch( p, paths[p].copyfrom_path, paths[p].copyfrom_rev, revision.revnum)