[PATCH] convert/bzr: correctly handle divergent nested renames (issue3089)
Patrick Mezard
pmezard at gmail.com
Tue Nov 8 10:43:00 CST 2011
# HG changeset patch
# User Patrick Mezard <pmezard at gmail.com>
# Date 1320768538 -3600
# Branch stable
# Node ID b4274167128fb95f170e952329c0e30fc7dca717
# Parent 54c0517c0fe8af4f8851a1bbb5bb229f0e7dd853
convert/bzr: correctly handle divergent nested renames (issue3089)
With renames like:
a -> b
a/c -> a/c
We were ignoring or duplicating the second one instead of leaving files
unchanged or moving them to their proper destination only.
To avoid this, we process the files in reverse lexicographic order, from most
to least specific change, and ignore files already processed.
diff --git a/hgext/convert/bzr.py b/hgext/convert/bzr.py
--- a/hgext/convert/bzr.py
+++ b/hgext/convert/bzr.py
@@ -173,8 +173,14 @@
revid = current._revision_id
changes = []
renames = {}
+ seen = set()
+ # Process the entries by reverse lexicographic name order to
+ # handle nested renames correctly, most specific first.
+ curchanges = sorted(current.iter_changes(origin),
+ key=lambda c: c[1][0] or c[1][1],
+ reverse=1)
for (fileid, paths, changed_content, versioned, parent, name,
- kind, executable) in current.iter_changes(origin):
+ kind, executable) in curchanges:
if paths[0] == u'' or paths[1] == u'':
# ignore changes to tree root
@@ -188,7 +194,8 @@
# so it can be removed.
changes.append((self.recode(paths[0]), revid))
- if None not in paths and paths[0] != paths[1]:
+ if kind[0] == 'directory' and None not in paths:
+ renaming = paths[0] != paths[1]
# neither an add nor an delete - a move
# rename all directory contents manually
subdir = origin.inventory.path2id(paths[0])
@@ -198,6 +205,16 @@
if entry.kind == 'directory':
continue
frompath = self.recode(paths[0] + '/' + name)
+ if frompath in seen:
+ # Already handled by a more specific change entry
+ # This is important when you have:
+ # a => b
+ # a/c => a/c
+ # Here a/c must not be renamed into b/c
+ continue
+ seen.add(frompath)
+ if not renaming:
+ continue
topath = self.recode(paths[1] + '/' + name)
# register the files as changed
changes.append((frompath, revid))
@@ -215,6 +232,7 @@
# we got unicode paths, need to convert them
path, topath = [self.recode(part) for part in paths]
+ seen.add(path or topath)
if topath is None:
# file deleted
More information about the Mercurial-devel
mailing list