|
Line 0
Link Here
|
|
|
1 |
Description: Fix a case where deleteion of an entry in a renamed directory is not reproduced |
| 2 |
correctly in fast-export. Thanks to Harry Hirsch, Nuno Araujo, and Andrew Huff for the patch. |
| 3 |
Bugs: https://launchpad.net/bugs/430347 https://launchpad.net/bugs/1167690 https://launchpad.net/bugs/1014291 |
| 4 |
|
| 5 |
=== modified file 'exporter.py' |
| 6 |
--- a/exporter.py 2014-05-15 09:26:03 +0000 |
| 7 |
+++ b/exporter.py 2015-05-04 13:08:57 +0000 |
| 8 |
@@ -514,6 +514,7 @@ |
| 9 |
# |
| 10 |
# 1) bzr rm a; bzr mv b a; bzr commit |
| 11 |
# 2) bzr mv x/y z; bzr rm x; commmit |
| 12 |
+ # 3) bzr mv x y; bzr rm y/z; bzr commit |
| 13 |
# |
| 14 |
# The first must come out with the delete first like this: |
| 15 |
# |
| 16 |
@@ -525,6 +526,11 @@ |
| 17 |
# R x/y z |
| 18 |
# D x |
| 19 |
# |
| 20 |
+ # The third case must come out with delete first like this: |
| 21 |
+ # |
| 22 |
+ # D x/z |
| 23 |
+ # R x y |
| 24 |
+ # |
| 25 |
# So outputting all deletes first or all renames first won't work. |
| 26 |
# Instead, we need to make multiple passes over the various lists to |
| 27 |
# get the ordering right. |
| 28 |
@@ -532,6 +538,7 @@ |
| 29 |
must_be_renamed = {} |
| 30 |
old_to_new = {} |
| 31 |
deleted_paths = set([p for p, _, _ in deletes]) |
| 32 |
+ deleted_child_paths = set() |
| 33 |
for (oldpath, newpath, id_, kind, |
| 34 |
text_modified, meta_modified) in renames: |
| 35 |
emit = kind != 'directory' or not self.plain_format |
| 36 |
@@ -543,6 +550,20 @@ |
| 37 |
self.note("Skipping empty dir %s in rev %s" % (oldpath, |
| 38 |
revision_id)) |
| 39 |
continue |
| 40 |
+ |
| 41 |
+ if kind == 'directory': |
| 42 |
+ # handling deleted children in renamed directory (case 3 above) |
| 43 |
+ for p, e in tree_old.inventory.iter_entries_by_dir(from_dir=id_): |
| 44 |
+ if e.kind == 'directory' or not self.plain_format: |
| 45 |
+ continue |
| 46 |
+ old_child_path = osutils.pathjoin(oldpath, p) |
| 47 |
+ new_child_path = osutils.pathjoin(newpath, p) |
| 48 |
+ if old_child_path in deleted_paths: |
| 49 |
+ file_cmds.append(commands.FileDeleteCommand(old_child_path.encode("utf-8"))) |
| 50 |
+ deleted_paths.remove(old_child_path) |
| 51 |
+ deleted_child_paths.add(old_child_path) |
| 52 |
+ |
| 53 |
+ |
| 54 |
#oldpath = self._adjust_path_for_renames(oldpath, renamed, |
| 55 |
# revision_id) |
| 56 |
renamed.append([oldpath, newpath]) |
| 57 |
@@ -561,6 +582,8 @@ |
| 58 |
continue |
| 59 |
old_child_path = osutils.pathjoin(oldpath, p) |
| 60 |
new_child_path = osutils.pathjoin(newpath, p) |
| 61 |
+ if old_child_path in deleted_child_paths: |
| 62 |
+ continue |
| 63 |
must_be_renamed[old_child_path] = new_child_path |
| 64 |
|
| 65 |
# Add children not already renamed |
| 66 |
|