Merge lp:~jelmer/brz/extract-paths2ids into lp:brz
- extract-paths2ids
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Jelmer Vernooij |
Approved revision: | no longer in the source branch. |
Merge reported by: | The Breezy Bot |
Merged at revision: | not available |
Proposed branch: | lp:~jelmer/brz/extract-paths2ids |
Merge into: | lp:brz |
Prerequisite: | lp:~jelmer/brz/find-previous-paths |
Diff against target: |
1340 lines (+329/-267) 20 files modified
breezy/builtins.py (+13/-14) breezy/bzr/inventory.py (+2/-2) breezy/bzr/inventorytree.py (+138/-12) breezy/bzr/workingtree.py (+4/-7) breezy/filter_tree.py (+2/-2) breezy/merge.py (+15/-31) breezy/rename_map.py (+9/-1) breezy/tests/per_intertree/test_compare.py (+3/-1) breezy/tests/per_tree/test_inv.py (+10/-4) breezy/tests/per_tree/test_test_trees.py (+2/-8) breezy/tests/per_workingtree/test_inv.py (+1/-1) breezy/tests/per_workingtree/test_nested_specifics.py (+1/-1) breezy/tests/per_workingtree/test_paths2ids.py (+37/-0) breezy/tests/test_merge.py (+5/-9) breezy/tests/test_merge_core.py (+5/-5) breezy/tests/test_shelf.py (+2/-2) breezy/tests/test_transform.py (+5/-4) breezy/tests/test_workingtree.py (+2/-1) breezy/transform.py (+22/-22) breezy/tree.py (+51/-140) |
To merge this branch: | bzr merge lp:~jelmer/brz/extract-paths2ids |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Packman | Approve | ||
Review via email: mp+341923@code.launchpad.net |
Commit message
Add a new Tree.find_
Description of the change
Add a new Tree.find_
This finds a set of paths in a specific tree that are related to a set of specified paths in trees to look up in.
This allows further eliminating the use of file ids in public APIs:
* Tree.paths2ids can now be InventoryTree-
* Merge now only takes a list of interesting files rather than a list of interesting file ids or interesting files.
* Tree.iter_
The Breezy Bot (the-breezy-bot) wrote : | # |
Merging failed
https:/
The Breezy Bot (the-breezy-bot) wrote : | # |
Merging failed
https:/
The Breezy Bot (the-breezy-bot) wrote : | # |
Running landing tests failed
https:/
Preview Diff
1 | === modified file 'breezy/builtins.py' | |||
2 | --- breezy/builtins.py 2018-03-24 00:39:56 +0000 | |||
3 | +++ breezy/builtins.py 2018-03-24 01:23:20 +0000 | |||
4 | @@ -53,6 +53,7 @@ | |||
5 | 53 | symbol_versioning, | 53 | symbol_versioning, |
6 | 54 | timestamp, | 54 | timestamp, |
7 | 55 | transport, | 55 | transport, |
8 | 56 | tree as _mod_tree, | ||
9 | 56 | ui, | 57 | ui, |
10 | 57 | urlutils, | 58 | urlutils, |
11 | 58 | views, | 59 | views, |
12 | @@ -960,11 +961,11 @@ | |||
13 | 960 | 961 | ||
14 | 961 | self.add_cleanup(tree.lock_read().unlock) | 962 | self.add_cleanup(tree.lock_read().unlock) |
15 | 962 | if file_list is not None: | 963 | if file_list is not None: |
18 | 963 | file_ids = tree.paths2ids(file_list, trees=extra_trees, | 964 | paths = tree.find_related_paths_across_trees( |
19 | 964 | require_versioned=True) | 965 | file_list, extra_trees, require_versioned=True) |
20 | 965 | # find_ids_across_trees may include some paths that don't | 966 | # find_ids_across_trees may include some paths that don't |
21 | 966 | # exist in 'tree'. | 967 | # exist in 'tree'. |
23 | 967 | entries = tree.iter_entries_by_dir(specific_file_ids=file_ids) | 968 | entries = tree.iter_entries_by_dir(specific_files=paths) |
24 | 968 | else: | 969 | else: |
25 | 969 | entries = tree.iter_entries_by_dir() | 970 | entries = tree.iter_entries_by_dir() |
26 | 970 | 971 | ||
27 | @@ -4775,29 +4776,27 @@ | |||
28 | 4775 | " merges. Not cherrypicking or" | 4776 | " merges. Not cherrypicking or" |
29 | 4776 | " multi-merges.")) | 4777 | " multi-merges.")) |
30 | 4777 | repository = tree.branch.repository | 4778 | repository = tree.branch.repository |
32 | 4778 | interesting_ids = None | 4779 | interesting_files = None |
33 | 4779 | new_conflicts = [] | 4780 | new_conflicts = [] |
34 | 4780 | conflicts = tree.conflicts() | 4781 | conflicts = tree.conflicts() |
35 | 4781 | if file_list is not None: | 4782 | if file_list is not None: |
37 | 4782 | interesting_ids = set() | 4783 | interesting_files = set() |
38 | 4783 | for filename in file_list: | 4784 | for filename in file_list: |
41 | 4784 | file_id = tree.path2id(filename) | 4785 | if not tree.is_versioned(filename): |
40 | 4785 | if file_id is None: | ||
42 | 4786 | raise errors.NotVersionedError(filename) | 4786 | raise errors.NotVersionedError(filename) |
45 | 4787 | interesting_ids.add(file_id) | 4787 | interesting_files.add(filename) |
46 | 4788 | if tree.kind(filename, file_id) != "directory": | 4788 | if tree.kind(filename) != "directory": |
47 | 4789 | continue | 4789 | continue |
48 | 4790 | 4790 | ||
52 | 4791 | # FIXME: Support nested trees | 4791 | for path, ie in tree.iter_entries_by_dir(specific_files=[filename]): |
53 | 4792 | for name, ie in tree.root_inventory.iter_entries(file_id): | 4792 | interesting_files.add(path) |
51 | 4793 | interesting_ids.add(ie.file_id) | ||
54 | 4794 | new_conflicts = conflicts.select_conflicts(tree, file_list)[0] | 4793 | new_conflicts = conflicts.select_conflicts(tree, file_list)[0] |
55 | 4795 | else: | 4794 | else: |
56 | 4796 | # Remerge only supports resolving contents conflicts | 4795 | # Remerge only supports resolving contents conflicts |
57 | 4797 | allowed_conflicts = ('text conflict', 'contents conflict') | 4796 | allowed_conflicts = ('text conflict', 'contents conflict') |
58 | 4798 | restore_files = [c.path for c in conflicts | 4797 | restore_files = [c.path for c in conflicts |
59 | 4799 | if c.typestring in allowed_conflicts] | 4798 | if c.typestring in allowed_conflicts] |
61 | 4800 | _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids) | 4799 | _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_files) |
62 | 4801 | tree.set_conflicts(ConflictList(new_conflicts)) | 4800 | tree.set_conflicts(ConflictList(new_conflicts)) |
63 | 4802 | if file_list is not None: | 4801 | if file_list is not None: |
64 | 4803 | restore_files = file_list | 4802 | restore_files = file_list |
65 | @@ -4814,7 +4813,7 @@ | |||
66 | 4814 | tree.set_parent_ids(parents[:1]) | 4813 | tree.set_parent_ids(parents[:1]) |
67 | 4815 | try: | 4814 | try: |
68 | 4816 | merger = _mod_merge.Merger.from_revision_ids(tree, parents[1]) | 4815 | merger = _mod_merge.Merger.from_revision_ids(tree, parents[1]) |
70 | 4817 | merger.interesting_ids = interesting_ids | 4816 | merger.interesting_files = interesting_files |
71 | 4818 | merger.merge_type = merge_type | 4817 | merger.merge_type = merge_type |
72 | 4819 | merger.show_base = show_base | 4818 | merger.show_base = show_base |
73 | 4820 | merger.reprocess = reprocess | 4819 | merger.reprocess = reprocess |
74 | 4821 | 4820 | ||
75 | === modified file 'breezy/bzr/inventory.py' | |||
76 | --- breezy/bzr/inventory.py 2018-03-10 15:17:30 +0000 | |||
77 | +++ breezy/bzr/inventory.py 2018-03-24 01:23:20 +0000 | |||
78 | @@ -720,12 +720,12 @@ | |||
79 | 720 | 720 | ||
80 | 721 | def _preload_cache(self): | 721 | def _preload_cache(self): |
81 | 722 | """Populate any caches, we are about to access all items. | 722 | """Populate any caches, we are about to access all items. |
83 | 723 | 723 | ||
84 | 724 | The default implementation does nothing, because CommonInventory doesn't | 724 | The default implementation does nothing, because CommonInventory doesn't |
85 | 725 | have a cache. | 725 | have a cache. |
86 | 726 | """ | 726 | """ |
87 | 727 | pass | 727 | pass |
89 | 728 | 728 | ||
90 | 729 | def iter_entries_by_dir(self, from_dir=None, specific_file_ids=None, | 729 | def iter_entries_by_dir(self, from_dir=None, specific_file_ids=None, |
91 | 730 | yield_parents=False): | 730 | yield_parents=False): |
92 | 731 | """Iterate over the entries in a directory first order. | 731 | """Iterate over the entries in a directory first order. |
93 | 732 | 732 | ||
94 | === modified file 'breezy/bzr/inventorytree.py' | |||
95 | --- breezy/bzr/inventorytree.py 2018-03-24 00:16:27 +0000 | |||
96 | +++ breezy/bzr/inventorytree.py 2018-03-24 01:23:20 +0000 | |||
97 | @@ -170,6 +170,53 @@ | |||
98 | 170 | file_id = file_id[0] | 170 | file_id = file_id[0] |
99 | 171 | return self.root_inventory, file_id | 171 | return self.root_inventory, file_id |
100 | 172 | 172 | ||
101 | 173 | def find_related_paths_across_trees(self, paths, trees=[], | ||
102 | 174 | require_versioned=True): | ||
103 | 175 | """Find related paths in tree corresponding to specified filenames in any | ||
104 | 176 | of `lookup_trees`. | ||
105 | 177 | |||
106 | 178 | All matches in all trees will be used, and all children of matched | ||
107 | 179 | directories will be used. | ||
108 | 180 | |||
109 | 181 | :param paths: The filenames to find related paths for (if None, returns | ||
110 | 182 | None) | ||
111 | 183 | :param trees: The trees to find file_ids within | ||
112 | 184 | :param require_versioned: if true, all specified filenames must occur in | ||
113 | 185 | at least one tree. | ||
114 | 186 | :return: a set of paths for the specified filenames and their children | ||
115 | 187 | in `tree` | ||
116 | 188 | """ | ||
117 | 189 | if paths is None: | ||
118 | 190 | return None; | ||
119 | 191 | file_ids = self.paths2ids( | ||
120 | 192 | paths, trees, require_versioned=require_versioned) | ||
121 | 193 | ret = set() | ||
122 | 194 | for file_id in file_ids: | ||
123 | 195 | try: | ||
124 | 196 | ret.add(self.id2path(file_id)) | ||
125 | 197 | except errors.NoSuchId: | ||
126 | 198 | pass | ||
127 | 199 | return ret | ||
128 | 200 | |||
129 | 201 | def paths2ids(self, paths, trees=[], require_versioned=True): | ||
130 | 202 | """Return all the ids that can be reached by walking from paths. | ||
131 | 203 | |||
132 | 204 | Each path is looked up in this tree and any extras provided in | ||
133 | 205 | trees, and this is repeated recursively: the children in an extra tree | ||
134 | 206 | of a directory that has been renamed under a provided path in this tree | ||
135 | 207 | are all returned, even if none exist under a provided path in this | ||
136 | 208 | tree, and vice versa. | ||
137 | 209 | |||
138 | 210 | :param paths: An iterable of paths to start converting to ids from. | ||
139 | 211 | Alternatively, if paths is None, no ids should be calculated and None | ||
140 | 212 | will be returned. This is offered to make calling the api unconditional | ||
141 | 213 | for code that *might* take a list of files. | ||
142 | 214 | :param trees: Additional trees to consider. | ||
143 | 215 | :param require_versioned: If False, do not raise NotVersionedError if | ||
144 | 216 | an element of paths is not versioned in this tree and all of trees. | ||
145 | 217 | """ | ||
146 | 218 | return find_ids_across_trees(paths, [self] + list(trees), require_versioned) | ||
147 | 219 | |||
148 | 173 | def path2id(self, path): | 220 | def path2id(self, path): |
149 | 174 | """Return the id for path in this tree.""" | 221 | """Return the id for path in this tree.""" |
150 | 175 | with self.lock_read(): | 222 | with self.lock_read(): |
151 | @@ -222,7 +269,7 @@ | |||
152 | 222 | # are not versioned. | 269 | # are not versioned. |
153 | 223 | return set((p for p in paths if self.path2id(p) is None)) | 270 | return set((p for p in paths if self.path2id(p) is None)) |
154 | 224 | 271 | ||
156 | 225 | def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False): | 272 | def iter_entries_by_dir(self, specific_files=None, yield_parents=False): |
157 | 226 | """Walk the tree in 'by_dir' order. | 273 | """Walk the tree in 'by_dir' order. |
158 | 227 | 274 | ||
159 | 228 | This will yield each entry in the tree as a (path, entry) tuple. | 275 | This will yield each entry in the tree as a (path, entry) tuple. |
160 | @@ -231,20 +278,20 @@ | |||
161 | 231 | See Tree.iter_entries_by_dir for details. | 278 | See Tree.iter_entries_by_dir for details. |
162 | 232 | 279 | ||
163 | 233 | :param yield_parents: If True, yield the parents from the root leading | 280 | :param yield_parents: If True, yield the parents from the root leading |
166 | 234 | down to specific_file_ids that have been requested. This has no | 281 | down to specific_files that have been requested. This has no |
167 | 235 | impact if specific_file_ids is None. | 282 | impact if specific_files is None. |
168 | 236 | """ | 283 | """ |
169 | 237 | with self.lock_read(): | 284 | with self.lock_read(): |
173 | 238 | if specific_file_ids is None: | 285 | if specific_files is not None: |
171 | 239 | inventory_file_ids = None | ||
172 | 240 | else: | ||
174 | 241 | inventory_file_ids = [] | 286 | inventory_file_ids = [] |
177 | 242 | for tree_file_id in specific_file_ids: | 287 | for path in specific_files: |
178 | 243 | inventory, inv_file_id = self._unpack_file_id(tree_file_id) | 288 | inventory, inv_file_id = self._path2inv_file_id(path) |
179 | 244 | if not inventory is self.root_inventory: # for now | 289 | if not inventory is self.root_inventory: # for now |
180 | 245 | raise AssertionError("%r != %r" % ( | 290 | raise AssertionError("%r != %r" % ( |
181 | 246 | inventory, self.root_inventory)) | 291 | inventory, self.root_inventory)) |
182 | 247 | inventory_file_ids.append(inv_file_id) | 292 | inventory_file_ids.append(inv_file_id) |
183 | 293 | else: | ||
184 | 294 | inventory_file_ids = None | ||
185 | 248 | # FIXME: Handle nested trees | 295 | # FIXME: Handle nested trees |
186 | 249 | return self.root_inventory.iter_entries_by_dir( | 296 | return self.root_inventory.iter_entries_by_dir( |
187 | 250 | specific_file_ids=inventory_file_ids, yield_parents=yield_parents) | 297 | specific_file_ids=inventory_file_ids, yield_parents=yield_parents) |
188 | @@ -319,6 +366,84 @@ | |||
189 | 319 | return last_revision | 366 | return last_revision |
190 | 320 | 367 | ||
191 | 321 | 368 | ||
192 | 369 | def find_ids_across_trees(filenames, trees, require_versioned=True): | ||
193 | 370 | """Find the ids corresponding to specified filenames. | ||
194 | 371 | |||
195 | 372 | All matches in all trees will be used, and all children of matched | ||
196 | 373 | directories will be used. | ||
197 | 374 | |||
198 | 375 | :param filenames: The filenames to find file_ids for (if None, returns | ||
199 | 376 | None) | ||
200 | 377 | :param trees: The trees to find file_ids within | ||
201 | 378 | :param require_versioned: if true, all specified filenames must occur in | ||
202 | 379 | at least one tree. | ||
203 | 380 | :return: a set of file ids for the specified filenames and their children. | ||
204 | 381 | """ | ||
205 | 382 | if not filenames: | ||
206 | 383 | return None | ||
207 | 384 | specified_path_ids = _find_ids_across_trees(filenames, trees, | ||
208 | 385 | require_versioned) | ||
209 | 386 | return _find_children_across_trees(specified_path_ids, trees) | ||
210 | 387 | |||
211 | 388 | |||
212 | 389 | def _find_ids_across_trees(filenames, trees, require_versioned): | ||
213 | 390 | """Find the ids corresponding to specified filenames. | ||
214 | 391 | |||
215 | 392 | All matches in all trees will be used, but subdirectories are not scanned. | ||
216 | 393 | |||
217 | 394 | :param filenames: The filenames to find file_ids for | ||
218 | 395 | :param trees: The trees to find file_ids within | ||
219 | 396 | :param require_versioned: if true, all specified filenames must occur in | ||
220 | 397 | at least one tree. | ||
221 | 398 | :return: a set of file ids for the specified filenames | ||
222 | 399 | """ | ||
223 | 400 | not_versioned = [] | ||
224 | 401 | interesting_ids = set() | ||
225 | 402 | for tree_path in filenames: | ||
226 | 403 | not_found = True | ||
227 | 404 | for tree in trees: | ||
228 | 405 | file_id = tree.path2id(tree_path) | ||
229 | 406 | if file_id is not None: | ||
230 | 407 | interesting_ids.add(file_id) | ||
231 | 408 | not_found = False | ||
232 | 409 | if not_found: | ||
233 | 410 | not_versioned.append(tree_path) | ||
234 | 411 | if len(not_versioned) > 0 and require_versioned: | ||
235 | 412 | raise errors.PathsNotVersionedError(not_versioned) | ||
236 | 413 | return interesting_ids | ||
237 | 414 | |||
238 | 415 | |||
239 | 416 | def _find_children_across_trees(specified_ids, trees): | ||
240 | 417 | """Return a set including specified ids and their children. | ||
241 | 418 | |||
242 | 419 | All matches in all trees will be used. | ||
243 | 420 | |||
244 | 421 | :param trees: The trees to find file_ids within | ||
245 | 422 | :return: a set containing all specified ids and their children | ||
246 | 423 | """ | ||
247 | 424 | interesting_ids = set(specified_ids) | ||
248 | 425 | pending = interesting_ids | ||
249 | 426 | # now handle children of interesting ids | ||
250 | 427 | # we loop so that we handle all children of each id in both trees | ||
251 | 428 | while len(pending) > 0: | ||
252 | 429 | new_pending = set() | ||
253 | 430 | for file_id in pending: | ||
254 | 431 | for tree in trees: | ||
255 | 432 | try: | ||
256 | 433 | path = tree.id2path(file_id) | ||
257 | 434 | except errors.NoSuchId: | ||
258 | 435 | continue | ||
259 | 436 | try: | ||
260 | 437 | for child in tree.iter_child_entries(path, file_id): | ||
261 | 438 | if child.file_id not in interesting_ids: | ||
262 | 439 | new_pending.add(child.file_id) | ||
263 | 440 | except errors.NotADirectory: | ||
264 | 441 | pass | ||
265 | 442 | interesting_ids.update(new_pending) | ||
266 | 443 | pending = new_pending | ||
267 | 444 | return interesting_ids | ||
268 | 445 | |||
269 | 446 | |||
270 | 322 | class MutableInventoryTree(MutableTree, InventoryTree): | 447 | class MutableInventoryTree(MutableTree, InventoryTree): |
271 | 323 | 448 | ||
272 | 324 | def apply_inventory_delta(self, changes): | 449 | def apply_inventory_delta(self, changes): |
273 | @@ -442,10 +567,11 @@ | |||
274 | 442 | return entry[3] | 567 | return entry[3] |
275 | 443 | # Find a 'best fit' match if the filesystem is case-insensitive | 568 | # Find a 'best fit' match if the filesystem is case-insensitive |
276 | 444 | inv_path = self.tree._fix_case_of_inventory_path(inv_path) | 569 | inv_path = self.tree._fix_case_of_inventory_path(inv_path) |
281 | 445 | file_id = self.tree.path2id(inv_path) | 570 | try: |
282 | 446 | if file_id is not None: | 571 | return self.tree.iter_entries_by_dir( |
283 | 447 | return self.tree.iter_entries_by_dir([file_id]).next()[1] | 572 | specific_files=[inv_path]).next()[1] |
284 | 448 | return None | 573 | except StopIteration: |
285 | 574 | return None | ||
286 | 449 | 575 | ||
287 | 450 | def _convert_to_directory(self, this_ie, inv_path): | 576 | def _convert_to_directory(self, this_ie, inv_path): |
288 | 451 | """Convert an entry to a directory. | 577 | """Convert an entry to a directory. |
289 | 452 | 578 | ||
290 | === modified file 'breezy/bzr/workingtree.py' | |||
291 | --- breezy/bzr/workingtree.py 2018-03-04 19:11:21 +0000 | |||
292 | +++ breezy/bzr/workingtree.py 2018-03-24 01:23:20 +0000 | |||
293 | @@ -652,10 +652,7 @@ | |||
294 | 652 | file_ids are in a WorkingTree if they are in the working inventory | 652 | file_ids are in a WorkingTree if they are in the working inventory |
295 | 653 | and the working file exists. | 653 | and the working file exists. |
296 | 654 | """ | 654 | """ |
301 | 655 | ret = set() | 655 | return {ie.file_id for path, ie in self.iter_entries_by_dir()} |
298 | 656 | for path, ie in self.iter_entries_by_dir(): | ||
299 | 657 | ret.add(ie.file_id) | ||
300 | 658 | return ret | ||
302 | 659 | 656 | ||
303 | 660 | def all_versioned_paths(self): | 657 | def all_versioned_paths(self): |
304 | 661 | return {path for path, ie in self.iter_entries_by_dir()} | 658 | return {path for path, ie in self.iter_entries_by_dir()} |
305 | @@ -1699,13 +1696,13 @@ | |||
306 | 1699 | blocked_parent_ids.add(ie.file_id) | 1696 | blocked_parent_ids.add(ie.file_id) |
307 | 1700 | yield path, ie | 1697 | yield path, ie |
308 | 1701 | 1698 | ||
310 | 1702 | def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False): | 1699 | def iter_entries_by_dir(self, specific_files=None, |
311 | 1700 | yield_parents=False): | ||
312 | 1703 | """See Tree.iter_entries_by_dir()""" | 1701 | """See Tree.iter_entries_by_dir()""" |
313 | 1704 | # The only trick here is that if we supports_tree_reference then we | 1702 | # The only trick here is that if we supports_tree_reference then we |
314 | 1705 | # need to detect if a directory becomes a tree-reference. | 1703 | # need to detect if a directory becomes a tree-reference. |
315 | 1706 | iterator = super(WorkingTree, self).iter_entries_by_dir( | 1704 | iterator = super(WorkingTree, self).iter_entries_by_dir( |
318 | 1707 | specific_file_ids=specific_file_ids, | 1705 | specific_files=specific_files, yield_parents=yield_parents) |
317 | 1708 | yield_parents=yield_parents) | ||
319 | 1709 | if not self.supports_tree_reference(): | 1706 | if not self.supports_tree_reference(): |
320 | 1710 | return iterator | 1707 | return iterator |
321 | 1711 | else: | 1708 | else: |
322 | 1712 | 1709 | ||
323 | === modified file 'breezy/filter_tree.py' | |||
324 | --- breezy/filter_tree.py 2018-03-23 23:32:28 +0000 | |||
325 | +++ breezy/filter_tree.py 2018-03-24 01:23:20 +0000 | |||
326 | @@ -58,14 +58,14 @@ | |||
327 | 58 | def is_executable(self, path, file_id=None): | 58 | def is_executable(self, path, file_id=None): |
328 | 59 | return self.backing_tree.is_executable(path, file_id) | 59 | return self.backing_tree.is_executable(path, file_id) |
329 | 60 | 60 | ||
331 | 61 | def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=None): | 61 | def iter_entries_by_dir(self, specific_files=None, yield_parents=None): |
332 | 62 | # NB: This simply returns the parent tree's entries; the length may be | 62 | # NB: This simply returns the parent tree's entries; the length may be |
333 | 63 | # wrong but it can't easily be calculated without filtering the whole | 63 | # wrong but it can't easily be calculated without filtering the whole |
334 | 64 | # text. Currently all callers cope with this; perhaps they should be | 64 | # text. Currently all callers cope with this; perhaps they should be |
335 | 65 | # updated to a narrower interface that only provides things guaranteed | 65 | # updated to a narrower interface that only provides things guaranteed |
336 | 66 | # cheaply available across all trees. -- mbp 20110705 | 66 | # cheaply available across all trees. -- mbp 20110705 |
337 | 67 | return self.backing_tree.iter_entries_by_dir( | 67 | return self.backing_tree.iter_entries_by_dir( |
339 | 68 | specific_file_ids=specific_file_ids, | 68 | specific_files=specific_files, |
340 | 69 | yield_parents=yield_parents) | 69 | yield_parents=yield_parents) |
341 | 70 | 70 | ||
342 | 71 | def lock_read(self): | 71 | def lock_read(self): |
343 | 72 | 72 | ||
344 | === modified file 'breezy/merge.py' | |||
345 | --- breezy/merge.py 2018-03-24 00:39:56 +0000 | |||
346 | +++ breezy/merge.py 2018-03-24 01:23:20 +0000 | |||
347 | @@ -56,12 +56,13 @@ | |||
348 | 56 | # TODO: Report back as changes are merged in | 56 | # TODO: Report back as changes are merged in |
349 | 57 | 57 | ||
350 | 58 | 58 | ||
352 | 59 | def transform_tree(from_tree, to_tree, interesting_ids=None): | 59 | def transform_tree(from_tree, to_tree, interesting_files=None): |
353 | 60 | from_tree.lock_tree_write() | 60 | from_tree.lock_tree_write() |
354 | 61 | operation = cleanup.OperationWithCleanups(merge_inner) | 61 | operation = cleanup.OperationWithCleanups(merge_inner) |
355 | 62 | operation.add_cleanup(from_tree.unlock) | 62 | operation.add_cleanup(from_tree.unlock) |
356 | 63 | operation.run_simple(from_tree.branch, to_tree, from_tree, | 63 | operation.run_simple(from_tree.branch, to_tree, from_tree, |
358 | 64 | ignore_zero=True, interesting_ids=interesting_ids, this_tree=from_tree) | 64 | ignore_zero=True, this_tree=from_tree, |
359 | 65 | interesting_files=interesting_files) | ||
360 | 65 | 66 | ||
361 | 66 | 67 | ||
362 | 67 | class MergeHooks(hooks.Hooks): | 68 | class MergeHooks(hooks.Hooks): |
363 | @@ -295,7 +296,6 @@ | |||
364 | 295 | self.base_tree = base_tree | 296 | self.base_tree = base_tree |
365 | 296 | self.ignore_zero = False | 297 | self.ignore_zero = False |
366 | 297 | self.backup_files = False | 298 | self.backup_files = False |
367 | 298 | self.interesting_ids = None | ||
368 | 299 | self.interesting_files = None | 299 | self.interesting_files = None |
369 | 300 | self.show_base = False | 300 | self.show_base = False |
370 | 301 | self.reprocess = False | 301 | self.reprocess = False |
371 | @@ -610,7 +610,6 @@ | |||
372 | 610 | def make_merger(self): | 610 | def make_merger(self): |
373 | 611 | kwargs = {'working_tree': self.this_tree, 'this_tree': self.this_tree, | 611 | kwargs = {'working_tree': self.this_tree, 'this_tree': self.this_tree, |
374 | 612 | 'other_tree': self.other_tree, | 612 | 'other_tree': self.other_tree, |
375 | 613 | 'interesting_ids': self.interesting_ids, | ||
376 | 614 | 'interesting_files': self.interesting_files, | 613 | 'interesting_files': self.interesting_files, |
377 | 615 | 'this_branch': self.this_branch, | 614 | 'this_branch': self.this_branch, |
378 | 616 | 'other_branch': self.other_branch, | 615 | 'other_branch': self.other_branch, |
379 | @@ -722,7 +721,7 @@ | |||
380 | 722 | requires_file_merge_plan = False | 721 | requires_file_merge_plan = False |
381 | 723 | 722 | ||
382 | 724 | def __init__(self, working_tree, this_tree, base_tree, other_tree, | 723 | def __init__(self, working_tree, this_tree, base_tree, other_tree, |
384 | 725 | interesting_ids=None, reprocess=False, show_base=False, | 724 | reprocess=False, show_base=False, |
385 | 726 | change_reporter=None, interesting_files=None, do_merge=True, | 725 | change_reporter=None, interesting_files=None, do_merge=True, |
386 | 727 | cherrypick=False, lca_trees=None, this_branch=None, | 726 | cherrypick=False, lca_trees=None, this_branch=None, |
387 | 728 | other_branch=None): | 727 | other_branch=None): |
388 | @@ -735,30 +734,22 @@ | |||
389 | 735 | :param this_branch: The branch associated with this_tree. Defaults to | 734 | :param this_branch: The branch associated with this_tree. Defaults to |
390 | 736 | this_tree.branch if not supplied. | 735 | this_tree.branch if not supplied. |
391 | 737 | :param other_branch: The branch associated with other_tree, if any. | 736 | :param other_branch: The branch associated with other_tree, if any. |
392 | 738 | :param interesting_ids: The file_ids of files that should be | ||
393 | 739 | participate in the merge. May not be combined with | ||
394 | 740 | interesting_files. | ||
395 | 741 | :param: reprocess If True, perform conflict-reduction processing. | 737 | :param: reprocess If True, perform conflict-reduction processing. |
396 | 742 | :param show_base: If True, show the base revision in text conflicts. | 738 | :param show_base: If True, show the base revision in text conflicts. |
397 | 743 | (incompatible with reprocess) | 739 | (incompatible with reprocess) |
398 | 744 | :param change_reporter: An object that should report changes made | 740 | :param change_reporter: An object that should report changes made |
399 | 745 | :param interesting_files: The tree-relative paths of files that should | 741 | :param interesting_files: The tree-relative paths of files that should |
400 | 746 | participate in the merge. If these paths refer to directories, | 742 | participate in the merge. If these paths refer to directories, |
404 | 747 | the contents of those directories will also be included. May not | 743 | the contents of those directories will also be included. If not |
405 | 748 | be combined with interesting_ids. If neither interesting_files nor | 744 | specified, all files may participate in the |
403 | 749 | interesting_ids is specified, all files may participate in the | ||
406 | 750 | merge. | 745 | merge. |
407 | 751 | :param lca_trees: Can be set to a dictionary of {revision_id:rev_tree} | 746 | :param lca_trees: Can be set to a dictionary of {revision_id:rev_tree} |
408 | 752 | if the ancestry was found to include a criss-cross merge. | 747 | if the ancestry was found to include a criss-cross merge. |
409 | 753 | Otherwise should be None. | 748 | Otherwise should be None. |
410 | 754 | """ | 749 | """ |
411 | 755 | object.__init__(self) | 750 | object.__init__(self) |
412 | 756 | if interesting_files is not None and interesting_ids is not None: | ||
413 | 757 | raise ValueError( | ||
414 | 758 | 'specify either interesting_ids or interesting_files') | ||
415 | 759 | if this_branch is None: | 751 | if this_branch is None: |
416 | 760 | this_branch = this_tree.branch | 752 | this_branch = this_tree.branch |
417 | 761 | self.interesting_ids = interesting_ids | ||
418 | 762 | self.interesting_files = interesting_files | 753 | self.interesting_files = interesting_files |
419 | 763 | self.working_tree = working_tree | 754 | self.working_tree = working_tree |
420 | 764 | self.this_tree = this_tree | 755 | self.this_tree = this_tree |
421 | @@ -874,14 +865,13 @@ | |||
422 | 874 | iterator = self.other_tree.iter_changes(self.base_tree, | 865 | iterator = self.other_tree.iter_changes(self.base_tree, |
423 | 875 | specific_files=self.interesting_files, | 866 | specific_files=self.interesting_files, |
424 | 876 | extra_trees=[self.this_tree]) | 867 | extra_trees=[self.this_tree]) |
425 | 868 | this_interesting_files = self.this_tree.find_related_paths_across_trees( | ||
426 | 869 | self.interesting_files, trees=[self.other_tree]) | ||
427 | 877 | this_entries = dict((e.file_id, e) for p, e in | 870 | this_entries = dict((e.file_id, e) for p, e in |
428 | 878 | self.this_tree.iter_entries_by_dir( | 871 | self.this_tree.iter_entries_by_dir( |
430 | 879 | self.interesting_ids)) | 872 | specific_files=this_interesting_files)) |
431 | 880 | for (file_id, paths, changed, versioned, parents, names, kind, | 873 | for (file_id, paths, changed, versioned, parents, names, kind, |
432 | 881 | executable) in iterator: | 874 | executable) in iterator: |
433 | 882 | if (self.interesting_ids is not None and | ||
434 | 883 | file_id not in self.interesting_ids): | ||
435 | 884 | continue | ||
436 | 885 | entry = this_entries.get(file_id) | 875 | entry = this_entries.get(file_id) |
437 | 886 | if entry is not None: | 876 | if entry is not None: |
438 | 887 | this_name = entry.name | 877 | this_name = entry.name |
439 | @@ -919,10 +909,10 @@ | |||
440 | 919 | lookup_trees = [self.this_tree, self.base_tree] | 909 | lookup_trees = [self.this_tree, self.base_tree] |
441 | 920 | lookup_trees.extend(self._lca_trees) | 910 | lookup_trees.extend(self._lca_trees) |
442 | 921 | # I think we should include the lca trees as well | 911 | # I think we should include the lca trees as well |
445 | 922 | interesting_ids = self.other_tree.paths2ids(self.interesting_files, | 912 | interesting_files = self.other_tree.find_related_paths_across_trees( |
446 | 923 | lookup_trees) | 913 | self.interesting_files, lookup_trees) |
447 | 924 | else: | 914 | else: |
449 | 925 | interesting_ids = self.interesting_ids | 915 | interesting_files = None |
450 | 926 | result = [] | 916 | result = [] |
451 | 927 | walker = _mod_tree.MultiWalker(self.other_tree, self._lca_trees) | 917 | walker = _mod_tree.MultiWalker(self.other_tree, self._lca_trees) |
452 | 928 | 918 | ||
453 | @@ -932,7 +922,7 @@ | |||
454 | 932 | # Is this modified at all from any of the other trees? | 922 | # Is this modified at all from any of the other trees? |
455 | 933 | if other_ie is None: | 923 | if other_ie is None: |
456 | 934 | other_ie = _none_entry | 924 | other_ie = _none_entry |
458 | 935 | if interesting_ids is not None and file_id not in interesting_ids: | 925 | if interesting_files is not None and path not in interesting_files: |
459 | 936 | continue | 926 | continue |
460 | 937 | 927 | ||
461 | 938 | # If other_revision is found in any of the lcas, that means this | 928 | # If other_revision is found in any of the lcas, that means this |
462 | @@ -1815,7 +1805,7 @@ | |||
463 | 1815 | self.merge_type = Merge3Merger | 1805 | self.merge_type = Merge3Merger |
464 | 1816 | self.show_base = False | 1806 | self.show_base = False |
465 | 1817 | self.reprocess = False | 1807 | self.reprocess = False |
467 | 1818 | self.interesting_ids = None | 1808 | self.interesting_files = None |
468 | 1819 | self.merge_type = _MergeTypeParameterizer(MergeIntoMergeType, | 1809 | self.merge_type = _MergeTypeParameterizer(MergeIntoMergeType, |
469 | 1820 | target_subdir=self._target_subdir, | 1810 | target_subdir=self._target_subdir, |
470 | 1821 | source_subpath=self._source_subpath) | 1811 | source_subpath=self._source_subpath) |
471 | @@ -1926,7 +1916,6 @@ | |||
472 | 1926 | def merge_inner(this_branch, other_tree, base_tree, ignore_zero=False, | 1916 | def merge_inner(this_branch, other_tree, base_tree, ignore_zero=False, |
473 | 1927 | backup_files=False, | 1917 | backup_files=False, |
474 | 1928 | merge_type=Merge3Merger, | 1918 | merge_type=Merge3Merger, |
475 | 1929 | interesting_ids=None, | ||
476 | 1930 | show_base=False, | 1919 | show_base=False, |
477 | 1931 | reprocess=False, | 1920 | reprocess=False, |
478 | 1932 | other_rev_id=None, | 1921 | other_rev_id=None, |
479 | @@ -1947,13 +1936,8 @@ | |||
480 | 1947 | change_reporter=change_reporter) | 1936 | change_reporter=change_reporter) |
481 | 1948 | merger.backup_files = backup_files | 1937 | merger.backup_files = backup_files |
482 | 1949 | merger.merge_type = merge_type | 1938 | merger.merge_type = merge_type |
483 | 1950 | merger.interesting_ids = interesting_ids | ||
484 | 1951 | merger.ignore_zero = ignore_zero | 1939 | merger.ignore_zero = ignore_zero |
490 | 1952 | if interesting_files: | 1940 | merger.interesting_files = interesting_files |
486 | 1953 | if interesting_ids: | ||
487 | 1954 | raise ValueError('Only supply interesting_ids' | ||
488 | 1955 | ' or interesting_files') | ||
489 | 1956 | merger.interesting_files = interesting_files | ||
491 | 1957 | merger.show_base = show_base | 1941 | merger.show_base = show_base |
492 | 1958 | merger.reprocess = reprocess | 1942 | merger.reprocess = reprocess |
493 | 1959 | merger.other_rev_id = other_rev_id | 1943 | merger.other_rev_id = other_rev_id |
494 | 1960 | 1944 | ||
495 | === modified file 'breezy/rename_map.py' | |||
496 | --- breezy/rename_map.py 2018-03-12 01:24:43 +0000 | |||
497 | +++ breezy/rename_map.py 2018-03-24 01:23:20 +0000 | |||
498 | @@ -26,6 +26,7 @@ | |||
499 | 26 | from .sixish import ( | 26 | from .sixish import ( |
500 | 27 | BytesIO, | 27 | BytesIO, |
501 | 28 | viewitems, | 28 | viewitems, |
502 | 29 | viewvalues, | ||
503 | 29 | ) | 30 | ) |
504 | 30 | from .ui import ui_factory | 31 | from .ui import ui_factory |
505 | 31 | 32 | ||
506 | @@ -237,7 +238,14 @@ | |||
507 | 237 | def _make_inventory_delta(self, matches): | 238 | def _make_inventory_delta(self, matches): |
508 | 238 | delta = [] | 239 | delta = [] |
509 | 239 | file_id_matches = dict((f, p) for p, f in viewitems(matches)) | 240 | file_id_matches = dict((f, p) for p, f in viewitems(matches)) |
511 | 240 | for old_path, entry in self.tree.iter_entries_by_dir(file_id_matches): | 241 | file_id_query = [] |
512 | 242 | for f in viewvalues(matches): | ||
513 | 243 | try: | ||
514 | 244 | file_id_query.append(self.tree.id2path(f)) | ||
515 | 245 | except errors.NoSuchId: | ||
516 | 246 | pass | ||
517 | 247 | for old_path, entry in self.tree.iter_entries_by_dir( | ||
518 | 248 | specific_files=file_id_query): | ||
519 | 241 | new_path = file_id_matches[entry.file_id] | 249 | new_path = file_id_matches[entry.file_id] |
520 | 242 | parent_path, new_name = osutils.split(new_path) | 250 | parent_path, new_name = osutils.split(new_path) |
521 | 243 | parent_id = matches.get(parent_path) | 251 | parent_id = matches.get(parent_path) |
522 | 244 | 252 | ||
523 | === modified file 'breezy/tests/per_intertree/test_compare.py' | |||
524 | --- breezy/tests/per_intertree/test_compare.py 2017-11-21 20:37:41 +0000 | |||
525 | +++ breezy/tests/per_intertree/test_compare.py 2018-03-24 01:23:20 +0000 | |||
526 | @@ -557,7 +557,9 @@ | |||
527 | 557 | 557 | ||
528 | 558 | @staticmethod | 558 | @staticmethod |
529 | 559 | def get_path_entry(tree, file_id): | 559 | def get_path_entry(tree, file_id): |
531 | 560 | iterator = tree.iter_entries_by_dir(specific_file_ids=[file_id]) | 560 | with tree.lock_read(): |
532 | 561 | path = tree.id2path(file_id) | ||
533 | 562 | iterator = tree.iter_entries_by_dir(specific_files=[path]) | ||
534 | 561 | try: | 563 | try: |
535 | 562 | return next(iterator) | 564 | return next(iterator) |
536 | 563 | except StopIteration: | 565 | except StopIteration: |
537 | 564 | 566 | ||
538 | === modified file 'breezy/tests/per_tree/test_inv.py' | |||
539 | --- breezy/tests/per_tree/test_inv.py 2017-08-01 01:44:41 +0000 | |||
540 | +++ breezy/tests/per_tree/test_inv.py 2018-03-24 01:23:20 +0000 | |||
541 | @@ -33,8 +33,8 @@ | |||
542 | 33 | ) | 33 | ) |
543 | 34 | 34 | ||
544 | 35 | 35 | ||
547 | 36 | def get_entry(tree, file_id): | 36 | def get_entry(tree, path): |
548 | 37 | return tree.iter_entries_by_dir([file_id]).next()[1] | 37 | return tree.iter_entries_by_dir(specific_files=[path]).next()[1] |
549 | 38 | 38 | ||
550 | 39 | 39 | ||
551 | 40 | class TestInventoryWithSymlinks(per_tree.TestCaseWithTree): | 40 | class TestInventoryWithSymlinks(per_tree.TestCaseWithTree): |
552 | @@ -52,7 +52,7 @@ | |||
553 | 52 | raise TestSkipped( | 52 | raise TestSkipped( |
554 | 53 | 'symlinks not accurately represented in working trees and' | 53 | 'symlinks not accurately represented in working trees and' |
555 | 54 | ' preview trees') | 54 | ' preview trees') |
557 | 55 | entry = get_entry(self.tree, self.tree.path2id('symlink')) | 55 | entry = get_entry(self.tree, 'symlink') |
558 | 56 | self.assertEqual(entry.symlink_target, 'link-target') | 56 | self.assertEqual(entry.symlink_target, 'link-target') |
559 | 57 | 57 | ||
560 | 58 | def test_symlink_target_tree(self): | 58 | def test_symlink_target_tree(self): |
561 | @@ -64,7 +64,7 @@ | |||
562 | 64 | self.assertIs(None, self.tree.get_file_size('symlink')) | 64 | self.assertIs(None, self.tree.get_file_size('symlink')) |
563 | 65 | 65 | ||
564 | 66 | def test_symlink(self): | 66 | def test_symlink(self): |
566 | 67 | entry = get_entry(self.tree, self.tree.path2id('symlink')) | 67 | entry = get_entry(self.tree, 'symlink') |
567 | 68 | self.assertEqual(entry.kind, 'symlink') | 68 | self.assertEqual(entry.kind, 'symlink') |
568 | 69 | self.assertEqual(None, entry.text_size) | 69 | self.assertEqual(None, entry.text_size) |
569 | 70 | 70 | ||
570 | @@ -76,6 +76,9 @@ | |||
571 | 76 | self.build_tree(['tree/dir/', 'tree/dir/file']) | 76 | self.build_tree(['tree/dir/', 'tree/dir/file']) |
572 | 77 | work_tree.add(['dir', 'dir/file']) | 77 | work_tree.add(['dir', 'dir/file']) |
573 | 78 | tree = self._convert_tree(work_tree) | 78 | tree = self._convert_tree(work_tree) |
574 | 79 | if not isinstance(tree, InventoryTree): | ||
575 | 80 | raise tests.TestNotApplicable( | ||
576 | 81 | "test not applicable on non-inventory tests") | ||
577 | 79 | tree.lock_read() | 82 | tree.lock_read() |
578 | 80 | self.addCleanup(tree.unlock) | 83 | self.addCleanup(tree.unlock) |
579 | 81 | self.assertEqual({tree.path2id('dir'), tree.path2id('dir/file')}, | 84 | self.assertEqual({tree.path2id('dir'), tree.path2id('dir/file')}, |
580 | @@ -88,6 +91,9 @@ | |||
581 | 88 | work_tree.commit('commit old state') | 91 | work_tree.commit('commit old state') |
582 | 89 | work_tree.remove('file') | 92 | work_tree.remove('file') |
583 | 90 | tree = self._convert_tree(work_tree) | 93 | tree = self._convert_tree(work_tree) |
584 | 94 | if not isinstance(tree, InventoryTree): | ||
585 | 95 | raise tests.TestNotApplicable( | ||
586 | 96 | "test not applicable on non-inventory tests") | ||
587 | 91 | tree.lock_read() | 97 | tree.lock_read() |
588 | 92 | self.addCleanup(tree.unlock) | 98 | self.addCleanup(tree.unlock) |
589 | 93 | self.assertEqual(set([]), tree.paths2ids(['file'], | 99 | self.assertEqual(set([]), tree.paths2ids(['file'], |
590 | 94 | 100 | ||
591 | === modified file 'breezy/tests/per_tree/test_test_trees.py' | |||
592 | --- breezy/tests/per_tree/test_test_trees.py 2018-02-26 13:36:15 +0000 | |||
593 | +++ breezy/tests/per_tree/test_test_trees.py 2018-03-24 01:23:20 +0000 | |||
594 | @@ -228,11 +228,8 @@ | |||
595 | 228 | (u'ba\N{Euro Sign}r/ba\N{Euro Sign}z', | 228 | (u'ba\N{Euro Sign}r/ba\N{Euro Sign}z', |
596 | 229 | baz_id, bar_id, revision_id), | 229 | baz_id, bar_id, revision_id), |
597 | 230 | ] | 230 | ] |
600 | 231 | tree.lock_read() | 231 | with tree.lock_read(): |
599 | 232 | try: | ||
601 | 233 | path_entries = list(tree.iter_entries_by_dir()) | 232 | path_entries = list(tree.iter_entries_by_dir()) |
602 | 234 | finally: | ||
603 | 235 | tree.unlock() | ||
604 | 236 | 233 | ||
605 | 237 | for expected, (path, ie) in zip(path_and_ids, path_entries): | 234 | for expected, (path, ie) in zip(path_and_ids, path_entries): |
606 | 238 | self.assertEqual(expected[0], path) # Paths should match | 235 | self.assertEqual(expected[0], path) # Paths should match |
607 | @@ -276,11 +273,8 @@ | |||
608 | 276 | (u'ba\N{Euro Sign}r/qu\N{Euro Sign}x', | 273 | (u'ba\N{Euro Sign}r/qu\N{Euro Sign}x', |
609 | 277 | qux_id, bar_id, revision_id_2), | 274 | qux_id, bar_id, revision_id_2), |
610 | 278 | ] | 275 | ] |
613 | 279 | tree.lock_read() | 276 | with tree.lock_read(): |
612 | 280 | try: | ||
614 | 281 | path_entries = list(tree.iter_entries_by_dir()) | 277 | path_entries = list(tree.iter_entries_by_dir()) |
615 | 282 | finally: | ||
616 | 283 | tree.unlock() | ||
617 | 284 | 278 | ||
618 | 285 | for (epath, efid, eparent, erev), (path, ie) in zip(path_and_ids, | 279 | for (epath, efid, eparent, erev), (path, ie) in zip(path_and_ids, |
619 | 286 | path_entries): | 280 | path_entries): |
620 | 287 | 281 | ||
621 | === modified file 'breezy/tests/per_workingtree/test_inv.py' | |||
622 | --- breezy/tests/per_workingtree/test_inv.py 2018-02-15 19:38:33 +0000 | |||
623 | +++ breezy/tests/per_workingtree/test_inv.py 2018-03-24 01:23:20 +0000 | |||
624 | @@ -178,6 +178,6 @@ | |||
625 | 178 | # wt.current_dirstate()'s idea about what files are where. | 178 | # wt.current_dirstate()'s idea about what files are where. |
626 | 179 | ie = base.inventory['subdir-id'] | 179 | ie = base.inventory['subdir-id'] |
627 | 180 | self.assertEqual('directory', ie.kind) | 180 | self.assertEqual('directory', ie.kind) |
629 | 181 | path, ie = next(base.iter_entries_by_dir(['subdir-id'])) | 181 | path, ie = next(base.iter_entries_by_dir(specific_files=['subdir'])) |
630 | 182 | self.assertEqual('subdir', path) | 182 | self.assertEqual('subdir', path) |
631 | 183 | self.assertEqual('tree-reference', ie.kind) | 183 | self.assertEqual('tree-reference', ie.kind) |
632 | 184 | 184 | ||
633 | === modified file 'breezy/tests/per_workingtree/test_nested_specifics.py' | |||
634 | --- breezy/tests/per_workingtree/test_nested_specifics.py 2018-02-16 19:38:39 +0000 | |||
635 | +++ breezy/tests/per_workingtree/test_nested_specifics.py 2018-03-24 01:23:20 +0000 | |||
636 | @@ -79,5 +79,5 @@ | |||
637 | 79 | 79 | ||
638 | 80 | def test_iter_entries_by_dir_autodetects_subtree(self): | 80 | def test_iter_entries_by_dir_autodetects_subtree(self): |
639 | 81 | tree = self.prepare_with_subtree() | 81 | tree = self.prepare_with_subtree() |
641 | 82 | path, ie = next(tree.iter_entries_by_dir(['subtree-id'])) | 82 | path, ie = next(tree.iter_entries_by_dir(specific_files=['subtree'])) |
642 | 83 | self.assertEqual('tree-reference', ie.kind) | 83 | self.assertEqual('tree-reference', ie.kind) |
643 | 84 | 84 | ||
644 | === modified file 'breezy/tests/per_workingtree/test_paths2ids.py' | |||
645 | --- breezy/tests/per_workingtree/test_paths2ids.py 2018-02-03 13:39:29 +0000 | |||
646 | +++ breezy/tests/per_workingtree/test_paths2ids.py 2018-03-24 01:23:20 +0000 | |||
647 | @@ -22,6 +22,7 @@ | |||
648 | 22 | """ | 22 | """ |
649 | 23 | 23 | ||
650 | 24 | from breezy import errors | 24 | from breezy import errors |
651 | 25 | from breezy.bzr.inventorytree import InventoryTree | ||
652 | 25 | from breezy.tests import ( | 26 | from breezy.tests import ( |
653 | 26 | features, | 27 | features, |
654 | 27 | TestNotApplicable, | 28 | TestNotApplicable, |
655 | @@ -62,16 +63,30 @@ | |||
656 | 62 | 63 | ||
657 | 63 | def test_paths_none_result_none(self): | 64 | def test_paths_none_result_none(self): |
658 | 64 | tree = self.make_branch_and_tree('tree') | 65 | tree = self.make_branch_and_tree('tree') |
659 | 66 | if not isinstance(tree, InventoryTree): | ||
660 | 67 | raise TestNotApplicable( | ||
661 | 68 | "test not applicable on non-inventory tests") | ||
662 | 69 | |||
663 | 65 | tree.lock_read() | 70 | tree.lock_read() |
664 | 66 | self.assertEqual(None, tree.paths2ids(None)) | 71 | self.assertEqual(None, tree.paths2ids(None)) |
665 | 67 | tree.unlock() | 72 | tree.unlock() |
666 | 68 | 73 | ||
667 | 69 | def test_find_single_root(self): | 74 | def test_find_single_root(self): |
668 | 70 | tree = self.make_branch_and_tree('tree') | 75 | tree = self.make_branch_and_tree('tree') |
669 | 76 | if not isinstance(tree, InventoryTree): | ||
670 | 77 | raise TestNotApplicable( | ||
671 | 78 | "test not applicable on non-inventory tests") | ||
672 | 79 | |||
673 | 80 | |||
674 | 71 | self.assertExpectedIds([tree.path2id('')], tree, ['']) | 81 | self.assertExpectedIds([tree.path2id('')], tree, ['']) |
675 | 72 | 82 | ||
676 | 73 | def test_find_tree_and_clone_roots(self): | 83 | def test_find_tree_and_clone_roots(self): |
677 | 74 | tree = self.make_branch_and_tree('tree') | 84 | tree = self.make_branch_and_tree('tree') |
678 | 85 | if not isinstance(tree, InventoryTree): | ||
679 | 86 | raise TestNotApplicable( | ||
680 | 87 | "test not applicable on non-inventory tests") | ||
681 | 88 | |||
682 | 89 | |||
683 | 75 | clone = tree.controldir.clone('clone').open_workingtree() | 90 | clone = tree.controldir.clone('clone').open_workingtree() |
684 | 76 | clone.lock_tree_write() | 91 | clone.lock_tree_write() |
685 | 77 | clone_root_id = 'new-id' | 92 | clone_root_id = 'new-id' |
686 | @@ -136,6 +151,11 @@ | |||
687 | 136 | new-child because its under dir in new. | 151 | new-child because its under dir in new. |
688 | 137 | """ | 152 | """ |
689 | 138 | tree = self.make_branch_and_tree('tree') | 153 | tree = self.make_branch_and_tree('tree') |
690 | 154 | if not isinstance(tree, InventoryTree): | ||
691 | 155 | raise TestNotApplicable( | ||
692 | 156 | "test not applicable on non-inventory tests") | ||
693 | 157 | |||
694 | 158 | |||
695 | 139 | self.build_tree( | 159 | self.build_tree( |
696 | 140 | ['tree/dir/', 'tree/dir/child-moves', 'tree/dir/child-stays', | 160 | ['tree/dir/', 'tree/dir/child-moves', 'tree/dir/child-stays', |
697 | 141 | 'tree/dir/child-goes']) | 161 | 'tree/dir/child-goes']) |
698 | @@ -161,6 +181,11 @@ | |||
699 | 161 | 181 | ||
700 | 162 | def test_unversioned_one_tree(self): | 182 | def test_unversioned_one_tree(self): |
701 | 163 | tree = self.make_branch_and_tree('tree') | 183 | tree = self.make_branch_and_tree('tree') |
702 | 184 | if not isinstance(tree, InventoryTree): | ||
703 | 185 | raise TestNotApplicable( | ||
704 | 186 | "test not applicable on non-inventory tests") | ||
705 | 187 | |||
706 | 188 | |||
707 | 164 | self.build_tree(['tree/unversioned']) | 189 | self.build_tree(['tree/unversioned']) |
708 | 165 | self.assertExpectedIds([], tree, ['unversioned'], require_versioned=False) | 190 | self.assertExpectedIds([], tree, ['unversioned'], require_versioned=False) |
709 | 166 | tree.lock_read() | 191 | tree.lock_read() |
710 | @@ -172,6 +197,10 @@ | |||
711 | 172 | # should not raise an error: it must be unversioned in *all* trees to | 197 | # should not raise an error: it must be unversioned in *all* trees to |
712 | 173 | # error. | 198 | # error. |
713 | 174 | tree = self.make_branch_and_tree('tree') | 199 | tree = self.make_branch_and_tree('tree') |
714 | 200 | if not isinstance(tree, InventoryTree): | ||
715 | 201 | raise TestNotApplicable( | ||
716 | 202 | "test not applicable on non-inventory tests") | ||
717 | 203 | |||
718 | 175 | if not tree.supports_setting_file_ids(): | 204 | if not tree.supports_setting_file_ids(): |
719 | 176 | raise TestNotApplicable('tree does not support setting file ids') | 205 | raise TestNotApplicable('tree does not support setting file ids') |
720 | 177 | tree.commit('make basis') | 206 | tree.commit('make basis') |
721 | @@ -185,6 +214,10 @@ | |||
722 | 185 | # should not raise an error: it must be unversioned in *all* trees to | 214 | # should not raise an error: it must be unversioned in *all* trees to |
723 | 186 | # error. | 215 | # error. |
724 | 187 | tree = self.make_branch_and_tree('tree') | 216 | tree = self.make_branch_and_tree('tree') |
725 | 217 | if not isinstance(tree, InventoryTree): | ||
726 | 218 | raise TestNotApplicable( | ||
727 | 219 | "test not applicable on non-inventory tests") | ||
728 | 220 | |||
729 | 188 | tree.commit('make basis') | 221 | tree.commit('make basis') |
730 | 189 | basis = tree.basis_tree() | 222 | basis = tree.basis_tree() |
731 | 190 | self.assertExpectedIds([], tree, ['unversioned'], [basis], | 223 | self.assertExpectedIds([], tree, ['unversioned'], [basis], |
732 | @@ -201,6 +234,10 @@ | |||
733 | 201 | def test_unversioned_non_ascii_one_tree(self): | 234 | def test_unversioned_non_ascii_one_tree(self): |
734 | 202 | self.requireFeature(features.UnicodeFilenameFeature) | 235 | self.requireFeature(features.UnicodeFilenameFeature) |
735 | 203 | tree = self.make_branch_and_tree('.') | 236 | tree = self.make_branch_and_tree('.') |
736 | 237 | if not isinstance(tree, InventoryTree): | ||
737 | 238 | raise TestNotApplicable( | ||
738 | 239 | "test not applicable on non-inventory tests") | ||
739 | 240 | |||
740 | 204 | self.build_tree([u"\xa7"]) | 241 | self.build_tree([u"\xa7"]) |
741 | 205 | self.assertExpectedIds([], tree, [u"\xa7"], require_versioned=False) | 242 | self.assertExpectedIds([], tree, [u"\xa7"], require_versioned=False) |
742 | 206 | self.addCleanup(tree.lock_read().unlock) | 243 | self.addCleanup(tree.lock_read().unlock) |
743 | 207 | 244 | ||
744 | === modified file 'breezy/tests/test_merge.py' | |||
745 | --- breezy/tests/test_merge.py 2018-03-20 00:30:39 +0000 | |||
746 | +++ breezy/tests/test_merge.py 2018-03-24 01:23:20 +0000 | |||
747 | @@ -1265,8 +1265,7 @@ | |||
748 | 1265 | builder.build_snapshot(['B-id', 'C-id'], [], revision_id='D-id') | 1265 | builder.build_snapshot(['B-id', 'C-id'], [], revision_id='D-id') |
749 | 1266 | return builder | 1266 | return builder |
750 | 1267 | 1267 | ||
753 | 1268 | def make_Merger(self, builder, other_revision_id, | 1268 | def make_Merger(self, builder, other_revision_id, interesting_files=None): |
752 | 1269 | interesting_files=None, interesting_ids=None): | ||
754 | 1270 | """Make a Merger object from a branch builder""" | 1269 | """Make a Merger object from a branch builder""" |
755 | 1271 | mem_tree = memorytree.MemoryTree.create_on_branch(builder.get_branch()) | 1270 | mem_tree = memorytree.MemoryTree.create_on_branch(builder.get_branch()) |
756 | 1272 | mem_tree.lock_write() | 1271 | mem_tree.lock_write() |
757 | @@ -1274,8 +1273,6 @@ | |||
758 | 1274 | merger = _mod_merge.Merger.from_revision_ids( | 1273 | merger = _mod_merge.Merger.from_revision_ids( |
759 | 1275 | mem_tree, other_revision_id) | 1274 | mem_tree, other_revision_id) |
760 | 1276 | merger.set_interesting_files(interesting_files) | 1275 | merger.set_interesting_files(interesting_files) |
761 | 1277 | # It seems there is no matching function for set_interesting_ids | ||
762 | 1278 | merger.interesting_ids = interesting_ids | ||
763 | 1279 | merger.merge_type = _mod_merge.Merge3Merger | 1276 | merger.merge_type = _mod_merge.Merge3Merger |
764 | 1280 | return merger | 1277 | return merger |
765 | 1281 | 1278 | ||
766 | @@ -1400,10 +1397,9 @@ | |||
767 | 1400 | class TestMergerEntriesLCA(TestMergerBase): | 1397 | class TestMergerEntriesLCA(TestMergerBase): |
768 | 1401 | 1398 | ||
769 | 1402 | def make_merge_obj(self, builder, other_revision_id, | 1399 | def make_merge_obj(self, builder, other_revision_id, |
771 | 1403 | interesting_files=None, interesting_ids=None): | 1400 | interesting_files=None): |
772 | 1404 | merger = self.make_Merger(builder, other_revision_id, | 1401 | merger = self.make_Merger(builder, other_revision_id, |
775 | 1405 | interesting_files=interesting_files, | 1402 | interesting_files=interesting_files) |
774 | 1406 | interesting_ids=interesting_ids) | ||
776 | 1407 | return merger.make_merger() | 1403 | return merger.make_merger() |
777 | 1408 | 1404 | ||
778 | 1409 | def test_simple(self): | 1405 | def test_simple(self): |
779 | @@ -2099,7 +2095,7 @@ | |||
780 | 2099 | ((False, [False, False]), False, False)), | 2095 | ((False, [False, False]), False, False)), |
781 | 2100 | ], entries) | 2096 | ], entries) |
782 | 2101 | 2097 | ||
784 | 2102 | def test_interesting_ids(self): | 2098 | def test_interesting_files(self): |
785 | 2103 | # Two files modified, but we should filter one of them | 2099 | # Two files modified, but we should filter one of them |
786 | 2104 | builder = self.get_builder() | 2100 | builder = self.get_builder() |
787 | 2105 | builder.build_snapshot(None, | 2101 | builder.build_snapshot(None, |
788 | @@ -2114,7 +2110,7 @@ | |||
789 | 2114 | ('modify', ('b-id', 'new-content\n'))], revision_id='E-id') | 2110 | ('modify', ('b-id', 'new-content\n'))], revision_id='E-id') |
790 | 2115 | builder.build_snapshot(['B-id', 'C-id'], [], revision_id='D-id') | 2111 | builder.build_snapshot(['B-id', 'C-id'], [], revision_id='D-id') |
791 | 2116 | merge_obj = self.make_merge_obj(builder, 'E-id', | 2112 | merge_obj = self.make_merge_obj(builder, 'E-id', |
793 | 2117 | interesting_ids=['b-id']) | 2113 | interesting_files=['b']) |
794 | 2118 | entries = list(merge_obj._entries_lca()) | 2114 | entries = list(merge_obj._entries_lca()) |
795 | 2119 | root_id = 'a-root-id' | 2115 | root_id = 'a-root-id' |
796 | 2120 | self.assertEqual([('b-id', True, | 2116 | self.assertEqual([('b-id', True, |
797 | 2121 | 2117 | ||
798 | === modified file 'breezy/tests/test_merge_core.py' | |||
799 | --- breezy/tests/test_merge_core.py 2018-03-09 19:52:32 +0000 | |||
800 | +++ breezy/tests/test_merge_core.py 2018-03-24 01:23:20 +0000 | |||
801 | @@ -77,8 +77,8 @@ | |||
802 | 77 | if option is True: | 77 | if option is True: |
803 | 78 | new_file(tt) | 78 | new_file(tt) |
804 | 79 | 79 | ||
807 | 80 | def merge(self, merge_type=Merge3Merger, interesting_ids=None, **kwargs): | 80 | def merge(self, merge_type=Merge3Merger, interesting_files=None, **kwargs): |
808 | 81 | merger = self.make_merger(merge_type, interesting_ids, **kwargs) | 81 | merger = self.make_merger(merge_type, interesting_files, **kwargs) |
809 | 82 | merger.do_merge() | 82 | merger.do_merge() |
810 | 83 | return merger.cooked_conflicts | 83 | return merger.cooked_conflicts |
811 | 84 | 84 | ||
812 | @@ -86,7 +86,7 @@ | |||
813 | 86 | merger = self.make_merger(Merge3Merger, None, this_revision_tree=True) | 86 | merger = self.make_merger(Merge3Merger, None, this_revision_tree=True) |
814 | 87 | return merger.make_preview_transform() | 87 | return merger.make_preview_transform() |
815 | 88 | 88 | ||
817 | 89 | def make_merger(self, merge_type, interesting_ids, | 89 | def make_merger(self, merge_type, interesting_files, |
818 | 90 | this_revision_tree=False, **kwargs): | 90 | this_revision_tree=False, **kwargs): |
819 | 91 | self.base_tt.apply() | 91 | self.base_tt.apply() |
820 | 92 | self.base.commit('base commit') | 92 | self.base.commit('base commit') |
821 | @@ -110,7 +110,7 @@ | |||
822 | 110 | else: | 110 | else: |
823 | 111 | this_tree = self.this | 111 | this_tree = self.this |
824 | 112 | merger = merge_type(this_tree, self.this, self.base, other_basis, | 112 | merger = merge_type(this_tree, self.this, self.base, other_basis, |
826 | 113 | interesting_ids=interesting_ids, do_merge=False, | 113 | interesting_files=interesting_files, do_merge=False, |
827 | 114 | this_branch=self.this.branch, **kwargs) | 114 | this_branch=self.this.branch, **kwargs) |
828 | 115 | return merger | 115 | return merger |
829 | 116 | 116 | ||
830 | @@ -251,7 +251,7 @@ | |||
831 | 251 | builder.change_contents("1", other="text4") | 251 | builder.change_contents("1", other="text4") |
832 | 252 | builder.add_file("2", builder.tree_root, "name2", "hello1", True) | 252 | builder.add_file("2", builder.tree_root, "name2", "hello1", True) |
833 | 253 | builder.change_contents("2", other="text4") | 253 | builder.change_contents("2", other="text4") |
835 | 254 | builder.merge(interesting_ids=["1"]) | 254 | builder.merge(interesting_files=["name1"]) |
836 | 255 | self.assertEqual(builder.this.get_file("name1").read(), "text4" ) | 255 | self.assertEqual(builder.this.get_file("name1").read(), "text4" ) |
837 | 256 | self.assertEqual(builder.this.get_file("name2").read(), "hello1" ) | 256 | self.assertEqual(builder.this.get_file("name2").read(), "hello1" ) |
838 | 257 | builder.cleanup() | 257 | builder.cleanup() |
839 | 258 | 258 | ||
840 | === modified file 'breezy/tests/test_shelf.py' | |||
841 | --- breezy/tests/test_shelf.py 2017-12-12 01:19:18 +0000 | |||
842 | +++ breezy/tests/test_shelf.py 2018-03-24 01:23:20 +0000 | |||
843 | @@ -206,7 +206,7 @@ | |||
844 | 206 | 206 | ||
845 | 207 | def check_shelve_creation(self, creator, tree): | 207 | def check_shelve_creation(self, creator, tree): |
846 | 208 | self.assertRaises(StopIteration, | 208 | self.assertRaises(StopIteration, |
848 | 209 | next, tree.iter_entries_by_dir(['foo-id'])) | 209 | next, tree.iter_entries_by_dir(specific_files=['foo'])) |
849 | 210 | s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id') | 210 | s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id') |
850 | 211 | self.assertEqual('foo-id', | 211 | self.assertEqual('foo-id', |
851 | 212 | creator.shelf_transform.final_file_id(s_trans_id)) | 212 | creator.shelf_transform.final_file_id(s_trans_id)) |
852 | @@ -349,7 +349,7 @@ | |||
853 | 349 | creator.shelve_creation('foo-id') | 349 | creator.shelve_creation('foo-id') |
854 | 350 | creator.transform() | 350 | creator.transform() |
855 | 351 | self.assertRaises(StopIteration, | 351 | self.assertRaises(StopIteration, |
857 | 352 | next, tree.iter_entries_by_dir(['foo-id'])) | 352 | next, tree.iter_entries_by_dir(specific_files=['foo'])) |
858 | 353 | self.assertShelvedFileEqual('', creator, 'foo-id') | 353 | self.assertShelvedFileEqual('', creator, 'foo-id') |
859 | 354 | s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id') | 354 | s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id') |
860 | 355 | self.assertEqual('foo-id', | 355 | self.assertEqual('foo-id', |
861 | 356 | 356 | ||
862 | === modified file 'breezy/tests/test_transform.py' | |||
863 | --- breezy/tests/test_transform.py 2018-03-24 00:39:56 +0000 | |||
864 | +++ breezy/tests/test_transform.py 2018-03-24 01:23:20 +0000 | |||
865 | @@ -2937,13 +2937,14 @@ | |||
866 | 2937 | self.assertFalse(preview_tree.is_versioned('old_name/child')) | 2937 | self.assertFalse(preview_tree.is_versioned('old_name/child')) |
867 | 2938 | self.assertEqual('child-id', preview_tree.path2id('new_name/child')) | 2938 | self.assertEqual('child-id', preview_tree.path2id('new_name/child')) |
868 | 2939 | 2939 | ||
870 | 2940 | def assertMatchingIterEntries(self, tt, specific_file_ids=None): | 2940 | def assertMatchingIterEntries(self, tt, specific_files=None): |
871 | 2941 | preview_tree = tt.get_preview_tree() | 2941 | preview_tree = tt.get_preview_tree() |
872 | 2942 | preview_result = list(preview_tree.iter_entries_by_dir( | 2942 | preview_result = list(preview_tree.iter_entries_by_dir( |
874 | 2943 | specific_file_ids)) | 2943 | specific_files=specific_files)) |
875 | 2944 | tree = tt._tree | 2944 | tree = tt._tree |
876 | 2945 | tt.apply() | 2945 | tt.apply() |
878 | 2946 | actual_result = list(tree.iter_entries_by_dir(specific_file_ids)) | 2946 | actual_result = list(tree.iter_entries_by_dir( |
879 | 2947 | specific_files=specific_files)) | ||
880 | 2947 | self.assertEqual(actual_result, preview_result) | 2948 | self.assertEqual(actual_result, preview_result) |
881 | 2948 | 2949 | ||
882 | 2949 | def test_iter_entries_by_dir_new(self): | 2950 | def test_iter_entries_by_dir_new(self): |
883 | @@ -2983,7 +2984,7 @@ | |||
884 | 2983 | self.build_tree(['tree/parent/', 'tree/parent/child']) | 2984 | self.build_tree(['tree/parent/', 'tree/parent/child']) |
885 | 2984 | tree.add(['parent', 'parent/child'], ['parent-id', 'child-id']) | 2985 | tree.add(['parent', 'parent/child'], ['parent-id', 'child-id']) |
886 | 2985 | tt = TreeTransform(tree) | 2986 | tt = TreeTransform(tree) |
888 | 2986 | self.assertMatchingIterEntries(tt, ['tree-root-id', 'child-id']) | 2987 | self.assertMatchingIterEntries(tt, ['', 'parent/child']) |
889 | 2987 | 2988 | ||
890 | 2988 | def test_symlink_content_summary(self): | 2989 | def test_symlink_content_summary(self): |
891 | 2989 | self.requireFeature(SymlinkFeature) | 2990 | self.requireFeature(SymlinkFeature) |
892 | 2990 | 2991 | ||
893 | === modified file 'breezy/tests/test_workingtree.py' | |||
894 | --- breezy/tests/test_workingtree.py 2018-02-11 17:07:38 +0000 | |||
895 | +++ breezy/tests/test_workingtree.py 2018-03-24 01:23:20 +0000 | |||
896 | @@ -257,7 +257,8 @@ | |||
897 | 257 | subtree = self.make_branch_and_tree('tree/a/b') | 257 | subtree = self.make_branch_and_tree('tree/a/b') |
898 | 258 | self.assertEqual([('tree-reference', 'b-id')], | 258 | self.assertEqual([('tree-reference', 'b-id')], |
899 | 259 | [(ie.kind, ie.file_id) | 259 | [(ie.kind, ie.file_id) |
901 | 260 | for path, ie in tree.iter_entries_by_dir(['b-id'])]) | 260 | for path, ie in tree.iter_entries_by_dir( |
902 | 261 | specific_files=['a/b'])]) | ||
903 | 261 | 262 | ||
904 | 262 | def test_direct_subtree(self): | 263 | def test_direct_subtree(self): |
905 | 263 | tree = self.make_simple_tree() | 264 | tree = self.make_simple_tree() |
906 | 264 | 265 | ||
907 | === modified file 'breezy/transform.py' | |||
908 | --- breezy/transform.py 2018-03-24 00:39:56 +0000 | |||
909 | +++ breezy/transform.py 2018-03-24 01:23:20 +0000 | |||
910 | @@ -894,7 +894,7 @@ | |||
911 | 894 | to_trans_ids[to_file_id] = trans_id | 894 | to_trans_ids[to_file_id] = trans_id |
912 | 895 | return from_trans_ids, to_trans_ids | 895 | return from_trans_ids, to_trans_ids |
913 | 896 | 896 | ||
915 | 897 | def _from_file_data(self, from_trans_id, from_versioned, file_id): | 897 | def _from_file_data(self, from_trans_id, from_versioned, from_path): |
916 | 898 | """Get data about a file in the from (tree) state | 898 | """Get data about a file in the from (tree) state |
917 | 899 | 899 | ||
918 | 900 | Return a (name, parent, kind, executable) tuple | 900 | Return a (name, parent, kind, executable) tuple |
919 | @@ -902,7 +902,8 @@ | |||
920 | 902 | from_path = self._tree_id_paths.get(from_trans_id) | 902 | from_path = self._tree_id_paths.get(from_trans_id) |
921 | 903 | if from_versioned: | 903 | if from_versioned: |
922 | 904 | # get data from working tree if versioned | 904 | # get data from working tree if versioned |
924 | 905 | from_entry = self._tree.iter_entries_by_dir([file_id]).next()[1] | 905 | from_entry = self._tree.iter_entries_by_dir( |
925 | 906 | specific_files=[from_path]).next()[1] | ||
926 | 906 | from_name = from_entry.name | 907 | from_name = from_entry.name |
927 | 907 | from_parent = from_entry.parent_id | 908 | from_parent = from_entry.parent_id |
928 | 908 | else: | 909 | else: |
929 | @@ -971,12 +972,6 @@ | |||
930 | 971 | else: | 972 | else: |
931 | 972 | to_versioned = True | 973 | to_versioned = True |
932 | 973 | 974 | ||
933 | 974 | from_name, from_parent, from_kind, from_executable = \ | ||
934 | 975 | self._from_file_data(from_trans_id, from_versioned, file_id) | ||
935 | 976 | |||
936 | 977 | to_name, to_parent, to_kind, to_executable = \ | ||
937 | 978 | self._to_file_data(to_trans_id, from_trans_id, from_executable) | ||
938 | 979 | |||
939 | 980 | if not from_versioned: | 975 | if not from_versioned: |
940 | 981 | from_path = None | 976 | from_path = None |
941 | 982 | else: | 977 | else: |
942 | @@ -985,6 +980,13 @@ | |||
943 | 985 | to_path = None | 980 | to_path = None |
944 | 986 | else: | 981 | else: |
945 | 987 | to_path = final_paths.get_path(to_trans_id) | 982 | to_path = final_paths.get_path(to_trans_id) |
946 | 983 | |||
947 | 984 | from_name, from_parent, from_kind, from_executable = \ | ||
948 | 985 | self._from_file_data(from_trans_id, from_versioned, from_path) | ||
949 | 986 | |||
950 | 987 | to_name, to_parent, to_kind, to_executable = \ | ||
951 | 988 | self._to_file_data(to_trans_id, from_trans_id, from_executable) | ||
952 | 989 | |||
953 | 988 | if from_kind != to_kind: | 990 | if from_kind != to_kind: |
954 | 989 | modified = True | 991 | modified = True |
955 | 990 | elif to_kind in ('file', 'symlink') and ( | 992 | elif to_kind in ('file', 'symlink') and ( |
956 | @@ -1763,9 +1765,6 @@ | |||
957 | 1763 | inventory_delta.append((path, None, file_id, None)) | 1765 | inventory_delta.append((path, None, file_id, None)) |
958 | 1764 | new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in | 1766 | new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in |
959 | 1765 | new_paths) | 1767 | new_paths) |
960 | 1766 | entries = self._tree.iter_entries_by_dir( | ||
961 | 1767 | viewvalues(new_path_file_ids)) | ||
962 | 1768 | old_paths = dict((e.file_id, p) for p, e in entries) | ||
963 | 1769 | final_kinds = {} | 1768 | final_kinds = {} |
964 | 1770 | for num, (path, trans_id) in enumerate(new_paths): | 1769 | for num, (path, trans_id) in enumerate(new_paths): |
965 | 1771 | if (num % 10) == 0: | 1770 | if (num % 10) == 0: |
966 | @@ -1793,7 +1792,10 @@ | |||
967 | 1793 | new_entry = inventory.make_entry(kind, | 1792 | new_entry = inventory.make_entry(kind, |
968 | 1794 | self.final_name(trans_id), | 1793 | self.final_name(trans_id), |
969 | 1795 | parent_file_id, file_id) | 1794 | parent_file_id, file_id) |
971 | 1796 | old_path = old_paths.get(new_entry.file_id) | 1795 | try: |
972 | 1796 | old_path = self._tree.id2path(new_entry.file_id) | ||
973 | 1797 | except errors.NoSuchId: | ||
974 | 1798 | old_path = None | ||
975 | 1797 | new_executability = self._new_executability.get(trans_id) | 1799 | new_executability = self._new_executability.get(trans_id) |
976 | 1798 | if new_executability is not None: | 1800 | if new_executability is not None: |
977 | 1799 | new_entry.executable = new_executability | 1801 | new_entry.executable = new_executability |
978 | @@ -1944,10 +1946,8 @@ | |||
979 | 1944 | path = self._tree_id_paths[parent_id] | 1946 | path = self._tree_id_paths[parent_id] |
980 | 1945 | except KeyError: | 1947 | except KeyError: |
981 | 1946 | return | 1948 | return |
986 | 1947 | file_id = self.tree_file_id(parent_id) | 1949 | entry = self._tree.iter_entries_by_dir( |
987 | 1948 | if file_id is None: | 1950 | specific_files=[path]).next()[1] |
984 | 1949 | return | ||
985 | 1950 | entry = self._tree.iter_entries_by_dir([file_id]).next()[1] | ||
988 | 1951 | children = getattr(entry, 'children', {}) | 1951 | children = getattr(entry, 'children', {}) |
989 | 1952 | for child in children: | 1952 | for child in children: |
990 | 1953 | childpath = joinpath(path, child) | 1953 | childpath = joinpath(path, child) |
991 | @@ -2127,14 +2127,14 @@ | |||
992 | 2127 | if self._transform.final_file_id(trans_id) is None: | 2127 | if self._transform.final_file_id(trans_id) is None: |
993 | 2128 | yield self._final_paths._determine_path(trans_id) | 2128 | yield self._final_paths._determine_path(trans_id) |
994 | 2129 | 2129 | ||
996 | 2130 | def _make_inv_entries(self, ordered_entries, specific_file_ids=None, | 2130 | def _make_inv_entries(self, ordered_entries, specific_files=None, |
997 | 2131 | yield_parents=False): | 2131 | yield_parents=False): |
998 | 2132 | for trans_id, parent_file_id in ordered_entries: | 2132 | for trans_id, parent_file_id in ordered_entries: |
999 | 2133 | file_id = self._transform.final_file_id(trans_id) | 2133 | file_id = self._transform.final_file_id(trans_id) |
1000 | 2134 | if file_id is None: | 2134 | if file_id is None: |
1001 | 2135 | continue | 2135 | continue |
1004 | 2136 | if (specific_file_ids is not None | 2136 | if (specific_files is not None and |
1005 | 2137 | and file_id not in specific_file_ids): | 2137 | unicode(self._final_paths.get_path(trans_id)) not in specific_files): |
1006 | 2138 | continue | 2138 | continue |
1007 | 2139 | kind = self._transform.final_kind(trans_id) | 2139 | kind = self._transform.final_kind(trans_id) |
1008 | 2140 | if kind is None: | 2140 | if kind is None: |
1009 | @@ -2172,7 +2172,7 @@ | |||
1010 | 2172 | for entry, trans_id in self._make_inv_entries(todo): | 2172 | for entry, trans_id in self._make_inv_entries(todo): |
1011 | 2173 | yield entry | 2173 | yield entry |
1012 | 2174 | 2174 | ||
1014 | 2175 | def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False): | 2175 | def iter_entries_by_dir(self, specific_files=None, yield_parents=False): |
1015 | 2176 | # This may not be a maximally efficient implementation, but it is | 2176 | # This may not be a maximally efficient implementation, but it is |
1016 | 2177 | # reasonably straightforward. An implementation that grafts the | 2177 | # reasonably straightforward. An implementation that grafts the |
1017 | 2178 | # TreeTransform changes onto the tree's iter_entries_by_dir results | 2178 | # TreeTransform changes onto the tree's iter_entries_by_dir results |
1018 | @@ -2180,7 +2180,7 @@ | |||
1019 | 2180 | # position. | 2180 | # position. |
1020 | 2181 | ordered_ids = self._list_files_by_dir() | 2181 | ordered_ids = self._list_files_by_dir() |
1021 | 2182 | for entry, trans_id in self._make_inv_entries(ordered_ids, | 2182 | for entry, trans_id in self._make_inv_entries(ordered_ids, |
1023 | 2183 | specific_file_ids, yield_parents=yield_parents): | 2183 | specific_files, yield_parents=yield_parents): |
1024 | 2184 | yield unicode(self._final_paths.get_path(trans_id)), entry | 2184 | yield unicode(self._final_paths.get_path(trans_id)), entry |
1025 | 2185 | 2185 | ||
1026 | 2186 | def _iter_entries_for_dir(self, dir_path): | 2186 | def _iter_entries_for_dir(self, dir_path): |
1027 | @@ -3081,7 +3081,7 @@ | |||
1028 | 3081 | if file_id is None: | 3081 | if file_id is None: |
1029 | 3082 | file_id = tt.inactive_file_id(trans_id) | 3082 | file_id = tt.inactive_file_id(trans_id) |
1030 | 3083 | _, entry = next(path_tree.iter_entries_by_dir( | 3083 | _, entry = next(path_tree.iter_entries_by_dir( |
1032 | 3084 | [file_id])) | 3084 | specific_files=[path_tree.id2path(file_id)])) |
1033 | 3085 | # special-case the other tree root (move its | 3085 | # special-case the other tree root (move its |
1034 | 3086 | # children to current root) | 3086 | # children to current root) |
1035 | 3087 | if entry.parent_id is None: | 3087 | if entry.parent_id is None: |
1036 | 3088 | 3088 | ||
1037 | === modified file 'breezy/tree.py' | |||
1038 | --- breezy/tree.py 2018-03-24 00:39:56 +0000 | |||
1039 | +++ breezy/tree.py 2018-03-24 01:23:20 +0000 | |||
1040 | @@ -213,7 +213,7 @@ | |||
1041 | 213 | """ | 213 | """ |
1042 | 214 | raise NotImplementedError(self.id2path) | 214 | raise NotImplementedError(self.id2path) |
1043 | 215 | 215 | ||
1045 | 216 | def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False): | 216 | def iter_entries_by_dir(self, specific_files=None, yield_parents=False): |
1046 | 217 | """Walk the tree in 'by_dir' order. | 217 | """Walk the tree in 'by_dir' order. |
1047 | 218 | 218 | ||
1048 | 219 | This will yield each entry in the tree as a (path, entry) tuple. | 219 | This will yield each entry in the tree as a (path, entry) tuple. |
1049 | @@ -239,8 +239,8 @@ | |||
1050 | 239 | a, f, a/b, a/d, a/b/c, a/d/e, f/g | 239 | a, f, a/b, a/d, a/b/c, a/d/e, f/g |
1051 | 240 | 240 | ||
1052 | 241 | :param yield_parents: If True, yield the parents from the root leading | 241 | :param yield_parents: If True, yield the parents from the root leading |
1055 | 242 | down to specific_file_ids that have been requested. This has no | 242 | down to specific_files that have been requested. This has no |
1056 | 243 | impact if specific_file_ids is None. | 243 | impact if specific_files is None. |
1057 | 244 | """ | 244 | """ |
1058 | 245 | raise NotImplementedError(self.iter_entries_by_dir) | 245 | raise NotImplementedError(self.iter_entries_by_dir) |
1059 | 246 | 246 | ||
1060 | @@ -501,24 +501,23 @@ | |||
1061 | 501 | """ | 501 | """ |
1062 | 502 | return self.path2id(path) is not None | 502 | return self.path2id(path) is not None |
1063 | 503 | 503 | ||
1080 | 504 | def paths2ids(self, paths, trees=[], require_versioned=True): | 504 | def find_related_paths_across_trees(self, paths, trees=[], |
1081 | 505 | """Return all the ids that can be reached by walking from paths. | 505 | require_versioned=True): |
1082 | 506 | 506 | """Find related paths in tree corresponding to specified filenames in any | |
1083 | 507 | Each path is looked up in this tree and any extras provided in | 507 | of `lookup_trees`. |
1084 | 508 | trees, and this is repeated recursively: the children in an extra tree | 508 | |
1085 | 509 | of a directory that has been renamed under a provided path in this tree | 509 | All matches in all trees will be used, and all children of matched |
1086 | 510 | are all returned, even if none exist under a provided path in this | 510 | directories will be used. |
1087 | 511 | tree, and vice versa. | 511 | |
1088 | 512 | 512 | :param paths: The filenames to find related paths for (if None, returns | |
1089 | 513 | :param paths: An iterable of paths to start converting to ids from. | 513 | None) |
1090 | 514 | Alternatively, if paths is None, no ids should be calculated and None | 514 | :param trees: The trees to find file_ids within |
1091 | 515 | will be returned. This is offered to make calling the api unconditional | 515 | :param require_versioned: if true, all specified filenames must occur in |
1092 | 516 | for code that *might* take a list of files. | 516 | at least one tree. |
1093 | 517 | :param trees: Additional trees to consider. | 517 | :return: a set of paths for the specified filenames and their children |
1094 | 518 | :param require_versioned: If False, do not raise NotVersionedError if | 518 | in `tree` |
1079 | 519 | an element of paths is not versioned in this tree and all of trees. | ||
1095 | 520 | """ | 519 | """ |
1097 | 521 | return find_ids_across_trees(paths, [self] + list(trees), require_versioned) | 520 | raise NotImplementedError(self.find_related_paths_across_trees) |
1098 | 522 | 521 | ||
1099 | 523 | def lock_read(self): | 522 | def lock_read(self): |
1100 | 524 | """Lock this tree for multiple read only operations. | 523 | """Lock this tree for multiple read only operations. |
1101 | @@ -657,84 +656,6 @@ | |||
1102 | 657 | return searcher | 656 | return searcher |
1103 | 658 | 657 | ||
1104 | 659 | 658 | ||
1105 | 660 | def find_ids_across_trees(filenames, trees, require_versioned=True): | ||
1106 | 661 | """Find the ids corresponding to specified filenames. | ||
1107 | 662 | |||
1108 | 663 | All matches in all trees will be used, and all children of matched | ||
1109 | 664 | directories will be used. | ||
1110 | 665 | |||
1111 | 666 | :param filenames: The filenames to find file_ids for (if None, returns | ||
1112 | 667 | None) | ||
1113 | 668 | :param trees: The trees to find file_ids within | ||
1114 | 669 | :param require_versioned: if true, all specified filenames must occur in | ||
1115 | 670 | at least one tree. | ||
1116 | 671 | :return: a set of file ids for the specified filenames and their children. | ||
1117 | 672 | """ | ||
1118 | 673 | if not filenames: | ||
1119 | 674 | return None | ||
1120 | 675 | specified_path_ids = _find_ids_across_trees(filenames, trees, | ||
1121 | 676 | require_versioned) | ||
1122 | 677 | return _find_children_across_trees(specified_path_ids, trees) | ||
1123 | 678 | |||
1124 | 679 | |||
1125 | 680 | def _find_ids_across_trees(filenames, trees, require_versioned): | ||
1126 | 681 | """Find the ids corresponding to specified filenames. | ||
1127 | 682 | |||
1128 | 683 | All matches in all trees will be used, but subdirectories are not scanned. | ||
1129 | 684 | |||
1130 | 685 | :param filenames: The filenames to find file_ids for | ||
1131 | 686 | :param trees: The trees to find file_ids within | ||
1132 | 687 | :param require_versioned: if true, all specified filenames must occur in | ||
1133 | 688 | at least one tree. | ||
1134 | 689 | :return: a set of file ids for the specified filenames | ||
1135 | 690 | """ | ||
1136 | 691 | not_versioned = [] | ||
1137 | 692 | interesting_ids = set() | ||
1138 | 693 | for tree_path in filenames: | ||
1139 | 694 | not_found = True | ||
1140 | 695 | for tree in trees: | ||
1141 | 696 | file_id = tree.path2id(tree_path) | ||
1142 | 697 | if file_id is not None: | ||
1143 | 698 | interesting_ids.add(file_id) | ||
1144 | 699 | not_found = False | ||
1145 | 700 | if not_found: | ||
1146 | 701 | not_versioned.append(tree_path) | ||
1147 | 702 | if len(not_versioned) > 0 and require_versioned: | ||
1148 | 703 | raise errors.PathsNotVersionedError(not_versioned) | ||
1149 | 704 | return interesting_ids | ||
1150 | 705 | |||
1151 | 706 | |||
1152 | 707 | def _find_children_across_trees(specified_ids, trees): | ||
1153 | 708 | """Return a set including specified ids and their children. | ||
1154 | 709 | |||
1155 | 710 | All matches in all trees will be used. | ||
1156 | 711 | |||
1157 | 712 | :param trees: The trees to find file_ids within | ||
1158 | 713 | :return: a set containing all specified ids and their children | ||
1159 | 714 | """ | ||
1160 | 715 | interesting_ids = set(specified_ids) | ||
1161 | 716 | pending = interesting_ids | ||
1162 | 717 | # now handle children of interesting ids | ||
1163 | 718 | # we loop so that we handle all children of each id in both trees | ||
1164 | 719 | while len(pending) > 0: | ||
1165 | 720 | new_pending = set() | ||
1166 | 721 | for tree in trees: | ||
1167 | 722 | for file_id in pending: | ||
1168 | 723 | try: | ||
1169 | 724 | path = tree.id2path(file_id) | ||
1170 | 725 | except errors.NoSuchId: | ||
1171 | 726 | continue | ||
1172 | 727 | try: | ||
1173 | 728 | for child in tree.iter_child_entries(path, file_id): | ||
1174 | 729 | if child.file_id not in interesting_ids: | ||
1175 | 730 | new_pending.add(child.file_id) | ||
1176 | 731 | except errors.NotADirectory: | ||
1177 | 732 | pass | ||
1178 | 733 | interesting_ids.update(new_pending) | ||
1179 | 734 | pending = new_pending | ||
1180 | 735 | return interesting_ids | ||
1181 | 736 | |||
1182 | 737 | |||
1183 | 738 | class InterTree(InterObject): | 659 | class InterTree(InterObject): |
1184 | 739 | """This class represents operations taking place between two Trees. | 660 | """This class represents operations taking place between two Trees. |
1185 | 740 | 661 | ||
1186 | @@ -854,18 +775,6 @@ | |||
1187 | 854 | if extra_trees is not None: | 775 | if extra_trees is not None: |
1188 | 855 | trees = trees + tuple(extra_trees) | 776 | trees = trees + tuple(extra_trees) |
1189 | 856 | with self.lock_read(): | 777 | with self.lock_read(): |
1190 | 857 | # target is usually the newer tree: | ||
1191 | 858 | specific_file_ids = self.target.paths2ids(specific_files, trees, | ||
1192 | 859 | require_versioned=require_versioned) | ||
1193 | 860 | if specific_files and not specific_file_ids: | ||
1194 | 861 | # All files are unversioned, so just return an empty delta | ||
1195 | 862 | # _compare_trees would think we want a complete delta | ||
1196 | 863 | result = delta.TreeDelta() | ||
1197 | 864 | fake_entry = inventory.InventoryFile('unused', 'unused', 'unused') | ||
1198 | 865 | result.unversioned = [(path, None, | ||
1199 | 866 | self.target._comparison_data(fake_entry, path)[0]) for path in | ||
1200 | 867 | specific_files] | ||
1201 | 868 | return result | ||
1202 | 869 | return delta._compare_trees(self.source, self.target, want_unchanged, | 778 | return delta._compare_trees(self.source, self.target, want_unchanged, |
1203 | 870 | specific_files, include_root, extra_trees=extra_trees, | 779 | specific_files, include_root, extra_trees=extra_trees, |
1204 | 871 | require_versioned=require_versioned, | 780 | require_versioned=require_versioned, |
1205 | @@ -907,17 +816,23 @@ | |||
1206 | 907 | output. An unversioned file is defined as one with (False, False) | 816 | output. An unversioned file is defined as one with (False, False) |
1207 | 908 | for the versioned pair. | 817 | for the versioned pair. |
1208 | 909 | """ | 818 | """ |
1212 | 910 | lookup_trees = [self.source] | 819 | if not extra_trees: |
1213 | 911 | if extra_trees: | 820 | extra_trees = [] |
1214 | 912 | lookup_trees.extend(extra_trees) | 821 | else: |
1215 | 822 | extra_trees = list(extra_trees) | ||
1216 | 913 | # The ids of items we need to examine to insure delta consistency. | 823 | # The ids of items we need to examine to insure delta consistency. |
1217 | 914 | precise_file_ids = set() | 824 | precise_file_ids = set() |
1218 | 915 | changed_file_ids = [] | 825 | changed_file_ids = [] |
1219 | 916 | if specific_files == []: | 826 | if specific_files == []: |
1221 | 917 | specific_file_ids = [] | 827 | target_specific_files = [] |
1222 | 828 | source_specific_files = [] | ||
1223 | 918 | else: | 829 | else: |
1226 | 919 | specific_file_ids = self.target.paths2ids(specific_files, | 830 | target_specific_files = self.target.find_related_paths_across_trees( |
1227 | 920 | lookup_trees, require_versioned=require_versioned) | 831 | specific_files, [self.source] + extra_trees, |
1228 | 832 | require_versioned=require_versioned) | ||
1229 | 833 | source_specific_files = self.source.find_related_paths_across_trees( | ||
1230 | 834 | specific_files, [self.target] + extra_trees, | ||
1231 | 835 | require_versioned=require_versioned) | ||
1232 | 921 | if specific_files is not None: | 836 | if specific_files is not None: |
1233 | 922 | # reparented or added entries must have their parents included | 837 | # reparented or added entries must have their parents included |
1234 | 923 | # so that valid deltas can be created. The seen_parents set | 838 | # so that valid deltas can be created. The seen_parents set |
1235 | @@ -937,10 +852,10 @@ | |||
1236 | 937 | all_unversioned = collections.deque() | 852 | all_unversioned = collections.deque() |
1237 | 938 | to_paths = {} | 853 | to_paths = {} |
1238 | 939 | from_entries_by_dir = list(self.source.iter_entries_by_dir( | 854 | from_entries_by_dir = list(self.source.iter_entries_by_dir( |
1240 | 940 | specific_file_ids=specific_file_ids)) | 855 | specific_files=source_specific_files)) |
1241 | 941 | from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir) | 856 | from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir) |
1242 | 942 | to_entries_by_dir = list(self.target.iter_entries_by_dir( | 857 | to_entries_by_dir = list(self.target.iter_entries_by_dir( |
1244 | 943 | specific_file_ids=specific_file_ids)) | 858 | specific_files=target_specific_files)) |
1245 | 944 | num_entries = len(from_entries_by_dir) + len(to_entries_by_dir) | 859 | num_entries = len(from_entries_by_dir) + len(to_entries_by_dir) |
1246 | 945 | entry_count = 0 | 860 | entry_count = 0 |
1247 | 946 | # the unversioned path lookup only occurs on real trees - where there | 861 | # the unversioned path lookup only occurs on real trees - where there |
1248 | @@ -969,7 +884,7 @@ | |||
1249 | 969 | if pb is not None: | 884 | if pb is not None: |
1250 | 970 | pb.update('comparing files', entry_count, num_entries) | 885 | pb.update('comparing files', entry_count, num_entries) |
1251 | 971 | if changes or include_unchanged: | 886 | if changes or include_unchanged: |
1253 | 972 | if specific_file_ids is not None: | 887 | if specific_files is not None: |
1254 | 973 | new_parent_id = result[4][1] | 888 | new_parent_id = result[4][1] |
1255 | 974 | precise_file_ids.add(new_parent_id) | 889 | precise_file_ids.add(new_parent_id) |
1256 | 975 | changed_file_ids.append(result[0]) | 890 | changed_file_ids.append(result[0]) |
1257 | @@ -1017,12 +932,12 @@ | |||
1258 | 1017 | yield(file_id, (path, to_path), changed_content, versioned, parent, | 932 | yield(file_id, (path, to_path), changed_content, versioned, parent, |
1259 | 1018 | name, kind, executable) | 933 | name, kind, executable) |
1260 | 1019 | changed_file_ids = set(changed_file_ids) | 934 | changed_file_ids = set(changed_file_ids) |
1262 | 1020 | if specific_file_ids is not None: | 935 | if specific_files is not None: |
1263 | 1021 | for result in self._handle_precise_ids(precise_file_ids, | 936 | for result in self._handle_precise_ids(precise_file_ids, |
1264 | 1022 | changed_file_ids): | 937 | changed_file_ids): |
1265 | 1023 | yield result | 938 | yield result |
1266 | 1024 | 939 | ||
1268 | 1025 | def _get_entry(self, tree, file_id): | 940 | def _get_entry(self, tree, path): |
1269 | 1026 | """Get an inventory entry from a tree, with missing entries as None. | 941 | """Get an inventory entry from a tree, with missing entries as None. |
1270 | 1027 | 942 | ||
1271 | 1028 | If the tree raises NotImplementedError on accessing .inventory, then | 943 | If the tree raises NotImplementedError on accessing .inventory, then |
1272 | @@ -1032,20 +947,12 @@ | |||
1273 | 1032 | :param tree: The tree to lookup the entry in. | 947 | :param tree: The tree to lookup the entry in. |
1274 | 1033 | :param file_id: The file_id to lookup. | 948 | :param file_id: The file_id to lookup. |
1275 | 1034 | """ | 949 | """ |
1276 | 950 | # No inventory available. | ||
1277 | 1035 | try: | 951 | try: |
1291 | 1036 | inventory = tree.root_inventory | 952 | iterator = tree.iter_entries_by_dir(specific_files=[path]) |
1292 | 1037 | except (AttributeError, NotImplementedError): | 953 | return iterator.next()[1] |
1293 | 1038 | # No inventory available. | 954 | except StopIteration: |
1294 | 1039 | try: | 955 | return None |
1282 | 1040 | iterator = tree.iter_entries_by_dir(specific_file_ids=[file_id]) | ||
1283 | 1041 | return iterator.next()[1] | ||
1284 | 1042 | except StopIteration: | ||
1285 | 1043 | return None | ||
1286 | 1044 | else: | ||
1287 | 1045 | try: | ||
1288 | 1046 | return inventory[file_id] | ||
1289 | 1047 | except errors.NoSuchId: | ||
1290 | 1048 | return None | ||
1295 | 1049 | 956 | ||
1296 | 1050 | def _handle_precise_ids(self, precise_file_ids, changed_file_ids, | 957 | def _handle_precise_ids(self, precise_file_ids, changed_file_ids, |
1297 | 1051 | discarded_changes=None): | 958 | discarded_changes=None): |
1298 | @@ -1093,22 +1000,26 @@ | |||
1299 | 1093 | # Examine file_id | 1000 | # Examine file_id |
1300 | 1094 | if discarded_changes: | 1001 | if discarded_changes: |
1301 | 1095 | result = discarded_changes.get(file_id) | 1002 | result = discarded_changes.get(file_id) |
1303 | 1096 | old_entry = None | 1003 | source_entry = None |
1304 | 1097 | else: | 1004 | else: |
1305 | 1098 | result = None | 1005 | result = None |
1306 | 1099 | if result is None: | 1006 | if result is None: |
1307 | 1100 | old_entry = self._get_entry(self.source, file_id) | ||
1308 | 1101 | new_entry = self._get_entry(self.target, file_id) | ||
1309 | 1102 | try: | 1007 | try: |
1310 | 1103 | source_path = self.source.id2path(file_id) | 1008 | source_path = self.source.id2path(file_id) |
1311 | 1104 | except errors.NoSuchId: | 1009 | except errors.NoSuchId: |
1312 | 1105 | source_path = None | 1010 | source_path = None |
1313 | 1011 | source_entry = None | ||
1314 | 1012 | else: | ||
1315 | 1013 | source_entry = self._get_entry(self.source, source_path) | ||
1316 | 1106 | try: | 1014 | try: |
1317 | 1107 | target_path = self.target.id2path(file_id) | 1015 | target_path = self.target.id2path(file_id) |
1318 | 1108 | except errors.NoSuchId: | 1016 | except errors.NoSuchId: |
1319 | 1109 | target_path = None | 1017 | target_path = None |
1320 | 1018 | target_entry = None | ||
1321 | 1019 | else: | ||
1322 | 1020 | target_entry = self._get_entry(self.target, target_path) | ||
1323 | 1110 | result, changes = self._changes_from_entries( | 1021 | result, changes = self._changes_from_entries( |
1325 | 1111 | old_entry, new_entry, source_path, target_path) | 1022 | source_entry, target_entry, source_path, target_path) |
1326 | 1112 | else: | 1023 | else: |
1327 | 1113 | changes = True | 1024 | changes = True |
1328 | 1114 | # Get this parents parent to examine. | 1025 | # Get this parents parent to examine. |
1329 | @@ -1119,9 +1030,9 @@ | |||
1330 | 1119 | result[6][1] != 'directory'): | 1030 | result[6][1] != 'directory'): |
1331 | 1120 | # This stopped being a directory, the old children have | 1031 | # This stopped being a directory, the old children have |
1332 | 1121 | # to be included. | 1032 | # to be included. |
1334 | 1122 | if old_entry is None: | 1033 | if source_entry is None: |
1335 | 1123 | # Reusing a discarded change. | 1034 | # Reusing a discarded change. |
1337 | 1124 | old_entry = self._get_entry(self.source, file_id) | 1035 | source_entry = self._get_entry(self.source, result[1][0]) |
1338 | 1125 | precise_file_ids.update( | 1036 | precise_file_ids.update( |
1339 | 1126 | child.file_id | 1037 | child.file_id |
1340 | 1127 | for child in self.source.iter_child_entries(result[1][0])) | 1038 | for child in self.source.iter_child_entries(result[1][0])) |
Thanks, all looks sensible.