Merge lp:~lifeless/bzr/bug-367632 into lp:~bzr/bzr/trunk-old

Proposed by Robert Collins
Status: Merged
Merged at revision: not available
Proposed branch: lp:~lifeless/bzr/bug-367632
Merge into: lp:~bzr/bzr/trunk-old
Diff against target: 127 lines (has conflicts)
Text conflict in NEWS
To merge this branch: bzr merge lp:~lifeless/bzr/bug-367632
Reviewer Review Type Date Requested Status
Martin Pool Approve
Review via email: mp+8928@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

Add interface enforcement for the behaviour of iter_changes with missing
subtrees with explicit paths - the whole subtree is returned.

This fixes the behaviour of 'revert .' when a directory and its contents
have been removed.

-Rob

--

Revision history for this message
Martin Pool (mbp) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2009-07-20 21:21:10 +0000
3+++ NEWS 2009-07-21 03:35:33 +0000
4@@ -38,10 +38,16 @@
5 * ``bzr mv`` no longer takes out branch locks, which allows it to work
6 when the branch is readonly. (Robert Collins, #216541)
7
8+<<<<<<< TREE
9 * Fixed a NameError that occurs when merging or pulling from a URL that
10 causes a redirection loop when bzr tries to read a URL as a bundle.
11 (Andrew Bennetts, #400847)
12
13+=======
14+* ``bzr revert .`` no longer generates an InconsistentDelta error when
15+ there are missing subtrees. (Robert Collins, #367632)
16+
17+>>>>>>> MERGE-SOURCE
18 * Fixed spurious "Source branch does not support stacking" warning when
19 pushing. (Andrew Bennetts, #388908)
20
21
22=== modified file 'bzrlib/tests/per_intertree/test_compare.py'
23--- bzrlib/tests/per_intertree/test_compare.py 2009-07-14 10:12:30 +0000
24+++ bzrlib/tests/per_intertree/test_compare.py 2009-07-21 03:35:33 +0000
25@@ -757,6 +757,29 @@
26 (None, root_id), (None, 'file'), (None, None), (None, False))]
27 self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
28
29+ def test_only_in_target_missing_subtree_specific_bug_367632(self):
30+ tree1 = self.make_branch_and_tree('tree1')
31+ tree2 = self.make_to_branch_and_tree('tree2')
32+ tree2.set_root_id(tree1.get_root_id())
33+ self.build_tree(['tree2/a-dir/', 'tree2/a-dir/a-file'])
34+ tree2.add(['a-dir', 'a-dir/a-file'], ['dir-id', 'file-id'])
35+ os.unlink('tree2/a-dir/a-file')
36+ os.rmdir('tree2/a-dir')
37+ tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
38+ self.not_applicable_if_missing_in('a-dir', tree2)
39+ root_id = tree1.path2id('')
40+ expected = [
41+ ('dir-id', (None, 'a-dir'), False, (False, True),
42+ (None, root_id), (None, 'a-dir'), (None, None), (None, False)),
43+ ('file-id', (None, 'a-dir/a-file'), False, (False, True),
44+ (None, 'dir-id'), (None, 'a-file'), (None, None), (None, False))
45+ ]
46+ # bug 367632 showed that specifying the root broke some code paths,
47+ # so we check this contract with and without it.
48+ self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
49+ self.assertEqual(expected,
50+ self.do_iter_changes(tree1, tree2, specific_files=['']))
51+
52 def test_unchanged_with_renames_and_modifications(self):
53 """want_unchanged should generate a list of unchanged entries."""
54 tree1 = self.make_branch_and_tree('1')
55@@ -765,7 +788,6 @@
56 tree2 = self.get_tree_no_parents_abc_content_5(tree2)
57 tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
58 root_id = tree1.path2id('')
59-
60 self.assertEqual(sorted([self.unchanged(tree1, root_id),
61 self.unchanged(tree1, 'b-id'),
62 ('a-id', ('a', 'd'), True, (True, True),
63
64=== modified file 'bzrlib/transform.py'
65--- bzrlib/transform.py 2009-07-20 06:06:22 +0000
66+++ bzrlib/transform.py 2009-07-21 03:35:33 +0000
67@@ -1718,14 +1718,20 @@
68 def __iter__(self):
69 return iter(self.all_file_ids())
70
71- def has_id(self, file_id):
72+ def _has_id(self, file_id, fallback_check):
73 if file_id in self._transform._r_new_id:
74 return True
75 elif file_id in set([self._transform.tree_file_id(trans_id) for
76 trans_id in self._transform._removed_id]):
77 return False
78 else:
79- return self._transform._tree.has_id(file_id)
80+ return fallback_check(file_id)
81+
82+ def has_id(self, file_id):
83+ return self._has_id(file_id, self._transform._tree.has_id)
84+
85+ def has_or_had_id(self, file_id):
86+ return self._has_id(file_id, self._transform._tree.has_or_had_id)
87
88 def _path2trans_id(self, path):
89 # We must not use None here, because that is a valid value to store.
90
91=== modified file 'bzrlib/tree.py'
92--- bzrlib/tree.py 2009-07-10 08:33:11 +0000
93+++ bzrlib/tree.py 2009-07-21 03:35:33 +0000
94@@ -133,8 +133,6 @@
95 return self.has_id(file_id)
96
97 def has_or_had_id(self, file_id):
98- if file_id == self.inventory.root.file_id:
99- return True
100 return self.inventory.has_id(file_id)
101
102 def is_ignored(self, filename):
103@@ -825,7 +823,7 @@
104 new_pending = set()
105 for file_id in pending:
106 for tree in trees:
107- if not tree.has_id(file_id):
108+ if not tree.has_or_had_id(file_id):
109 continue
110 for child_id in tree.iter_children(file_id):
111 if child_id not in interesting_ids:
112
113=== modified file 'bzrlib/workingtree_4.py'
114--- bzrlib/workingtree_4.py 2009-07-15 04:33:14 +0000
115+++ bzrlib/workingtree_4.py 2009-07-21 03:35:33 +0000
116@@ -435,6 +435,11 @@
117 return osutils.lexists(pathjoin(
118 self.basedir, row[0].decode('utf8'), row[1].decode('utf8')))
119
120+ def has_or_had_id(self, file_id):
121+ state = self.current_dirstate()
122+ row, parents = self._get_entry(file_id=file_id)
123+ return row is not None
124+
125 @needs_read_lock
126 def id2path(self, file_id):
127 "Convert a file-id to a path."