summaryrefslogtreecommitdiff
path: root/devel/bzr-fastimport/files/patch-deletion-case
blob: 656a490a240174516367198ab517c3e9cabffc25 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
Description: Fix a case where deleteion of an entry in a renamed directory is not reproduced
 correctly in fast-export.  Thanks to Harry Hirsch, Nuno Araujo, and Andrew Huff for the patch.
Bugs: https://launchpad.net/bugs/430347 https://launchpad.net/bugs/1167690 https://launchpad.net/bugs/1014291

=== modified file 'exporter.py'
--- a/exporter.py	2014-05-15 09:26:03 +0000
+++ b/exporter.py	2015-05-04 13:08:57 +0000
@@ -514,6 +514,7 @@
         #
         # 1) bzr rm a; bzr mv b a; bzr commit
         # 2) bzr mv x/y z; bzr rm x; commmit
+        # 3) bzr mv x y; bzr rm y/z; bzr commit
         #
         # The first must come out with the delete first like this:
         #
@@ -525,6 +526,11 @@
         # R x/y z
         # D x
         #
+        # The third case must come out with delete first like this:
+        #
+        # D x/z
+        # R x y
+        #
         # So outputting all deletes first or all renames first won't work.
         # Instead, we need to make multiple passes over the various lists to
         # get the ordering right.
@@ -532,6 +538,7 @@
         must_be_renamed = {}
         old_to_new = {}
         deleted_paths = set([p for p, _, _ in deletes])
+        deleted_child_paths = set()
         for (oldpath, newpath, id_, kind,
                 text_modified, meta_modified) in renames:
             emit = kind != 'directory' or not self.plain_format
@@ -543,6 +550,20 @@
                 self.note("Skipping empty dir %s in rev %s" % (oldpath,
                     revision_id))
                 continue
+                
+            if kind == 'directory':
+                # handling deleted children in renamed directory (case 3 above)
+                for p, e in tree_old.inventory.iter_entries_by_dir(from_dir=id_):
+                    if e.kind == 'directory' or not self.plain_format:
+                        continue
+                    old_child_path = osutils.pathjoin(oldpath, p)
+                    new_child_path = osutils.pathjoin(newpath, p)
+                    if old_child_path in deleted_paths:
+                        file_cmds.append(commands.FileDeleteCommand(old_child_path.encode("utf-8")))
+                        deleted_paths.remove(old_child_path)
+                        deleted_child_paths.add(old_child_path)
+
+                
             #oldpath = self._adjust_path_for_renames(oldpath, renamed,
             #    revision_id)
             renamed.append([oldpath, newpath])
@@ -561,6 +582,8 @@
                         continue
                     old_child_path = osutils.pathjoin(oldpath, p)
                     new_child_path = osutils.pathjoin(newpath, p)
+                    if old_child_path in deleted_child_paths:
+                        continue
                     must_be_renamed[old_child_path] = new_child_path
 
         # Add children not already renamed