Merge lp:~jelmer/brz/commit-builder-fixes into lp:~jelmer/brz/foreign

Proposed by Jelmer Vernooij
Status: Superseded
Proposed branch: lp:~jelmer/brz/commit-builder-fixes
Merge into: lp:~jelmer/brz/foreign
Diff against target: 5948 lines (+1655/-931) (has conflicts)
63 files modified
Makefile (+6/-0)
breezy/branch.py (+8/-28)
breezy/branchbuilder.py (+4/-4)
breezy/builtins.py (+13/-14)
breezy/bzr/branch.py (+31/-0)
breezy/bzr/inventory.py (+2/-2)
breezy/bzr/inventorytree.py (+179/-47)
breezy/bzr/remote.py (+1/-0)
breezy/bzr/workingtree.py (+5/-8)
breezy/bzr/workingtree_4.py (+1/-1)
breezy/config.py (+1/-1)
breezy/filter_tree.py (+3/-3)
breezy/filters/__init__.py (+4/-19)
breezy/gpg.py (+6/-3)
breezy/log.py (+1/-1)
breezy/memorytree.py (+6/-1)
breezy/merge.py (+168/-171)
breezy/plugins/changelog_merge/changelog_merge.py (+23/-0)
breezy/plugins/changelog_merge/tests/test_changelog_merge.py (+3/-2)
breezy/plugins/launchpad/lp_registration.py (+2/-3)
breezy/plugins/po_merge/po_merge.py (+1/-1)
breezy/plugins/stats/cmds.py (+3/-2)
breezy/plugins/stats/test_stats.py (+1/-0)
breezy/rename_map.py (+9/-1)
breezy/tests/__init__.py (+1/-1)
breezy/tests/blackbox/test_config.py (+4/-4)
breezy/tests/matchers.py (+74/-0)
breezy/tests/per_branch/test_branch.py (+5/-0)
breezy/tests/per_branch/test_commit.py (+15/-6)
breezy/tests/per_intertree/test_compare.py (+3/-1)
breezy/tests/per_intertree/test_file_content_matches.py (+14/-1)
breezy/tests/per_repository/test_commit_builder.py (+136/-120)
breezy/tests/per_repository_vf/test_fileid_involved.py (+1/-2)
breezy/tests/per_tree/__init__.py (+0/-50)
breezy/tests/per_tree/test_inv.py (+10/-4)
breezy/tests/per_tree/test_test_trees.py (+157/-51)
breezy/tests/per_tree/test_tree.py (+9/-1)
breezy/tests/per_tree/test_walkdirs.py (+1/-1)
breezy/tests/per_workingtree/test_check_state.py (+5/-2)
breezy/tests/per_workingtree/test_inv.py (+1/-1)
breezy/tests/per_workingtree/test_merge_from_branch.py (+1/-1)
breezy/tests/per_workingtree/test_move.py (+230/-0)
breezy/tests/per_workingtree/test_nested_specifics.py (+1/-1)
breezy/tests/per_workingtree/test_paths2ids.py (+37/-0)
breezy/tests/per_workingtree/test_pull.py (+1/-1)
breezy/tests/per_workingtree/test_rename_one.py (+117/-0)
breezy/tests/per_workingtree/test_revision_tree.py (+3/-3)
breezy/tests/per_workingtree/test_workingtree.py (+8/-8)
breezy/tests/test_bundle.py (+9/-9)
breezy/tests/test_bzrdir.py (+1/-1)
breezy/tests/test_matchers.py (+28/-0)
breezy/tests/test_merge.py (+28/-10)
breezy/tests/test_merge_core.py (+5/-5)
breezy/tests/test_revert.py (+2/-2)
breezy/tests/test_shelf.py (+2/-2)
breezy/tests/test_transform.py (+49/-48)
breezy/tests/test_workingtree.py (+2/-1)
breezy/transform.py (+91/-101)
breezy/transport/http/_urllib2_wrappers.py (+3/-1)
breezy/transport/sftp.py (+2/-2)
breezy/tree.py (+93/-177)
breezy/workingtree.py (+18/-1)
doc/en/release-notes/brz-3.0.txt (+7/-0)
Text conflict in breezy/gpg.py
Text conflict in breezy/merge.py
Text conflict in breezy/plugins/changelog_merge/changelog_merge.py
Text conflict in breezy/tests/matchers.py
Text conflict in breezy/tests/per_intertree/test_file_content_matches.py
Text conflict in breezy/tests/per_repository/test_commit_builder.py
Text conflict in breezy/tests/per_workingtree/test_move.py
Text conflict in breezy/tests/per_workingtree/test_rename_one.py
Text conflict in breezy/tests/test_matchers.py
Text conflict in breezy/transform.py
Text conflict in breezy/tree.py
Text conflict in breezy/workingtree.py
To merge this branch: bzr merge lp:~jelmer/brz/commit-builder-fixes
Reviewer Review Type Date Requested Status
Jelmer Vernooij Pending
Review via email: mp+342046@code.launchpad.net

This proposal has been superseded by a proposal from 2018-03-24.

Description of the change

Some fixes for the commit builder tests.

* Add some entropy to commit messages.
* Skip tests that rely on empty versioned directories

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2017-11-21 01:01:11 +0000
3+++ Makefile 2018-03-24 17:11:56 +0000
4@@ -90,6 +90,12 @@
5 # Check that there were no errors reported.
6 subunit-stats < selftest.log
7
8+check-ci: docs extensions
9+ # FIXME: Remove -Wignore::FutureWarning once
10+ # https://github.com/paramiko/paramiko/issues/713 is not a concern
11+ # anymore -- vila 2017-05-24
12+ python -Werror -Wignore::FutureWarning -Wignore::ImportWarning -O ./brz selftest -v --parallel=fork -Oselftest.timeout=120 --subunit2
13+
14 # Run Python style checker (apt-get install pyflakes)
15 #
16 # Note that at present this gives many false warnings, because it doesn't
17
18=== modified file 'breezy/branch.py'
19--- breezy/branch.py 2018-03-04 02:57:55 +0000
20+++ breezy/branch.py 2018-03-24 17:11:56 +0000
21@@ -26,6 +26,7 @@
22 config as _mod_config,
23 debug,
24 fetch,
25+ memorytree,
26 repository,
27 revision as _mod_revision,
28 tag as _mod_tag,
29@@ -96,7 +97,6 @@
30 self._revision_id_to_revno_cache = None
31 self._partial_revision_id_to_revno_cache = {}
32 self._partial_revision_history_cache = []
33- self._tags_bytes = None
34 self._last_revision_info_cache = None
35 self._master_branch_cache = None
36 self._merge_sorted_revisions_cache = None
37@@ -258,23 +258,6 @@
38 a_branch = Branch.open(url, possible_transports=possible_transports)
39 return a_branch.repository
40
41- def _get_tags_bytes(self):
42- """Get the bytes of a serialised tags dict.
43-
44- Note that not all branches support tags, nor do all use the same tags
45- logic: this method is specific to BasicTags. Other tag implementations
46- may use the same method name and behave differently, safely, because
47- of the double-dispatch via
48- format.make_tags->tags_instance->get_tags_dict.
49-
50- :return: The bytes of the tags file.
51- :seealso: Branch._set_tags_bytes.
52- """
53- with self.lock_read():
54- if self._tags_bytes is None:
55- self._tags_bytes = self._transport.get_bytes('tags')
56- return self._tags_bytes
57-
58 def _get_nick(self, local=False, possible_transports=None):
59 config = self.get_config()
60 # explicit overrides master, but don't look for master if local is True
61@@ -908,15 +891,6 @@
62 if_present_ids=tags_to_fetch, find_ghosts=True).execute()
63 self.repository.fetch(old_repository, fetch_spec=fetch_spec)
64
65- def _set_tags_bytes(self, bytes):
66- """Mirror method for _get_tags_bytes.
67-
68- :seealso: Branch._get_tags_bytes.
69- """
70- with self.lock_write():
71- self._tags_bytes = bytes
72- return self._transport.put_bytes('tags', bytes)
73-
74 def _cache_revision_history(self, rev_history):
75 """Set the cached revision history to rev_history.
76
77@@ -952,7 +926,6 @@
78 self._merge_sorted_revisions_cache = None
79 self._partial_revision_history_cache = []
80 self._partial_revision_id_to_revno_cache = {}
81- self._tags_bytes = None
82
83 def _gen_revision_history(self):
84 """Return sequence of revision hashes on to this branch.
85@@ -1513,6 +1486,13 @@
86 if_present_fetch.discard(_mod_revision.NULL_REVISION)
87 return must_fetch, if_present_fetch
88
89+ def create_memorytree(self):
90+ """Create a memory tree for this branch.
91+
92+ :return: An in-memory MutableTree instance
93+ """
94+ return memorytree.MemoryTree.create_on_branch(self)
95+
96
97 class BranchFormat(controldir.ControlComponentFormat):
98 """An encapsulation of the initialization and open routines for a format.
99
100=== modified file 'breezy/branchbuilder.py'
101--- breezy/branchbuilder.py 2017-11-19 18:35:20 +0000
102+++ breezy/branchbuilder.py 2018-03-24 17:11:56 +0000
103@@ -112,7 +112,7 @@
104 if base_id != self._branch.last_revision():
105 self._move_branch_pointer(base_id,
106 allow_leftmost_as_ghost=allow_leftmost_as_ghost)
107- tree = memorytree.MemoryTree.create_on_branch(self._branch)
108+ tree = self._branch.create_memorytree()
109 tree.lock_write()
110 try:
111 if parent_ids is not None:
112@@ -157,7 +157,7 @@
113 # We are cheating a little bit here, and locking the new tree
114 # before the old tree is unlocked. But that way the branch stays
115 # locked throughout.
116- new_tree = memorytree.MemoryTree.create_on_branch(self._branch)
117+ new_tree = self._branch.create_memorytree()
118 new_tree.lock_write()
119 self._tree.unlock()
120 self._tree = new_tree
121@@ -172,7 +172,7 @@
122 if self._tree is not None:
123 raise AssertionError('You cannot start a new series while a'
124 ' series is already going.')
125- self._tree = memorytree.MemoryTree.create_on_branch(self._branch)
126+ self._tree = self._branch.create_memorytree()
127 self._tree.lock_write()
128
129 def finish_series(self):
130@@ -223,7 +223,7 @@
131 if self._tree is not None:
132 tree = self._tree
133 else:
134- tree = memorytree.MemoryTree.create_on_branch(self._branch)
135+ tree = self._branch.create_memorytree()
136 tree.lock_write()
137 try:
138 if parent_ids is not None:
139
140=== modified file 'breezy/builtins.py'
141--- breezy/builtins.py 2018-03-12 05:18:13 +0000
142+++ breezy/builtins.py 2018-03-24 17:11:56 +0000
143@@ -53,6 +53,7 @@
144 symbol_versioning,
145 timestamp,
146 transport,
147+ tree as _mod_tree,
148 ui,
149 urlutils,
150 views,
151@@ -960,11 +961,11 @@
152
153 self.add_cleanup(tree.lock_read().unlock)
154 if file_list is not None:
155- file_ids = tree.paths2ids(file_list, trees=extra_trees,
156- require_versioned=True)
157+ paths = tree.find_related_paths_across_trees(
158+ file_list, extra_trees, require_versioned=True)
159 # find_ids_across_trees may include some paths that don't
160 # exist in 'tree'.
161- entries = tree.iter_entries_by_dir(specific_file_ids=file_ids)
162+ entries = tree.iter_entries_by_dir(specific_files=paths)
163 else:
164 entries = tree.iter_entries_by_dir()
165
166@@ -4776,29 +4777,27 @@
167 " merges. Not cherrypicking or"
168 " multi-merges."))
169 repository = tree.branch.repository
170- interesting_ids = None
171+ interesting_files = None
172 new_conflicts = []
173 conflicts = tree.conflicts()
174 if file_list is not None:
175- interesting_ids = set()
176+ interesting_files = set()
177 for filename in file_list:
178- file_id = tree.path2id(filename)
179- if file_id is None:
180+ if not tree.is_versioned(filename):
181 raise errors.NotVersionedError(filename)
182- interesting_ids.add(file_id)
183- if tree.kind(filename, file_id) != "directory":
184+ interesting_files.add(filename)
185+ if tree.kind(filename) != "directory":
186 continue
187
188- # FIXME: Support nested trees
189- for name, ie in tree.root_inventory.iter_entries(file_id):
190- interesting_ids.add(ie.file_id)
191+ for path, ie in tree.iter_entries_by_dir(specific_files=[filename]):
192+ interesting_files.add(path)
193 new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
194 else:
195 # Remerge only supports resolving contents conflicts
196 allowed_conflicts = ('text conflict', 'contents conflict')
197 restore_files = [c.path for c in conflicts
198 if c.typestring in allowed_conflicts]
199- _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
200+ _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_files)
201 tree.set_conflicts(ConflictList(new_conflicts))
202 if file_list is not None:
203 restore_files = file_list
204@@ -4815,7 +4814,7 @@
205 tree.set_parent_ids(parents[:1])
206 try:
207 merger = _mod_merge.Merger.from_revision_ids(tree, parents[1])
208- merger.interesting_ids = interesting_ids
209+ merger.interesting_files = interesting_files
210 merger.merge_type = merge_type
211 merger.show_base = show_base
212 merger.reprocess = reprocess
213
214=== modified file 'breezy/bzr/branch.py'
215--- breezy/bzr/branch.py 2017-11-12 18:17:03 +0000
216+++ breezy/bzr/branch.py 2018-03-24 17:11:56 +0000
217@@ -97,6 +97,7 @@
218 self.repository = _repository
219 self.conf_store = None
220 Branch.__init__(self, possible_transports)
221+ self._tags_bytes = None
222
223 def __str__(self):
224 return '%s(%s)' % (self.__class__.__name__, self.user_url)
225@@ -402,6 +403,36 @@
226 self._format._update_feature_flags(updated_flags)
227 self.control_transport.put_bytes('format', self._format.as_string())
228
229+ def _get_tags_bytes(self):
230+ """Get the bytes of a serialised tags dict.
231+
232+ Note that not all branches support tags, nor do all use the same tags
233+ logic: this method is specific to BasicTags. Other tag implementations
234+ may use the same method name and behave differently, safely, because
235+ of the double-dispatch via
236+ format.make_tags->tags_instance->get_tags_dict.
237+
238+ :return: The bytes of the tags file.
239+ :seealso: Branch._set_tags_bytes.
240+ """
241+ with self.lock_read():
242+ if self._tags_bytes is None:
243+ self._tags_bytes = self._transport.get_bytes('tags')
244+ return self._tags_bytes
245+
246+ def _set_tags_bytes(self, bytes):
247+ """Mirror method for _get_tags_bytes.
248+
249+ :seealso: Branch._get_tags_bytes.
250+ """
251+ with self.lock_write():
252+ self._tags_bytes = bytes
253+ return self._transport.put_bytes('tags', bytes)
254+
255+ def _clear_cached_state(self):
256+ super(BzrBranch, self)._clear_cached_state()
257+ self._tags_bytes = None
258+
259
260 class BzrBranch8(BzrBranch):
261 """A branch that stores tree-reference locations."""
262
263=== modified file 'breezy/bzr/inventory.py'
264--- breezy/bzr/inventory.py 2018-03-10 15:17:30 +0000
265+++ breezy/bzr/inventory.py 2018-03-24 17:11:56 +0000
266@@ -720,12 +720,12 @@
267
268 def _preload_cache(self):
269 """Populate any caches, we are about to access all items.
270-
271+
272 The default implementation does nothing, because CommonInventory doesn't
273 have a cache.
274 """
275 pass
276-
277+
278 def iter_entries_by_dir(self, from_dir=None, specific_file_ids=None,
279 yield_parents=False):
280 """Iterate over the entries in a directory first order.
281
282=== modified file 'breezy/bzr/inventorytree.py'
283--- breezy/bzr/inventorytree.py 2018-03-12 05:18:13 +0000
284+++ breezy/bzr/inventorytree.py 2018-03-24 17:11:56 +0000
285@@ -77,7 +77,8 @@
286 adjusted to account for existing elements that match case
287 insensitively.
288 """
289- return list(self._yield_canonical_inventory_paths(paths))
290+ with self.lock_read():
291+ return list(self._yield_canonical_inventory_paths(paths))
292
293 def get_canonical_inventory_path(self, path):
294 """Returns the first inventory item that case-insensitively matches path.
295@@ -97,7 +98,8 @@
296 :return: The input path adjusted to account for existing elements
297 that match case insensitively.
298 """
299- return next(self._yield_canonical_inventory_paths([path]))
300+ with self.lock_read():
301+ return next(self._yield_canonical_inventory_paths([path]))
302
303 def _yield_canonical_inventory_paths(self, paths):
304 for path in paths:
305@@ -112,31 +114,34 @@
306 for elt in bit_iter:
307 lelt = elt.lower()
308 new_path = None
309- for child in self.iter_children(cur_id):
310- try:
311- # XXX: it seem like if the child is known to be in the
312- # tree, we shouldn't need to go from its id back to
313- # its path -- mbp 2010-02-11
314- #
315- # XXX: it seems like we could be more efficient
316- # by just directly looking up the original name and
317- # only then searching all children; also by not
318- # chopping paths so much. -- mbp 2010-02-11
319- child_base = os.path.basename(self.id2path(child))
320- if (child_base == elt):
321- # if we found an exact match, we can stop now; if
322- # we found an approximate match we need to keep
323- # searching because there might be an exact match
324- # later.
325- cur_id = child
326- new_path = osutils.pathjoin(cur_path, child_base)
327- break
328- elif child_base.lower() == lelt:
329- cur_id = child
330- new_path = osutils.pathjoin(cur_path, child_base)
331- except errors.NoSuchId:
332- # before a change is committed we can see this error...
333- continue
334+ try:
335+ for child in self.iter_child_entries(self.id2path(cur_id), cur_id):
336+ try:
337+ # XXX: it seem like if the child is known to be in the
338+ # tree, we shouldn't need to go from its id back to
339+ # its path -- mbp 2010-02-11
340+ #
341+ # XXX: it seems like we could be more efficient
342+ # by just directly looking up the original name and
343+ # only then searching all children; also by not
344+ # chopping paths so much. -- mbp 2010-02-11
345+ child_base = os.path.basename(self.id2path(child.file_id))
346+ if (child_base == elt):
347+ # if we found an exact match, we can stop now; if
348+ # we found an approximate match we need to keep
349+ # searching because there might be an exact match
350+ # later.
351+ cur_id = child.file_id
352+ new_path = osutils.pathjoin(cur_path, child_base)
353+ break
354+ elif child_base.lower() == lelt:
355+ cur_id = child.file_id
356+ new_path = osutils.pathjoin(cur_path, child_base)
357+ except errors.NoSuchId:
358+ # before a change is committed we can see this error...
359+ continue
360+ except errors.NotADirectory:
361+ pass
362 if new_path:
363 cur_path = new_path
364 else:
365@@ -165,6 +170,53 @@
366 file_id = file_id[0]
367 return self.root_inventory, file_id
368
369+ def find_related_paths_across_trees(self, paths, trees=[],
370+ require_versioned=True):
371+ """Find related paths in tree corresponding to specified filenames in any
372+ of `lookup_trees`.
373+
374+ All matches in all trees will be used, and all children of matched
375+ directories will be used.
376+
377+ :param paths: The filenames to find related paths for (if None, returns
378+ None)
379+ :param trees: The trees to find file_ids within
380+ :param require_versioned: if true, all specified filenames must occur in
381+ at least one tree.
382+ :return: a set of paths for the specified filenames and their children
383+ in `tree`
384+ """
385+ if paths is None:
386+ return None;
387+ file_ids = self.paths2ids(
388+ paths, trees, require_versioned=require_versioned)
389+ ret = set()
390+ for file_id in file_ids:
391+ try:
392+ ret.add(self.id2path(file_id))
393+ except errors.NoSuchId:
394+ pass
395+ return ret
396+
397+ def paths2ids(self, paths, trees=[], require_versioned=True):
398+ """Return all the ids that can be reached by walking from paths.
399+
400+ Each path is looked up in this tree and any extras provided in
401+ trees, and this is repeated recursively: the children in an extra tree
402+ of a directory that has been renamed under a provided path in this tree
403+ are all returned, even if none exist under a provided path in this
404+ tree, and vice versa.
405+
406+ :param paths: An iterable of paths to start converting to ids from.
407+ Alternatively, if paths is None, no ids should be calculated and None
408+ will be returned. This is offered to make calling the api unconditional
409+ for code that *might* take a list of files.
410+ :param trees: Additional trees to consider.
411+ :param require_versioned: If False, do not raise NotVersionedError if
412+ an element of paths is not versioned in this tree and all of trees.
413+ """
414+ return find_ids_across_trees(paths, [self] + list(trees), require_versioned)
415+
416 def path2id(self, path):
417 """Return the id for path in this tree."""
418 with self.lock_read():
419@@ -217,7 +269,7 @@
420 # are not versioned.
421 return set((p for p in paths if self.path2id(p) is None))
422
423- def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
424+ def iter_entries_by_dir(self, specific_files=None, yield_parents=False):
425 """Walk the tree in 'by_dir' order.
426
427 This will yield each entry in the tree as a (path, entry) tuple.
428@@ -226,20 +278,20 @@
429 See Tree.iter_entries_by_dir for details.
430
431 :param yield_parents: If True, yield the parents from the root leading
432- down to specific_file_ids that have been requested. This has no
433- impact if specific_file_ids is None.
434+ down to specific_files that have been requested. This has no
435+ impact if specific_files is None.
436 """
437 with self.lock_read():
438- if specific_file_ids is None:
439- inventory_file_ids = None
440- else:
441+ if specific_files is not None:
442 inventory_file_ids = []
443- for tree_file_id in specific_file_ids:
444- inventory, inv_file_id = self._unpack_file_id(tree_file_id)
445+ for path in specific_files:
446+ inventory, inv_file_id = self._path2inv_file_id(path)
447 if not inventory is self.root_inventory: # for now
448 raise AssertionError("%r != %r" % (
449 inventory, self.root_inventory))
450 inventory_file_ids.append(inv_file_id)
451+ else:
452+ inventory_file_ids = None
453 # FIXME: Handle nested trees
454 return self.root_inventory.iter_entries_by_dir(
455 specific_file_ids=inventory_file_ids, yield_parents=yield_parents)
456@@ -248,15 +300,13 @@
457 with self.lock_read():
458 inv, inv_file_id = self._path2inv_file_id(path, file_id)
459 try:
460- return iter(viewvalues(inv[inv_file_id].children))
461+ ie = inv[inv_file_id]
462 except errors.NoSuchId:
463 raise errors.NoSuchFile(path)
464-
465- def iter_children(self, file_id, path=None):
466- """See Tree.iter_children."""
467- entry = self.iter_entries_by_dir([file_id]).next()[1]
468- for child in viewvalues(getattr(entry, 'children', {})):
469- yield child.file_id
470+ else:
471+ if ie.kind != 'directory':
472+ raise errors.NotADirectory(path)
473+ return iter(viewvalues(ie.children))
474
475 def _get_plan_merge_data(self, file_id, other, base):
476 from . import versionedfile
477@@ -316,6 +366,84 @@
478 return last_revision
479
480
481+def find_ids_across_trees(filenames, trees, require_versioned=True):
482+ """Find the ids corresponding to specified filenames.
483+
484+ All matches in all trees will be used, and all children of matched
485+ directories will be used.
486+
487+ :param filenames: The filenames to find file_ids for (if None, returns
488+ None)
489+ :param trees: The trees to find file_ids within
490+ :param require_versioned: if true, all specified filenames must occur in
491+ at least one tree.
492+ :return: a set of file ids for the specified filenames and their children.
493+ """
494+ if not filenames:
495+ return None
496+ specified_path_ids = _find_ids_across_trees(filenames, trees,
497+ require_versioned)
498+ return _find_children_across_trees(specified_path_ids, trees)
499+
500+
501+def _find_ids_across_trees(filenames, trees, require_versioned):
502+ """Find the ids corresponding to specified filenames.
503+
504+ All matches in all trees will be used, but subdirectories are not scanned.
505+
506+ :param filenames: The filenames to find file_ids for
507+ :param trees: The trees to find file_ids within
508+ :param require_versioned: if true, all specified filenames must occur in
509+ at least one tree.
510+ :return: a set of file ids for the specified filenames
511+ """
512+ not_versioned = []
513+ interesting_ids = set()
514+ for tree_path in filenames:
515+ not_found = True
516+ for tree in trees:
517+ file_id = tree.path2id(tree_path)
518+ if file_id is not None:
519+ interesting_ids.add(file_id)
520+ not_found = False
521+ if not_found:
522+ not_versioned.append(tree_path)
523+ if len(not_versioned) > 0 and require_versioned:
524+ raise errors.PathsNotVersionedError(not_versioned)
525+ return interesting_ids
526+
527+
528+def _find_children_across_trees(specified_ids, trees):
529+ """Return a set including specified ids and their children.
530+
531+ All matches in all trees will be used.
532+
533+ :param trees: The trees to find file_ids within
534+ :return: a set containing all specified ids and their children
535+ """
536+ interesting_ids = set(specified_ids)
537+ pending = interesting_ids
538+ # now handle children of interesting ids
539+ # we loop so that we handle all children of each id in both trees
540+ while len(pending) > 0:
541+ new_pending = set()
542+ for file_id in pending:
543+ for tree in trees:
544+ try:
545+ path = tree.id2path(file_id)
546+ except errors.NoSuchId:
547+ continue
548+ try:
549+ for child in tree.iter_child_entries(path, file_id):
550+ if child.file_id not in interesting_ids:
551+ new_pending.add(child.file_id)
552+ except errors.NotADirectory:
553+ pass
554+ interesting_ids.update(new_pending)
555+ pending = new_pending
556+ return interesting_ids
557+
558+
559 class MutableInventoryTree(MutableTree, InventoryTree):
560
561 def apply_inventory_delta(self, changes):
562@@ -439,10 +567,11 @@
563 return entry[3]
564 # Find a 'best fit' match if the filesystem is case-insensitive
565 inv_path = self.tree._fix_case_of_inventory_path(inv_path)
566- file_id = self.tree.path2id(inv_path)
567- if file_id is not None:
568- return self.tree.iter_entries_by_dir([file_id]).next()[1]
569- return None
570+ try:
571+ return self.tree.iter_entries_by_dir(
572+ specific_files=[inv_path]).next()[1]
573+ except StopIteration:
574+ return None
575
576 def _convert_to_directory(self, this_ie, inv_path):
577 """Convert an entry to a directory.
578@@ -749,7 +878,10 @@
579
580 def kind(self, path, file_id=None):
581 inv, inv_file_id = self._path2inv_file_id(path, file_id)
582- return inv[inv_file_id].kind
583+ try:
584+ return inv[inv_file_id].kind
585+ except errors.NoSuchId:
586+ raise errors.NoSuchFile(path)
587
588 def path_content_summary(self, path):
589 """See Tree.path_content_summary."""
590
591=== modified file 'breezy/bzr/remote.py'
592--- breezy/bzr/remote.py 2018-03-12 05:58:54 +0000
593+++ breezy/bzr/remote.py 2018-03-24 17:11:56 +0000
594@@ -3441,6 +3441,7 @@
595
596 def _clear_cached_state(self):
597 super(RemoteBranch, self)._clear_cached_state()
598+ self._tags_bytes = None
599 if self._real_branch is not None:
600 self._real_branch._clear_cached_state()
601
602
603=== modified file 'breezy/bzr/workingtree.py'
604--- breezy/bzr/workingtree.py 2018-03-04 19:11:38 +0000
605+++ breezy/bzr/workingtree.py 2018-03-24 17:11:56 +0000
606@@ -652,10 +652,7 @@
607 file_ids are in a WorkingTree if they are in the working inventory
608 and the working file exists.
609 """
610- ret = set()
611- for path, ie in self.iter_entries_by_dir():
612- ret.add(ie.file_id)
613- return ret
614+ return {ie.file_id for path, ie in self.iter_entries_by_dir()}
615
616 def all_versioned_paths(self):
617 return {path for path, ie in self.iter_entries_by_dir()}
618@@ -828,7 +825,7 @@
619
620 try:
621 kind = parent_tree.kind(path, file_id)
622- except errors.NoSuchId:
623+ except errors.NoSuchFile:
624 continue
625 if kind != 'file':
626 # Note: this is slightly unnecessary, because symlinks and
627@@ -1699,13 +1696,13 @@
628 blocked_parent_ids.add(ie.file_id)
629 yield path, ie
630
631- def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
632+ def iter_entries_by_dir(self, specific_files=None,
633+ yield_parents=False):
634 """See Tree.iter_entries_by_dir()"""
635 # The only trick here is that if we supports_tree_reference then we
636 # need to detect if a directory becomes a tree-reference.
637 iterator = super(WorkingTree, self).iter_entries_by_dir(
638- specific_file_ids=specific_file_ids,
639- yield_parents=yield_parents)
640+ specific_files=specific_files, yield_parents=yield_parents)
641 if not self.supports_tree_reference():
642 return iterator
643 else:
644
645=== modified file 'breezy/bzr/workingtree_4.py'
646--- breezy/bzr/workingtree_4.py 2018-03-12 05:18:13 +0000
647+++ breezy/bzr/workingtree_4.py 2018-03-24 17:11:56 +0000
648@@ -1963,7 +1963,7 @@
649 def kind(self, path, file_id=None):
650 entry = self._get_entry(file_id=file_id, path=path)[1]
651 if entry is None:
652- raise errors.NoSuchId(tree=self, file_id=file_id)
653+ raise errors.NoSuchFile(path)
654 parent_index = self._get_parent_index()
655 return dirstate.DirState._minikind_to_kind[entry[parent_index][0]]
656
657
658=== modified file 'breezy/config.py'
659--- breezy/config.py 2017-10-26 11:10:38 +0000
660+++ breezy/config.py 2018-03-24 17:11:56 +0000
661@@ -2706,7 +2706,7 @@
662 Whether revisions associated with tags should be fetched.
663 """))
664 option_registry.register_lazy(
665- 'bzr.transform.orphan_policy', 'breezy.transform', 'opt_transform_orphan')
666+ 'transform.orphan_policy', 'breezy.transform', 'opt_transform_orphan')
667 option_registry.register(
668 Option('bzr.workingtree.worth_saving_limit', default=10,
669 from_unicode=int_from_store, invalid='warning',
670
671=== modified file 'breezy/filter_tree.py'
672--- breezy/filter_tree.py 2017-11-12 17:53:35 +0000
673+++ breezy/filter_tree.py 2018-03-24 17:11:56 +0000
674@@ -47,7 +47,7 @@
675 def get_file_text(self, path, file_id=None):
676 chunks = self.backing_tree.get_file_lines(path, file_id)
677 filters = self.filter_stack_callback(path)
678- context = ContentFilterContext(path, self, None)
679+ context = ContentFilterContext(path, self)
680 contents = filtered_output_bytes(chunks, filters, context)
681 content = ''.join(contents)
682 return content
683@@ -58,14 +58,14 @@
684 def is_executable(self, path, file_id=None):
685 return self.backing_tree.is_executable(path, file_id)
686
687- def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=None):
688+ def iter_entries_by_dir(self, specific_files=None, yield_parents=None):
689 # NB: This simply returns the parent tree's entries; the length may be
690 # wrong but it can't easily be calculated without filtering the whole
691 # text. Currently all callers cope with this; perhaps they should be
692 # updated to a narrower interface that only provides things guaranteed
693 # cheaply available across all trees. -- mbp 20110705
694 return self.backing_tree.iter_entries_by_dir(
695- specific_file_ids=specific_file_ids,
696+ specific_files=specific_files,
697 yield_parents=yield_parents)
698
699 def lock_read(self):
700
701=== modified file 'breezy/filters/__init__.py'
702--- breezy/filters/__init__.py 2017-11-12 13:53:51 +0000
703+++ breezy/filters/__init__.py 2018-03-24 17:11:56 +0000
704@@ -72,19 +72,16 @@
705 class ContentFilterContext(object):
706 """Object providing information that filters can use."""
707
708- def __init__(self, relpath=None, tree=None, entry=None):
709+ def __init__(self, relpath=None, tree=None):
710 """Create a context.
711
712 :param relpath: the relative path or None if this context doesn't
713 support that information.
714 :param tree: the Tree providing this file or None if this context
715 doesn't support that information.
716- :param entry: the InventoryEntry object if it is already known or
717- None if it should be derived if possible
718 """
719 self._relpath = relpath
720 self._tree = tree
721- self._entry = entry
722 # Cached values
723 self._revision_id = None
724 self._revision = None
725@@ -97,24 +94,12 @@
726 """Source Tree object."""
727 return self._tree
728
729- def file_id(self):
730- """File-id of file."""
731- if self._entry is not None:
732- return self._entry.file_id
733- elif self._tree is None:
734- return None
735- else:
736- return self._tree.path2id(self._relpath)
737-
738 def revision_id(self):
739 """Id of revision that last changed this file."""
740 if self._revision_id is None:
741- if self._entry is not None:
742- self._revision_id = self._entry.revision
743- elif self._tree is not None:
744- file_id = self._tree.path2id(self._relpath)
745- self._entry = self._tree.inventory[file_id]
746- self._revision_id = self._entry.revision
747+ if self._tree is not None:
748+ self._revision_id = self._tree.get_file_revision(
749+ self._relpath)
750 return self._revision_id
751
752 def revision(self):
753
754=== modified file 'breezy/gpg.py'
755--- breezy/gpg.py 2018-03-12 05:59:58 +0000
756+++ breezy/gpg.py 2018-03-24 17:11:56 +0000
757@@ -193,12 +193,15 @@
758 try:
759 import gpg
760 self.context = gpg.Context()
761- self.context.armor = True
762+<<<<<<< TREE
763+ self.context.armor = True
764+=======
765+ self.context.armor = True
766+ self.context.signers = self._get_signing_keys()
767+>>>>>>> MERGE-SOURCE
768 except ImportError as error:
769 pass # can't use verify()
770
771- self.context.signers = self._get_signing_keys()
772-
773 def _get_signing_keys(self):
774 import gpg
775 keyname = self._config_stack.get('gpg_signing_key')
776
777=== modified file 'breezy/log.py'
778--- breezy/log.py 2018-03-12 05:56:13 +0000
779+++ breezy/log.py 2018-03-24 17:11:56 +0000
780@@ -64,7 +64,6 @@
781 config,
782 controldir,
783 diff,
784- errors,
785 foreign,
786 repository as _mod_repository,
787 revision as _mod_revision,
788@@ -74,6 +73,7 @@
789 """)
790
791 from . import (
792+ errors,
793 lazy_regex,
794 registry,
795 revisionspec,
796
797=== modified file 'breezy/memorytree.py'
798--- breezy/memorytree.py 2018-03-12 02:03:26 +0000
799+++ breezy/memorytree.py 2018-03-24 17:11:56 +0000
800@@ -270,7 +270,12 @@
801 # is not relevant to memory tree. Until that is done in unlock by
802 # working tree, we cannot share the implementation.
803 if file_ids is None:
804- file_ids = {self.path2id(path) for path in paths}
805+ file_ids = set()
806+ for path in paths:
807+ file_id = self.path2id(path)
808+ if file_id is None:
809+ raise errors.NoSuchFile(path)
810+ file_ids.add(file_id)
811 for file_id in file_ids:
812 if self._inventory.has_id(file_id):
813 self._inventory.remove_recursive_id(file_id)
814
815=== modified file 'breezy/merge.py'
816--- breezy/merge.py 2018-03-12 05:18:13 +0000
817+++ breezy/merge.py 2018-03-24 17:11:56 +0000
818@@ -56,12 +56,13 @@
819 # TODO: Report back as changes are merged in
820
821
822-def transform_tree(from_tree, to_tree, interesting_ids=None):
823+def transform_tree(from_tree, to_tree, interesting_files=None):
824 from_tree.lock_tree_write()
825 operation = cleanup.OperationWithCleanups(merge_inner)
826 operation.add_cleanup(from_tree.unlock)
827 operation.run_simple(from_tree.branch, to_tree, from_tree,
828- ignore_zero=True, interesting_ids=interesting_ids, this_tree=from_tree)
829+ ignore_zero=True, this_tree=from_tree,
830+ interesting_files=interesting_files)
831
832
833 class MergeHooks(hooks.Hooks):
834@@ -130,20 +131,6 @@
835 """
836 raise NotImplementedError(self.file_matches)
837
838- def get_filename(self, params, tree):
839- """Lookup the filename (i.e. basename, not path), given a Tree (e.g.
840- self.merger.this_tree) and a MergeFileHookParams.
841- """
842- return osutils.basename(tree.id2path(params.file_id))
843-
844- def get_filepath(self, params, tree):
845- """Calculate the path to the file in a tree.
846-
847- :param params: A MergeFileHookParams describing the file to merge
848- :param tree: a Tree, e.g. self.merger.this_tree.
849- """
850- return tree.id2path(params.file_id)
851-
852 def merge_contents(self, params):
853 """Merge the contents of a single file."""
854 # Check whether this custom merge logic should be used.
855@@ -216,7 +203,7 @@
856 affected_files = self.default_files
857 self.affected_files = affected_files
858 if affected_files:
859- filepath = self.get_filepath(params, self.merger.this_tree)
860+ filepath = params.this_path
861 if filepath in affected_files:
862 return True
863 return False
864@@ -240,16 +227,21 @@
865 There are some fields hooks can access:
866
867 :ivar file_id: the file ID of the file being merged
868+ :ivar base_path: Path in base tree
869+ :ivar other_path: Path in other tree
870+ :ivar this_path: Path in this tree
871 :ivar trans_id: the transform ID for the merge of this file
872 :ivar this_kind: kind of file_id in 'this' tree
873 :ivar other_kind: kind of file_id in 'other' tree
874 :ivar winner: one of 'this', 'other', 'conflict'
875 """
876
877- def __init__(self, merger, file_id, trans_id, this_kind, other_kind,
878+ def __init__(self, merger, file_id, paths, trans_id, this_kind, other_kind,
879 winner):
880 self._merger = merger
881 self.file_id = file_id
882+ self.paths = paths
883+ self.base_path, self.other_path, self.this_path = paths
884 self.trans_id = trans_id
885 self.this_kind = this_kind
886 self.other_kind = other_kind
887@@ -262,17 +254,17 @@
888 @decorators.cachedproperty
889 def base_lines(self):
890 """The lines of the 'base' version of the file."""
891- return self._merger.get_lines(self._merger.base_tree, self.file_id)
892+ return self._merger.get_lines(self._merger.base_tree, self.base_path, self.file_id)
893
894 @decorators.cachedproperty
895 def this_lines(self):
896 """The lines of the 'this' version of the file."""
897- return self._merger.get_lines(self._merger.this_tree, self.file_id)
898+ return self._merger.get_lines(self._merger.this_tree, self.this_path, self.file_id)
899
900 @decorators.cachedproperty
901 def other_lines(self):
902 """The lines of the 'other' version of the file."""
903- return self._merger.get_lines(self._merger.other_tree, self.file_id)
904+ return self._merger.get_lines(self._merger.other_tree, self.other_path, self.file_id)
905
906
907 class Merger(object):
908@@ -295,7 +287,6 @@
909 self.base_tree = base_tree
910 self.ignore_zero = False
911 self.backup_files = False
912- self.interesting_ids = None
913 self.interesting_files = None
914 self.show_base = False
915 self.reprocess = False
916@@ -610,7 +601,6 @@
917 def make_merger(self):
918 kwargs = {'working_tree': self.this_tree, 'this_tree': self.this_tree,
919 'other_tree': self.other_tree,
920- 'interesting_ids': self.interesting_ids,
921 'interesting_files': self.interesting_files,
922 'this_branch': self.this_branch,
923 'other_branch': self.other_branch,
924@@ -722,7 +712,7 @@
925 requires_file_merge_plan = False
926
927 def __init__(self, working_tree, this_tree, base_tree, other_tree,
928- interesting_ids=None, reprocess=False, show_base=False,
929+ reprocess=False, show_base=False,
930 change_reporter=None, interesting_files=None, do_merge=True,
931 cherrypick=False, lca_trees=None, this_branch=None,
932 other_branch=None):
933@@ -735,30 +725,22 @@
934 :param this_branch: The branch associated with this_tree. Defaults to
935 this_tree.branch if not supplied.
936 :param other_branch: The branch associated with other_tree, if any.
937- :param interesting_ids: The file_ids of files that should be
938- participate in the merge. May not be combined with
939- interesting_files.
940 :param: reprocess If True, perform conflict-reduction processing.
941 :param show_base: If True, show the base revision in text conflicts.
942 (incompatible with reprocess)
943 :param change_reporter: An object that should report changes made
944 :param interesting_files: The tree-relative paths of files that should
945 participate in the merge. If these paths refer to directories,
946- the contents of those directories will also be included. May not
947- be combined with interesting_ids. If neither interesting_files nor
948- interesting_ids is specified, all files may participate in the
949+ the contents of those directories will also be included. If not
950+ specified, all files may participate in the
951 merge.
952 :param lca_trees: Can be set to a dictionary of {revision_id:rev_tree}
953 if the ancestry was found to include a criss-cross merge.
954 Otherwise should be None.
955 """
956 object.__init__(self)
957- if interesting_files is not None and interesting_ids is not None:
958- raise ValueError(
959- 'specify either interesting_ids or interesting_files')
960 if this_branch is None:
961 this_branch = this_tree.branch
962- self.interesting_ids = interesting_ids
963 self.interesting_files = interesting_files
964 self.working_tree = working_tree
965 self.this_tree = this_tree
966@@ -830,18 +812,18 @@
967 hooks = [factory(self) for factory in factories] + [self]
968 self.active_hooks = [hook for hook in hooks if hook is not None]
969 with ui.ui_factory.nested_progress_bar() as child_pb:
970- for num, (file_id, changed, parents3, names3,
971+ for num, (file_id, changed, paths3, parents3, names3,
972 executable3) in enumerate(entries):
973 # Try merging each entry
974 child_pb.update(gettext('Preparing file merge'),
975 num, len(entries))
976- self._merge_names(file_id, parents3, names3, resolver=resolver)
977+ self._merge_names(file_id, paths3, parents3, names3, resolver=resolver)
978 if changed:
979- file_status = self._do_merge_contents(file_id)
980+ file_status = self._do_merge_contents(paths3, file_id)
981 else:
982 file_status = 'unmodified'
983- self._merge_executable(file_id,
984- executable3, file_status, resolver=resolver)
985+ self._merge_executable(paths3, file_id, executable3,
986+ file_status, resolver=resolver)
987 self.tt.fixup_new_roots()
988 self._finish_computing_transform()
989
990@@ -874,27 +856,32 @@
991 iterator = self.other_tree.iter_changes(self.base_tree,
992 specific_files=self.interesting_files,
993 extra_trees=[self.this_tree])
994- this_entries = dict((e.file_id, e) for p, e in
995- self.this_tree.iter_entries_by_dir(
996- self.interesting_ids))
997+ this_interesting_files = self.this_tree.find_related_paths_across_trees(
998+ self.interesting_files, trees=[self.other_tree])
999+ this_entries = dict(self.this_tree.iter_entries_by_dir(
1000+ specific_files=this_interesting_files))
1001 for (file_id, paths, changed, versioned, parents, names, kind,
1002 executable) in iterator:
1003- if (self.interesting_ids is not None and
1004- file_id not in self.interesting_ids):
1005- continue
1006- entry = this_entries.get(file_id)
1007- if entry is not None:
1008- this_name = entry.name
1009- this_parent = entry.parent_id
1010- this_executable = entry.executable
1011+ if paths[0] is not None:
1012+ this_path = _mod_tree.find_previous_path(
1013+ self.base_tree, self.this_tree, paths[0])
1014+ else:
1015+ this_path = _mod_tree.find_previous_path(
1016+ self.other_tree, self.this_tree, paths[1])
1017+ this_entry = this_entries.get(this_path)
1018+ if this_entry is not None:
1019+ this_name = this_entry.name
1020+ this_parent = this_entry.parent_id
1021+ this_executable = this_entry.executable
1022 else:
1023 this_name = None
1024 this_parent = None
1025 this_executable = None
1026 parents3 = parents + (this_parent,)
1027 names3 = names + (this_name,)
1028+ paths3 = paths + (this_path, )
1029 executable3 = executable + (this_executable,)
1030- result.append((file_id, changed, parents3, names3, executable3))
1031+ result.append((file_id, changed, paths3, parents3, names3, executable3))
1032 return result
1033
1034 def _entries_lca(self):
1035@@ -905,10 +892,11 @@
1036
1037 For the multi-valued entries, the format will be (BASE, [lca1, lca2])
1038
1039- :return: [(file_id, changed, parents, names, executable)], where:
1040+ :return: [(file_id, changed, paths, parents, names, executable)], where:
1041
1042 * file_id: Simple file_id of the entry
1043 * changed: Boolean, True if the kind or contents changed else False
1044+ * paths: ((base, [path, in, lcas]), path_other, path_this)
1045 * parents: ((base, [parent_id, in, lcas]), parent_id_other,
1046 parent_id_this)
1047 * names: ((base, [name, in, lcas]), name_in_other, name_in_this)
1048@@ -919,10 +907,10 @@
1049 lookup_trees = [self.this_tree, self.base_tree]
1050 lookup_trees.extend(self._lca_trees)
1051 # I think we should include the lca trees as well
1052- interesting_ids = self.other_tree.paths2ids(self.interesting_files,
1053- lookup_trees)
1054+ interesting_files = self.other_tree.find_related_paths_across_trees(
1055+ self.interesting_files, lookup_trees)
1056 else:
1057- interesting_ids = self.interesting_ids
1058+ interesting_files = None
1059 result = []
1060 walker = _mod_tree.MultiWalker(self.other_tree, self._lca_trees)
1061
1062@@ -932,7 +920,10 @@
1063 # Is this modified at all from any of the other trees?
1064 if other_ie is None:
1065 other_ie = _none_entry
1066- if interesting_ids is not None and file_id not in interesting_ids:
1067+ other_path = None
1068+ else:
1069+ other_path = self.other_tree.id2path(file_id)
1070+ if interesting_files is not None and other_path not in interesting_files:
1071 continue
1072
1073 # If other_revision is found in any of the lcas, that means this
1074@@ -955,21 +946,30 @@
1075 continue
1076
1077 lca_entries = []
1078+ lca_paths = []
1079 for lca_path, lca_ie in lca_values:
1080 if lca_ie is None:
1081 lca_entries.append(_none_entry)
1082+ lca_paths.append(None)
1083 else:
1084 lca_entries.append(lca_ie)
1085+ lca_paths.append(path)
1086
1087 try:
1088 base_ie = base_inventory[file_id]
1089 except errors.NoSuchId:
1090 base_ie = _none_entry
1091+ base_path = None
1092+ else:
1093+ base_path = self.base_tree.id2path(file_id)
1094
1095 try:
1096 this_ie = this_inventory[file_id]
1097 except errors.NoSuchId:
1098 this_ie = _none_entry
1099+ this_path = None
1100+ else:
1101+ this_path = self.this_tree.id2path(file_id)
1102
1103 lca_kinds = []
1104 lca_parent_ids = []
1105@@ -1000,15 +1000,18 @@
1106 continue
1107 content_changed = False
1108 elif other_ie.kind is None or other_ie.kind == 'file':
1109- def get_sha1(ie, tree):
1110- if ie.kind != 'file':
1111- return None
1112- return tree.get_file_sha1(tree.id2path(file_id), file_id)
1113- base_sha1 = get_sha1(base_ie, self.base_tree)
1114- lca_sha1s = [get_sha1(ie, tree) for ie, tree
1115- in zip(lca_entries, self._lca_trees)]
1116- this_sha1 = get_sha1(this_ie, self.this_tree)
1117- other_sha1 = get_sha1(other_ie, self.other_tree)
1118+ def get_sha1(tree, path):
1119+ if path is None:
1120+ return None
1121+ try:
1122+ return tree.get_file_sha1(path, file_id)
1123+ except errors.NoSuchFile:
1124+ return None
1125+ base_sha1 = get_sha1(self.base_tree, base_path)
1126+ lca_sha1s = [get_sha1(tree, lca_path) for tree, lca_path
1127+ in zip(self._lca_trees, lca_paths)]
1128+ this_sha1 = get_sha1(self.this_tree, this_path)
1129+ other_sha1 = get_sha1(self.other_tree, other_path)
1130 sha1_winner = self._lca_multi_way(
1131 (base_sha1, lca_sha1s), other_sha1, this_sha1,
1132 allow_overriding_lca=False)
1133@@ -1023,16 +1026,15 @@
1134 if sha1_winner == 'this':
1135 content_changed = False
1136 elif other_ie.kind == 'symlink':
1137- def get_target(ie, tree):
1138+ def get_target(ie, tree, path):
1139 if ie.kind != 'symlink':
1140 return None
1141- path = tree.id2path(file_id)
1142 return tree.get_symlink_target(path, file_id)
1143- base_target = get_target(base_ie, self.base_tree)
1144- lca_targets = [get_target(ie, tree) for ie, tree
1145- in zip(lca_entries, self._lca_trees)]
1146- this_target = get_target(this_ie, self.this_tree)
1147- other_target = get_target(other_ie, self.other_tree)
1148+ base_target = get_target(base_ie, self.base_tree, base_path)
1149+ lca_targets = [get_target(ie, tree, lca_path) for ie, tree, lca_path
1150+ in zip(lca_entries, self._lca_trees, lca_paths)]
1151+ this_target = get_target(this_ie, self.this_tree, this_path)
1152+ other_target = get_target(other_ie, self.other_tree, other_path)
1153 target_winner = self._lca_multi_way(
1154 (base_target, lca_targets),
1155 other_target, this_target)
1156@@ -1056,6 +1058,8 @@
1157
1158 # If we have gotten this far, that means something has changed
1159 result.append((file_id, content_changed,
1160+ ((base_path, lca_paths),
1161+ other_path, this_path),
1162 ((base_ie.parent_id, lca_parent_ids),
1163 other_ie.parent_id, this_ie.parent_id),
1164 ((base_ie.name, lca_names),
1165@@ -1066,6 +1070,8 @@
1166 return result
1167
1168 def write_modified(self, results):
1169+ if not self.working_tree.supports_merge_modified():
1170+ return
1171 modified_hashes = {}
1172 for path in results.modified_paths:
1173 wt_relpath = self.working_tree.relpath(path)
1174@@ -1076,10 +1082,7 @@
1175 if hash is None:
1176 continue
1177 modified_hashes[file_id] = hash
1178- try:
1179- self.working_tree.set_merge_modified(modified_hashes)
1180- except errors.UnsupportedOperation:
1181- pass # Well, whatever.
1182+ self.working_tree.set_merge_modified(modified_hashes)
1183
1184 @staticmethod
1185 def parent(entry, file_id):
1186@@ -1096,33 +1099,30 @@
1187 return entry.name
1188
1189 @staticmethod
1190- def contents_sha1(tree, file_id):
1191+ def contents_sha1(tree, path, file_id=None):
1192 """Determine the sha1 of the file contents (used as a key method)."""
1193 try:
1194- path = tree.id2path(file_id)
1195- except errors.NoSuchId:
1196+ return tree.get_file_sha1(path, file_id)
1197+ except errors.NoSuchFile:
1198 return None
1199- return tree.get_file_sha1(path, file_id)
1200
1201 @staticmethod
1202- def executable(tree, file_id):
1203+ def executable(tree, path, file_id=None):
1204 """Determine the executability of a file-id (used as a key method)."""
1205 try:
1206- path = tree.id2path(file_id)
1207- except errors.NoSuchId:
1208+ if tree.kind(path, file_id) != "file":
1209+ return False
1210+ except errors.NoSuchFile:
1211 return None
1212- if tree.kind(path, file_id) != "file":
1213- return False
1214 return tree.is_executable(path, file_id)
1215
1216 @staticmethod
1217- def kind(tree, path, file_id):
1218+ def kind(tree, path, file_id=None):
1219 """Determine the kind of a file-id (used as a key method)."""
1220 try:
1221- path = tree.id2path(file_id)
1222- except errors.NoSuchId:
1223+ return tree.kind(path, file_id)
1224+ except errors.NoSuchFile:
1225 return None
1226- return tree.kind(path, file_id)
1227
1228 @staticmethod
1229 def _three_way(base, other, this):
1230@@ -1209,13 +1209,14 @@
1231 else:
1232 names.append(entry.name)
1233 parents.append(entry.parent_id)
1234- return self._merge_names(file_id, parents, names,
1235+ return self._merge_names(file_id, paths, parents, names,
1236 resolver=self._three_way)
1237
1238- def _merge_names(self, file_id, parents, names, resolver):
1239+ def _merge_names(self, file_id, paths, parents, names, resolver):
1240 """Perform a merge on file_id names and parents"""
1241 base_name, other_name, this_name = names
1242 base_parent, other_parent, this_parent = parents
1243+ unused_base_path, other_path, this_path = paths
1244
1245 name_winner = resolver(*names)
1246
1247@@ -1235,7 +1236,7 @@
1248 self._raw_conflicts.append(('path conflict', trans_id, file_id,
1249 this_parent, this_name,
1250 other_parent, other_name))
1251- if not self.other_tree.has_id(file_id):
1252+ if other_path is None:
1253 # it doesn't matter whether the result was 'other' or
1254 # 'conflict'-- if it has no file id, we leave it alone.
1255 return
1256@@ -1257,12 +1258,10 @@
1257 self.tt.adjust_path(name, parent_trans_id,
1258 self.tt.trans_id_file_id(file_id))
1259
1260- def _do_merge_contents(self, file_id):
1261+ def _do_merge_contents(self, paths, file_id):
1262 """Performs a merge on file_id contents."""
1263- def contents_pair(tree):
1264- try:
1265- path = tree.id2path(file_id)
1266- except errors.NoSuchId:
1267+ def contents_pair(tree, path):
1268+ if path is None:
1269 return (None, None)
1270 try:
1271 kind = tree.kind(path, file_id)
1272@@ -1276,23 +1275,27 @@
1273 contents = None
1274 return kind, contents
1275
1276+ base_path, other_path, this_path = paths
1277 # See SPOT run. run, SPOT, run.
1278 # So we're not QUITE repeating ourselves; we do tricky things with
1279 # file kind...
1280- base_pair = contents_pair(self.base_tree)
1281- other_pair = contents_pair(self.other_tree)
1282+ other_pair = contents_pair(self.other_tree, other_path)
1283+ this_pair = contents_pair(self.this_tree, this_path)
1284 if self._lca_trees:
1285- this_pair = contents_pair(self.this_tree)
1286- lca_pairs = [contents_pair(tree) for tree in self._lca_trees]
1287+ (base_path, lca_paths) = base_path
1288+ base_pair = contents_pair(self.base_tree, base_path)
1289+ lca_pairs = [contents_pair(tree, path)
1290+ for tree, path in zip(self._lca_trees, lca_paths)]
1291 winner = self._lca_multi_way((base_pair, lca_pairs), other_pair,
1292 this_pair, allow_overriding_lca=False)
1293 else:
1294+ base_pair = contents_pair(self.base_tree, base_path)
1295 if base_pair == other_pair:
1296 winner = 'this'
1297 else:
1298 # We delayed evaluating this_pair as long as we can to avoid
1299 # unnecessary sha1 calculation
1300- this_pair = contents_pair(self.this_tree)
1301+ this_pair = contents_pair(self.this_tree, this_path)
1302 winner = self._three_way(base_pair, other_pair, this_pair)
1303 if winner == 'this':
1304 # No interesting changes introduced by OTHER
1305@@ -1300,7 +1303,9 @@
1306 # We have a hypothetical conflict, but if we have files, then we
1307 # can try to merge the content
1308 trans_id = self.tt.trans_id_file_id(file_id)
1309- params = MergeFileHookParams(self, file_id, trans_id, this_pair[0],
1310+ params = MergeFileHookParams(
1311+ self, file_id, (base_path, other_path,
1312+ this_path), trans_id, this_pair[0],
1313 other_pair[0], winner)
1314 hooks = self.active_hooks
1315 hook_status = 'not_applicable'
1316@@ -1324,9 +1329,7 @@
1317 inhibit_content_conflict = False
1318 if params.this_kind is None: # file_id is not in THIS
1319 # Is the name used for a different file_id ?
1320- dupe_path = self.other_tree.id2path(file_id)
1321- this_id = self.this_tree.path2id(dupe_path)
1322- if this_id is not None:
1323+ if self.this_tree.is_versioned(other_path):
1324 # Two entries for the same path
1325 keep_this = True
1326 # versioning the merged file will trigger a duplicate
1327@@ -1334,14 +1337,12 @@
1328 self.tt.version_file(file_id, trans_id)
1329 transform.create_from_tree(
1330 self.tt, trans_id, self.other_tree,
1331- self.other_tree.id2path(file_id), file_id=file_id,
1332+ other_path, file_id=file_id,
1333 filter_tree_path=self._get_filter_tree_path(file_id))
1334 inhibit_content_conflict = True
1335 elif params.other_kind is None: # file_id is not in OTHER
1336 # Is the name used for a different file_id ?
1337- dupe_path = self.this_tree.id2path(file_id)
1338- other_id = self.other_tree.path2id(dupe_path)
1339- if other_id is not None:
1340+ if self.other_tree.is_versioned(this_path):
1341 # Two entries for the same path again, but here, the other
1342 # entry will also be merged. We simply inhibit the
1343 # 'content' conflict creation because we know OTHER will
1344@@ -1355,7 +1356,7 @@
1345 self.tt.unversion_file(trans_id)
1346 # This is a contents conflict, because none of the available
1347 # functions could merge it.
1348- file_group = self._dump_conflicts(name, parent_id, file_id,
1349+ file_group = self._dump_conflicts(name, paths, parent_id, file_id,
1350 set_version=True)
1351 self._raw_conflicts.append(('contents conflict', file_group))
1352 elif hook_status == 'success':
1353@@ -1367,7 +1368,7 @@
1354 self._raw_conflicts.append(('text conflict', trans_id))
1355 name = self.tt.final_name(trans_id)
1356 parent_id = self.tt.final_parent(trans_id)
1357- self._dump_conflicts(name, parent_id, file_id)
1358+ self._dump_conflicts(name, paths, parent_id, file_id)
1359 elif hook_status == 'delete':
1360 self.tt.unversion_file(trans_id)
1361 result = "deleted"
1362@@ -1377,7 +1378,7 @@
1363 pass
1364 else:
1365 raise AssertionError('unknown hook_status: %r' % (hook_status,))
1366- if not self.this_tree.has_id(file_id) and result == "modified":
1367+ if not this_path and result == "modified":
1368 self.tt.version_file(file_id, trans_id)
1369 if not keep_this:
1370 # The merge has been performed and produced a new content, so the
1371@@ -1389,14 +1390,14 @@
1372 """Replace this contents with other."""
1373 file_id = merge_hook_params.file_id
1374 trans_id = merge_hook_params.trans_id
1375- if self.other_tree.has_id(file_id):
1376+ if merge_hook_params.other_path is not None:
1377 # OTHER changed the file
1378 transform.create_from_tree(
1379 self.tt, trans_id, self.other_tree,
1380- self.other_tree.id2path(file_id), file_id=file_id,
1381+ merge_hook_params.other_path, file_id=file_id,
1382 filter_tree_path=self._get_filter_tree_path(file_id))
1383 return 'done', None
1384- elif self.this_tree.has_id(file_id):
1385+ elif merge_hook_params.this_path is not None:
1386 # OTHER deleted the file
1387 return 'delete', None
1388 else:
1389@@ -1417,38 +1418,35 @@
1390 # BASE is a file, or both converted to files, so at least we
1391 # have agreement that output should be a file.
1392 try:
1393- self.text_merge(merge_hook_params.file_id,
1394- merge_hook_params.trans_id)
1395+ self.text_merge(merge_hook_params.trans_id,
1396+ merge_hook_params.paths, merge_hook_params.file_id)
1397 except errors.BinaryFile:
1398 return 'not_applicable', None
1399 return 'done', None
1400 else:
1401 return 'not_applicable', None
1402
1403- def get_lines(self, tree, file_id):
1404+ def get_lines(self, tree, path, file_id=None):
1405 """Return the lines in a file, or an empty list."""
1406+ if path is None:
1407+ return []
1408 try:
1409- path = tree.id2path(file_id)
1410- except errors.NoSuchId:
1411+ kind = tree.kind(path, file_id)
1412+ except errors.NoSuchFile:
1413 return []
1414 else:
1415+ if kind != 'file':
1416+ return []
1417 return tree.get_file_lines(path, file_id)
1418
1419- def text_merge(self, file_id, trans_id):
1420+ def text_merge(self, trans_id, paths, file_id):
1421 """Perform a three-way text merge on a file_id"""
1422 # it's possible that we got here with base as a different type.
1423 # if so, we just want two-way text conflicts.
1424- try:
1425- base_path = self.base_tree.id2path(file_id)
1426- except errors.NoSuchId:
1427- base_lines = []
1428- else:
1429- if self.base_tree.kind(base_path, file_id) == "file":
1430- base_lines = self.get_lines(self.base_tree, file_id)
1431- else:
1432- base_lines = []
1433- other_lines = self.get_lines(self.other_tree, file_id)
1434- this_lines = self.get_lines(self.this_tree, file_id)
1435+ base_path, other_path, this_path = paths
1436+ base_lines = self.get_lines(self.base_tree, base_path, file_id)
1437+ other_lines = self.get_lines(self.other_tree, other_path, file_id)
1438+ this_lines = self.get_lines(self.this_tree, this_path, file_id)
1439 m3 = merge3.Merge3(base_lines, this_lines, other_lines,
1440 is_cherrypick=self.cherrypick)
1441 start_marker = "!START OF MERGE CONFLICT!" + "I HOPE THIS IS UNIQUE"
1442@@ -1477,7 +1475,7 @@
1443 self._raw_conflicts.append(('text conflict', trans_id))
1444 name = self.tt.final_name(trans_id)
1445 parent_id = self.tt.final_parent(trans_id)
1446- file_group = self._dump_conflicts(name, parent_id, file_id,
1447+ file_group = self._dump_conflicts(name, paths, parent_id, file_id,
1448 this_lines, base_lines,
1449 other_lines)
1450 file_group.append(trans_id)
1451@@ -1495,7 +1493,7 @@
1452 # Skip the id2path lookup for older formats
1453 return None
1454
1455- def _dump_conflicts(self, name, parent_id, file_id, this_lines=None,
1456+ def _dump_conflicts(self, name, paths, parent_id, file_id, this_lines=None,
1457 base_lines=None, other_lines=None, set_version=False,
1458 no_base=False):
1459 """Emit conflict files.
1460@@ -1503,10 +1501,11 @@
1461 determined automatically. If set_version is true, the .OTHER, .THIS
1462 or .BASE (in that order) will be created as versioned files.
1463 """
1464- data = [('OTHER', self.other_tree, other_lines),
1465- ('THIS', self.this_tree, this_lines)]
1466+ base_path, other_path, this_path = paths
1467+ data = [('OTHER', self.other_tree, other_path, other_lines),
1468+ ('THIS', self.this_tree, this_path, this_lines)]
1469 if not no_base:
1470- data.append(('BASE', self.base_tree, base_lines))
1471+ data.append(('BASE', self.base_tree, base_path, base_lines))
1472
1473 # We need to use the actual path in the working tree of the file here,
1474 # ignoring the conflict suffixes
1475@@ -1523,12 +1522,8 @@
1476
1477 versioned = False
1478 file_group = []
1479- for suffix, tree, lines in data:
1480- try:
1481- path = tree.id2path(file_id)
1482- except errors.NoSuchId:
1483- pass
1484- else:
1485+ for suffix, tree, path, lines in data:
1486+ if path is not None:
1487 trans_id = self._conflict_file(
1488 name, parent_id, path, tree, file_id, suffix, lines,
1489 filter_tree_path)
1490@@ -1549,24 +1544,25 @@
1491 filter_tree_path=filter_tree_path)
1492 return trans_id
1493
1494- def merge_executable(self, file_id, file_status):
1495+ def merge_executable(self, paths, file_id, file_status):
1496 """Perform a merge on the execute bit."""
1497- executable = [self.executable(t, file_id) for t in (self.base_tree,
1498- self.other_tree, self.this_tree)]
1499- self._merge_executable(file_id, executable, file_status,
1500+ executable = [self.executable(t, p, file_id) for t, p in zip([self.base_tree,
1501+ self.other_tree, self.this_tree], paths)]
1502+ self._merge_executable(paths, file_id, executable, file_status,
1503 resolver=self._three_way)
1504
1505- def _merge_executable(self, file_id, executable, file_status,
1506+ def _merge_executable(self, paths, file_id, executable, file_status,
1507 resolver):
1508 """Perform a merge on the execute bit."""
1509 base_executable, other_executable, this_executable = executable
1510+ base_path, other_path, this_path = paths
1511 if file_status == "deleted":
1512 return
1513 winner = resolver(*executable)
1514 if winner == "conflict":
1515 # There must be a None in here, if we have a conflict, but we
1516 # need executability since file status was not deleted.
1517- if self.executable(self.other_tree, file_id) is None:
1518+ if self.executable(self.other_tree, other_path, file_id) is None:
1519 winner = "this"
1520 else:
1521 winner = "other"
1522@@ -1578,11 +1574,11 @@
1523 if winner == "this":
1524 executability = this_executable
1525 else:
1526- if self.other_tree.has_id(file_id):
1527+ if other_path is not None:
1528 executability = other_executable
1529- elif self.this_tree.has_id(file_id):
1530+ elif this_path is not None:
1531 executability = this_executable
1532- elif self.base_tree_has_id(file_id):
1533+ elif base_path is not None:
1534 executability = base_executable
1535 if executability is not None:
1536 trans_id = self.tt.trans_id_file_id(file_id)
1537@@ -1696,11 +1692,12 @@
1538 base_lines = None
1539 return lines, base_lines
1540
1541- def text_merge(self, file_id, trans_id):
1542+ def text_merge(self, trans_id, paths, file_id):
1543 """Perform a (weave) text merge for a given file and file-id.
1544 If conflicts are encountered, .THIS and .OTHER files will be emitted,
1545 and a conflict will be noted.
1546 """
1547+ base_path, other_path, this_path = paths
1548 lines, base_lines = self._merged_lines(file_id)
1549 lines = list(lines)
1550 # Note we're checking whether the OUTPUT is binary in this case,
1551@@ -1712,7 +1709,7 @@
1552 self._raw_conflicts.append(('text conflict', trans_id))
1553 name = self.tt.final_name(trans_id)
1554 parent_id = self.tt.final_parent(trans_id)
1555- file_group = self._dump_conflicts(name, parent_id, file_id,
1556+ file_group = self._dump_conflicts(name, paths, parent_id, file_id,
1557 no_base=False,
1558 base_lines=base_lines)
1559 file_group.append(trans_id)
1560@@ -1731,26 +1728,27 @@
1561
1562 requires_file_merge_plan = False
1563
1564- def dump_file(self, temp_dir, name, tree, file_id):
1565+ def dump_file(self, temp_dir, name, tree, path, file_id=None):
1566 out_path = osutils.pathjoin(temp_dir, name)
1567 with open(out_path, "wb") as out_file:
1568- in_file = tree.get_file(tree.id2path(file_id), file_id)
1569+ in_file = tree.get_file(path, file_id=None)
1570 for line in in_file:
1571 out_file.write(line)
1572 return out_path
1573
1574- def text_merge(self, file_id, trans_id):
1575+ def text_merge(self, trans_id, paths, file_id):
1576 """Perform a diff3 merge using a specified file-id and trans-id.
1577 If conflicts are encountered, .BASE, .THIS. and .OTHER conflict files
1578 will be dumped, and a will be conflict noted.
1579 """
1580 import breezy.patch
1581+ base_path, other_path, this_path = paths
1582 temp_dir = osutils.mkdtemp(prefix="bzr-")
1583 try:
1584 new_file = osutils.pathjoin(temp_dir, "new")
1585- this = self.dump_file(temp_dir, "this", self.this_tree, file_id)
1586- base = self.dump_file(temp_dir, "base", self.base_tree, file_id)
1587- other = self.dump_file(temp_dir, "other", self.other_tree, file_id)
1588+ this = self.dump_file(temp_dir, "this", self.this_tree, this_path, file_id)
1589+ base = self.dump_file(temp_dir, "base", self.base_tree, base_path, file_id)
1590+ other = self.dump_file(temp_dir, "other", self.other_tree, other_path, file_id)
1591 status = breezy.patch.diff3(new_file, this, base, other)
1592 if status not in (0, 1):
1593 raise errors.BzrError("Unhandled diff3 exit code")
1594@@ -1759,7 +1757,7 @@
1595 if status == 1:
1596 name = self.tt.final_name(trans_id)
1597 parent_id = self.tt.final_parent(trans_id)
1598- self._dump_conflicts(name, parent_id, file_id)
1599+ self._dump_conflicts(name, paths, parent_id, file_id)
1600 self._raw_conflicts.append(('text conflict', trans_id))
1601 finally:
1602 osutils.rmtree(temp_dir)
1603@@ -1816,7 +1814,7 @@
1604 self.merge_type = Merge3Merger
1605 self.show_base = False
1606 self.reprocess = False
1607- self.interesting_ids = None
1608+ self.interesting_files = None
1609 self.merge_type = _MergeTypeParameterizer(MergeIntoMergeType,
1610 target_subdir=self._target_subdir,
1611 source_subpath=self._source_subpath)
1612@@ -1878,11 +1876,16 @@
1613 with ui.ui_factory.nested_progress_bar() as child_pb:
1614 entries = self._entries_to_incorporate()
1615 entries = list(entries)
1616- for num, (entry, parent_id, path) in enumerate(entries):
1617+ for num, (entry, parent_id, relpath) in enumerate(entries):
1618 child_pb.update(gettext('Preparing file merge'), num, len(entries))
1619 parent_trans_id = self.tt.trans_id_file_id(parent_id)
1620+<<<<<<< TREE
1621 trans_id = transform.new_by_entry(
1622 self.other_tree.id2path(entry.file_id), self.tt, entry,
1623+=======
1624+ path = osutils.pathjoin(self._source_subpath, relpath)
1625+ trans_id = transform.new_by_entry(path, self.tt, entry,
1626+>>>>>>> MERGE-SOURCE
1627 parent_trans_id, self.other_tree)
1628 self._finish_computing_transform()
1629
1630@@ -1928,7 +1931,6 @@
1631 def merge_inner(this_branch, other_tree, base_tree, ignore_zero=False,
1632 backup_files=False,
1633 merge_type=Merge3Merger,
1634- interesting_ids=None,
1635 show_base=False,
1636 reprocess=False,
1637 other_rev_id=None,
1638@@ -1949,13 +1951,8 @@
1639 change_reporter=change_reporter)
1640 merger.backup_files = backup_files
1641 merger.merge_type = merge_type
1642- merger.interesting_ids = interesting_ids
1643 merger.ignore_zero = ignore_zero
1644- if interesting_files:
1645- if interesting_ids:
1646- raise ValueError('Only supply interesting_ids'
1647- ' or interesting_files')
1648- merger.interesting_files = interesting_files
1649+ merger.interesting_files = interesting_files
1650 merger.show_base = show_base
1651 merger.reprocess = reprocess
1652 merger.other_rev_id = other_rev_id
1653
1654=== modified file 'breezy/plugins/changelog_merge/changelog_merge.py'
1655--- breezy/plugins/changelog_merge/changelog_merge.py 2018-03-09 19:28:43 +0000
1656+++ breezy/plugins/changelog_merge/changelog_merge.py 2018-03-24 17:11:56 +0000
1657@@ -23,6 +23,7 @@
1658 from ... import (
1659 debug,
1660 merge,
1661+ osutils,
1662 urlutils,
1663 )
1664 from ...merge3 import Merge3
1665@@ -63,6 +64,7 @@
1666
1667 name_prefix = "changelog"
1668
1669+<<<<<<< TREE
1670 def get_filepath(self, params, tree):
1671 """Calculate the path to the file in a tree.
1672
1673@@ -75,6 +77,27 @@
1674 :param tree: a Tree, e.g. self.merger.this_tree.
1675 """
1676 return self.get_filename(params, tree)
1677+=======
1678+ def file_matches(self, params):
1679+ affected_files = self.affected_files
1680+ if affected_files is None:
1681+ config = self.merger.this_branch.get_config()
1682+ # Until bzr provides a better policy for caching the config, we
1683+ # just add the part we're interested in to the params to avoid
1684+ # reading the config files repeatedly (breezy.conf, location.conf,
1685+ # branch.conf).
1686+ config_key = self.name_prefix + '_merge_files'
1687+ affected_files = config.get_user_option_as_list(config_key)
1688+ if affected_files is None:
1689+ # If nothing was specified in the config, use the default.
1690+ affected_files = self.default_files
1691+ self.affected_files = affected_files
1692+ if affected_files:
1693+ filepath = osutils.basename(params.this_path)
1694+ if filepath in affected_files:
1695+ return True
1696+ return False
1697+>>>>>>> MERGE-SOURCE
1698
1699 def merge_text(self, params):
1700 """Merge changelog changes.
1701
1702=== modified file 'breezy/plugins/changelog_merge/tests/test_changelog_merge.py'
1703--- breezy/plugins/changelog_merge/tests/test_changelog_merge.py 2017-05-21 18:10:28 +0000
1704+++ breezy/plugins/changelog_merge/tests/test_changelog_merge.py 2018-03-24 17:11:56 +0000
1705@@ -191,8 +191,9 @@
1706 # won't write the new value to disk where get_user_option can get it).
1707 merger.this_branch.get_config().set_user_option(
1708 'changelog_merge_files', 'ChangeLog')
1709- merge_hook_params = merge.MergeFileHookParams(merger, 'clog-id', None,
1710- 'file', 'file', 'conflict')
1711+ merge_hook_params = merge.MergeFileHookParams(merger, 'clog-id',
1712+ ['ChangeLog', 'ChangeLog', 'ChangeLog'], None,
1713+ 'file', 'file', 'conflict')
1714 changelog_merger = changelog_merge.ChangeLogMerger(merger)
1715 return changelog_merger, merge_hook_params
1716
1717
1718=== modified file 'breezy/plugins/launchpad/lp_registration.py'
1719--- breezy/plugins/launchpad/lp_registration.py 2017-09-26 00:55:04 +0000
1720+++ breezy/plugins/launchpad/lp_registration.py 2018-03-24 17:11:56 +0000
1721@@ -74,8 +74,7 @@
1722 self.verbose = verbose
1723 url = self._scheme + "://" + host + handler
1724 request = _urllib2_wrappers.Request("POST", url, request_body)
1725- # FIXME: _urllib2_wrappers will override user-agent with its own
1726- # request.add_header("User-Agent", self.user_agent)
1727+ request.add_header("User-Agent", self.user_agent)
1728 request.add_header("Content-Type", "text/xml")
1729
1730 response = self._opener.open(request)
1731@@ -122,7 +121,7 @@
1732 if transport is None:
1733 uri_type = urllib.splittype(self.service_url)[0]
1734 transport = XMLRPCTransport(uri_type)
1735- transport.user_agent = 'bzr/%s (xmlrpclib/%s)' \
1736+ transport.user_agent = 'Breezy/%s (xmlrpclib/%s)' \
1737 % (_breezy_version, xmlrpclib.__version__)
1738 self.transport = transport
1739
1740
1741=== modified file 'breezy/plugins/po_merge/po_merge.py'
1742--- breezy/plugins/po_merge/po_merge.py 2017-05-22 00:56:52 +0000
1743+++ breezy/plugins/po_merge/po_merge.py 2018-03-24 17:11:56 +0000
1744@@ -99,7 +99,7 @@
1745 # Return early if there is no options defined
1746 return False
1747 po_dir = None
1748- po_path = self.get_filepath(params, self.merger.this_tree)
1749+ po_path = params.this_path
1750 for po_dir in self.po_dirs:
1751 glob = osutils.pathjoin(po_dir, self.po_glob)
1752 if fnmatch.fnmatch(po_path, glob):
1753
1754=== modified file 'breezy/plugins/stats/cmds.py'
1755--- breezy/plugins/stats/cmds.py 2018-02-24 15:50:23 +0000
1756+++ breezy/plugins/stats/cmds.py 2018-03-24 17:11:56 +0000
1757@@ -145,7 +145,7 @@
1758 combo_count = {}
1759 with ui.ui_factory.nested_progress_bar() as pb:
1760 trace.note('getting revisions')
1761- revisions = a_repo.iter_revisions(revids)
1762+ revisions = list(a_repo.iter_revisions(revids))
1763 for count, (revid, rev) in enumerate(revisions):
1764 pb.update('checking', count, len(revids))
1765 for author in rev.get_apparent_authors():
1766@@ -155,7 +155,8 @@
1767 email_users.setdefault(email, set()).add(username)
1768 combo = (username, email)
1769 combo_count[combo] = combo_count.setdefault(combo, 0) + 1
1770- return revisions, collapse_email_and_users(email_users, combo_count)
1771+ return ((rev for (revid, rev) in revisions),
1772+ collapse_email_and_users(email_users, combo_count))
1773
1774
1775 def get_info(a_repo, revision):
1776
1777=== modified file 'breezy/plugins/stats/test_stats.py'
1778--- breezy/plugins/stats/test_stats.py 2017-06-01 23:52:12 +0000
1779+++ breezy/plugins/stats/test_stats.py 2018-03-24 17:11:56 +0000
1780@@ -45,6 +45,7 @@
1781 self.assertEqual({('Fero', ''): ('Fero', ''),
1782 ('FERO', ''): ('Fero', ''),
1783 }, committers)
1784+ self.assertEquals(['1', '2', '3'], sorted([r.revision_id for r in revs]))
1785
1786
1787 class TestCollapseByPerson(TestCase):
1788
1789=== modified file 'breezy/rename_map.py'
1790--- breezy/rename_map.py 2018-03-12 05:18:13 +0000
1791+++ breezy/rename_map.py 2018-03-24 17:11:56 +0000
1792@@ -26,6 +26,7 @@
1793 from .sixish import (
1794 BytesIO,
1795 viewitems,
1796+ viewvalues,
1797 )
1798 from .ui import ui_factory
1799
1800@@ -237,7 +238,14 @@
1801 def _make_inventory_delta(self, matches):
1802 delta = []
1803 file_id_matches = dict((f, p) for p, f in viewitems(matches))
1804- for old_path, entry in self.tree.iter_entries_by_dir(file_id_matches):
1805+ file_id_query = []
1806+ for f in viewvalues(matches):
1807+ try:
1808+ file_id_query.append(self.tree.id2path(f))
1809+ except errors.NoSuchId:
1810+ pass
1811+ for old_path, entry in self.tree.iter_entries_by_dir(
1812+ specific_files=file_id_query):
1813 new_path = file_id_matches[entry.file_id]
1814 parent_path, new_name = osutils.split(new_path)
1815 parent_id = matches.get(parent_path)
1816
1817=== modified file 'breezy/tests/__init__.py'
1818--- breezy/tests/__init__.py 2018-02-15 19:38:33 +0000
1819+++ breezy/tests/__init__.py 2018-03-24 17:11:56 +0000
1820@@ -2693,7 +2693,7 @@
1821 def make_branch_and_memory_tree(self, relpath, format=None):
1822 """Create a branch on the default transport and a MemoryTree for it."""
1823 b = self.make_branch(relpath, format=format)
1824- return memorytree.MemoryTree.create_on_branch(b)
1825+ return b.create_memorytree()
1826
1827 def make_branch_builder(self, relpath, format=None):
1828 branch = self.make_branch(relpath, format=format)
1829
1830=== modified file 'breezy/tests/blackbox/test_config.py'
1831--- breezy/tests/blackbox/test_config.py 2017-07-30 18:38:48 +0000
1832+++ breezy/tests/blackbox/test_config.py 2018-03-24 17:11:56 +0000
1833@@ -116,20 +116,20 @@
1834 ''')
1835
1836 def test_registry_value_all(self):
1837- self.breezy_config.set_user_option('bzr.transform.orphan_policy',
1838+ self.breezy_config.set_user_option('transform.orphan_policy',
1839 u'move')
1840 script.run_script(self, '''\
1841 $ brz config -d tree
1842 breezy:
1843 [DEFAULT]
1844- bzr.transform.orphan_policy = move
1845+ transform.orphan_policy = move
1846 ''')
1847
1848 def test_registry_value_one(self):
1849- self.breezy_config.set_user_option('bzr.transform.orphan_policy',
1850+ self.breezy_config.set_user_option('transform.orphan_policy',
1851 u'move')
1852 script.run_script(self, '''\
1853- $ brz config -d tree bzr.transform.orphan_policy
1854+ $ brz config -d tree transform.orphan_policy
1855 move
1856 ''')
1857
1858
1859=== modified file 'breezy/tests/matchers.py'
1860--- breezy/tests/matchers.py 2018-03-12 02:33:32 +0000
1861+++ breezy/tests/matchers.py 2018-03-24 17:11:56 +0000
1862@@ -184,6 +184,7 @@
1863 return Equals(entries).match(actual)
1864
1865
1866+<<<<<<< TREE
1867 class HasPathRelations(Matcher):
1868 """Matcher verifies that paths have a relation to those in another tree.
1869
1870@@ -241,6 +242,79 @@
1871 return Equals(entries).match(actual)
1872
1873
1874+=======
1875+class HasPathRelations(Matcher):
1876+ """Matcher verifies that paths have a relation to those in another tree.
1877+
1878+ :ivar previous_tree: tree to compare to
1879+ :ivar previous_entries: List of expected entries, as (path, previous_path) pairs.
1880+ """
1881+
1882+ def __init__(self, previous_tree, previous_entries):
1883+ Matcher.__init__(self)
1884+ self.previous_tree = previous_tree
1885+ self.previous_entries = previous_entries
1886+
1887+ def get_path_map(self, tree):
1888+ """Get the (path, previous_path) pairs for the current tree."""
1889+ with tree.lock_read(), self.previous_tree.lock_read():
1890+ for path, ie in tree.iter_entries_by_dir():
1891+ if tree.supports_rename_tracking():
1892+ previous_path = find_previous_path(tree, self.previous_tree, path)
1893+ else:
1894+ if self.previous_tree.is_versioned(path):
1895+ previous_path = path
1896+ else:
1897+ previous_path = None
1898+ if previous_path:
1899+ kind = self.previous_tree.kind(previous_path)
1900+ if kind == 'directory':
1901+ previous_path += '/'
1902+ if ie.parent_id is None:
1903+ yield (u"", previous_path)
1904+ else:
1905+ yield (path+ie.kind_character(), previous_path)
1906+
1907+ @staticmethod
1908+ def _strip_unreferenced_directories(entries):
1909+ """Strip all directories that don't (in)directly contain any files.
1910+
1911+ :param entries: List of path strings or (path, previous_path) tuples to process
1912+ """
1913+ directories = []
1914+ for entry in entries:
1915+ if isinstance(entry, (str, text_type)):
1916+ path = entry
1917+ else:
1918+ path = entry[0]
1919+ if not path or path[-1] == "/":
1920+ # directory
1921+ directories.append((path, entry))
1922+ else:
1923+ # Yield the referenced parent directories
1924+ for dirpath, direntry in directories:
1925+ if osutils.is_inside(dirpath, path):
1926+ yield direntry
1927+ directories = []
1928+ yield entry
1929+
1930+ def __str__(self):
1931+ return 'HasPathRelations(%r, %r)' % (self.previous_tree, self.previous_entries)
1932+
1933+ def match(self, tree):
1934+ actual = list(self.get_path_map(tree))
1935+ if not tree.has_versioned_directories():
1936+ entries = list(self._strip_unreferenced_directories(self.previous_entries))
1937+ else:
1938+ entries = self.previous_entries
1939+ if not tree.supports_rename_tracking():
1940+ entries = [
1941+ (path, path if self.previous_tree.is_versioned(path) else None)
1942+ for (path, previous_path) in entries]
1943+ return Equals(entries).match(actual)
1944+
1945+
1946+>>>>>>> MERGE-SOURCE
1947 class RevisionHistoryMatches(Matcher):
1948 """A matcher that checks if a branch has a specific revision history.
1949
1950
1951=== modified file 'breezy/tests/per_branch/test_branch.py'
1952--- breezy/tests/per_branch/test_branch.py 2018-03-07 01:11:19 +0000
1953+++ breezy/tests/per_branch/test_branch.py 2018-03-24 17:11:56 +0000
1954@@ -34,6 +34,7 @@
1955 revision,
1956 shelf,
1957 tests,
1958+ tree as _mod_tree,
1959 )
1960 from breezy.bzr import (
1961 branch as _mod_bzrbranch,
1962@@ -497,6 +498,10 @@
1963 self.assertFalse(revision.NULL_REVISION in must_fetch)
1964 self.assertFalse(revision.NULL_REVISION in should_fetch)
1965
1966+ def test_create_memorytree(self):
1967+ tree = self.make_branch_and_tree('a')
1968+ self.assertIsInstance(tree.branch.create_memorytree(), _mod_tree.Tree)
1969+
1970
1971 class TestBranchFormat(per_branch.TestCaseWithBranch):
1972
1973
1974=== modified file 'breezy/tests/per_branch/test_commit.py'
1975--- breezy/tests/per_branch/test_commit.py 2018-01-12 08:52:43 +0000
1976+++ breezy/tests/per_branch/test_commit.py 2018-03-24 17:11:56 +0000
1977@@ -194,7 +194,8 @@
1978 dir_id = tree.path2id('dir')
1979 tree.add('dir/subfile')
1980 dir_subfile_id = tree.path2id('dir/subfile')
1981- tree.mkdir('to_be_unversioned')
1982+ tree.put_file_bytes_non_atomic('to_be_unversioned', 'blah')
1983+ tree.add(['to_be_unversioned'])
1984 to_be_unversioned_id = tree.path2id('to_be_unversioned')
1985 tree.put_file_bytes_non_atomic('dir/subfile', 'def')
1986 revid1 = tree.commit('first revision')
1987@@ -212,11 +213,19 @@
1988 revid2 = tree.commit('second revision')
1989
1990 expected_delta = delta.TreeDelta()
1991- expected_delta.added = [('added_dir', added_dir_id, 'directory')]
1992- expected_delta.removed = [('to_be_unversioned',
1993- to_be_unversioned_id, 'directory')]
1994- expected_delta.renamed = [('dir/subfile', 'dir/subfile_renamed',
1995- dir_subfile_id, 'file', False, False)]
1996+ if tree.has_versioned_directories():
1997+ expected_delta.added.append(('added_dir', added_dir_id, 'directory'))
1998+ if tree.supports_rename_tracking():
1999+ expected_delta.removed = [('to_be_unversioned',
2000+ to_be_unversioned_id, 'file')]
2001+ expected_delta.renamed = [('dir/subfile', 'dir/subfile_renamed',
2002+ dir_subfile_id, 'file', False, False)]
2003+ else:
2004+ expected_delta.added.append(('dir/subfile_renamed',
2005+ tree.path2id('dir/subfile_renamed'), 'file'))
2006+ expected_delta.removed = [
2007+ ('dir/subfile', dir_subfile_id, 'file'),
2008+ ('to_be_unversioned', to_be_unversioned_id, 'file')]
2009 expected_delta.modified=[('rootfile', rootfile_id, 'file', True,
2010 False)]
2011 self.assertEqual([('pre_commit', 1, revid1, 2, revid2,
2012
2013=== modified file 'breezy/tests/per_controldir/test_controldir.py'
2014=== modified file 'breezy/tests/per_controldir_colo/test_supported.py'
2015=== modified file 'breezy/tests/per_intertree/test_compare.py'
2016--- breezy/tests/per_intertree/test_compare.py 2017-11-21 20:37:41 +0000
2017+++ breezy/tests/per_intertree/test_compare.py 2018-03-24 17:11:56 +0000
2018@@ -557,7 +557,9 @@
2019
2020 @staticmethod
2021 def get_path_entry(tree, file_id):
2022- iterator = tree.iter_entries_by_dir(specific_file_ids=[file_id])
2023+ with tree.lock_read():
2024+ path = tree.id2path(file_id)
2025+ iterator = tree.iter_entries_by_dir(specific_files=[path])
2026 try:
2027 return next(iterator)
2028 except StopIteration:
2029
2030=== modified file 'breezy/tests/per_intertree/test_file_content_matches.py'
2031--- breezy/tests/per_intertree/test_file_content_matches.py 2018-03-09 18:27:46 +0000
2032+++ breezy/tests/per_intertree/test_file_content_matches.py 2018-03-24 17:11:56 +0000
2033@@ -32,7 +32,13 @@
2034 tree2.add('file', 'file-id-2')
2035 tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2036 inter = self.intertree_class(tree1, tree2)
2037- self.assertTrue(inter.file_content_matches('file', 'file'))
2038+<<<<<<< TREE
2039+ self.assertTrue(inter.file_content_matches('file', 'file'))
2040+=======
2041+ self.assertTrue(inter.file_content_matches(
2042+ 'file', 'file', 'file-id-1', 'file-id-2'))
2043+ self.assertTrue(inter.file_content_matches('file', 'file'))
2044+>>>>>>> MERGE-SOURCE
2045
2046 def test_different_contents_and_same_verifier(self):
2047 tree1 = self.make_branch_and_tree('1')
2048@@ -45,4 +51,11 @@
2049 tree2.add('file', 'file-id-2')
2050 tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2051 inter = self.intertree_class(tree1, tree2)
2052+<<<<<<< TREE
2053 self.assertFalse(inter.file_content_matches('file', 'file'))
2054+=======
2055+ self.assertFalse(inter.file_content_matches(
2056+ 'file', 'file', 'file-id-1', 'file-id-2'))
2057+ self.assertFalse(inter.file_content_matches(
2058+ 'file', 'file'))
2059+>>>>>>> MERGE-SOURCE
2060
2061=== modified file 'breezy/tests/per_repository/test_commit_builder.py'
2062--- breezy/tests/per_repository/test_commit_builder.py 2018-03-09 00:05:39 +0000
2063+++ breezy/tests/per_repository/test_commit_builder.py 2018-03-24 17:11:56 +0000
2064@@ -181,7 +181,7 @@
2065
2066 def test_commit_unchanged_root_record_iter_changes(self):
2067 tree = self.make_branch_and_tree(".")
2068- old_revision_id = tree.commit('')
2069+ old_revision_id = tree.commit('oldrev')
2070 tree.lock_write()
2071 builder = tree.branch.get_commit_builder([old_revision_id])
2072 try:
2073@@ -190,7 +190,7 @@
2074 # pointless commit.
2075 self.assertFalse(builder.any_changes())
2076 builder.finish_inventory()
2077- builder.commit('')
2078+ builder.commit('rev')
2079 builder_tree = builder.revision_tree()
2080 new_root_id = builder_tree.get_root_id()
2081 new_root_revision = builder_tree.get_file_revision(u'')
2082@@ -284,8 +284,8 @@
2083 # commiting without changing the root does not change the
2084 # last modified except on non-rich-root-repositories.
2085 tree = self.make_branch_and_tree('.')
2086- rev1 = tree.commit('')
2087- rev2 = tree.commit('')
2088+ rev1 = tree.commit('rev1')
2089+ rev2 = tree.commit('rev2')
2090 tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
2091 self.assertEqual(rev1, tree1.get_file_revision(u''))
2092 if tree.branch.repository.supports_rich_root():
2093@@ -293,14 +293,13 @@
2094 else:
2095 self.assertEqual(rev2, tree2.get_file_revision(u''))
2096
2097- def _add_commit_check_unchanged(self, tree, name, mini_commit=None):
2098+ def _add_commit_check_unchanged(self, tree, name):
2099 tree.add([name])
2100- self._commit_check_unchanged(tree, name, tree.path2id(name),
2101- mini_commit=mini_commit)
2102+ self._commit_check_unchanged(tree, name, tree.path2id(name))
2103
2104- def _commit_check_unchanged(self, tree, name, file_id, mini_commit=None):
2105- rev1 = tree.commit('')
2106- rev2 = mini_commit(tree, name, name, False, False)
2107+ def _commit_check_unchanged(self, tree, name, file_id):
2108+ rev1 = tree.commit('rev1')
2109+ rev2 = self.mini_commit_record_iter_changes(tree, name, name, False, False)
2110 tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
2111 self.assertEqual(rev1, tree1.get_file_revision(tree1.id2path(file_id)))
2112 self.assertEqual(rev1, tree2.get_file_revision(tree2.id2path(file_id)))
2113@@ -315,8 +314,7 @@
2114 raise tests.TestNotApplicable(
2115 'Format does not support versioned directories')
2116 self.build_tree(['dir/'])
2117- self._add_commit_check_unchanged(tree, 'dir',
2118- mini_commit=self.mini_commit_record_iter_changes)
2119+ self._add_commit_check_unchanged(tree, 'dir')
2120
2121 def test_last_modified_revision_after_commit_dir_contents_unchanged(self):
2122 # committing without changing a dir does not change the last modified
2123@@ -325,10 +323,10 @@
2124 self.build_tree(['dir/', 'dir/orig'])
2125 tree.add(['dir', 'dir/orig'])
2126 dir_id = tree.path2id('dir')
2127- rev1 = tree.commit('')
2128+ rev1 = tree.commit('rev1')
2129 self.build_tree(['dir/content'])
2130 tree.add(['dir/content'])
2131- rev2 = tree.commit('')
2132+ rev2 = tree.commit('rev2')
2133 tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
2134 self.assertEqual(rev1, tree1.get_file_revision('dir'))
2135 self.assertEqual(rev1, tree2.get_file_revision('dir'))
2136@@ -339,16 +337,14 @@
2137 # committing without changing a file does not change the last modified.
2138 tree = self.make_branch_and_tree('.')
2139 self.build_tree(['file'])
2140- self._add_commit_check_unchanged(tree, 'file',
2141- mini_commit=self.mini_commit_record_iter_changes)
2142+ self._add_commit_check_unchanged(tree, 'file')
2143
2144 def test_last_modified_revision_after_commit_link_unchanged(self):
2145 # committing without changing a link does not change the last modified.
2146 self.requireFeature(features.SymlinkFeature)
2147 tree = self.make_branch_and_tree('.')
2148 os.symlink('target', 'link')
2149- self._add_commit_check_unchanged(tree, 'link',
2150- mini_commit=self.mini_commit_record_iter_changes)
2151+ self._add_commit_check_unchanged(tree, 'link')
2152
2153 def test_last_modified_revision_after_commit_reference_unchanged(self):
2154 # committing without changing a subtree does not change the last
2155@@ -358,47 +354,47 @@
2156 try:
2157 tree.add_reference(subtree)
2158 self._commit_check_unchanged(tree, 'reference',
2159- subtree.get_root_id(),
2160- mini_commit=self.mini_commit_record_iter_changes)
2161+ subtree.get_root_id())
2162 except errors.UnsupportedOperation:
2163 return
2164
2165 def _add_commit_renamed_check_changed(self, tree, name,
2166- expect_fs_hash=False, mini_commit=None):
2167+ expect_fs_hash=False):
2168 def rename():
2169 tree.rename_one(name, 'new_' + name)
2170- self._add_commit_change_check_changed(tree, name, rename,
2171- expect_fs_hash=expect_fs_hash, mini_commit=mini_commit)
2172+ self._add_commit_change_check_changed(tree,
2173+ (name, 'new_' + name), rename,
2174+ expect_fs_hash=expect_fs_hash)
2175
2176- def _commit_renamed_check_changed(self, tree, name, file_id,
2177- expect_fs_hash=False, mini_commit=None):
2178+ def _commit_renamed_check_changed(self, tree, name,
2179+ expect_fs_hash=False):
2180 def rename():
2181 tree.rename_one(name, 'new_' + name)
2182- self._commit_change_check_changed(tree, name, file_id, rename,
2183- expect_fs_hash=expect_fs_hash, mini_commit=mini_commit)
2184+ self._commit_change_check_changed(tree, [name, 'new_' + name],
2185+ rename, expect_fs_hash=expect_fs_hash)
2186
2187 def test_last_modified_revision_after_rename_dir_changes(self):
2188 # renaming a dir changes the last modified.
2189 tree = self.make_branch_and_tree('.')
2190+ if not tree.has_versioned_directories():
2191+ raise tests.TestNotApplicable(
2192+ 'Format does not support versioned directories')
2193 self.build_tree(['dir/'])
2194- self._add_commit_renamed_check_changed(tree, 'dir',
2195- mini_commit=self.mini_commit_record_iter_changes)
2196+ self._add_commit_renamed_check_changed(tree, 'dir')
2197
2198 def test_last_modified_revision_after_rename_file_changes(self):
2199 # renaming a file changes the last modified.
2200 tree = self.make_branch_and_tree('.')
2201 self.build_tree(['file'])
2202 self._add_commit_renamed_check_changed(tree, 'file',
2203- expect_fs_hash=True,
2204- mini_commit=self.mini_commit_record_iter_changes)
2205+ expect_fs_hash=True)
2206
2207 def test_last_modified_revision_after_rename_link_changes(self):
2208 # renaming a link changes the last modified.
2209 self.requireFeature(features.SymlinkFeature)
2210 tree = self.make_branch_and_tree('.')
2211 os.symlink('target', 'link')
2212- self._add_commit_renamed_check_changed(tree, 'link',
2213- mini_commit=self.mini_commit_record_iter_changes)
2214+ self._add_commit_renamed_check_changed(tree, 'link')
2215
2216 def test_last_modified_revision_after_rename_ref_changes(self):
2217 # renaming a reference changes the last modified.
2218@@ -406,62 +402,58 @@
2219 subtree = self.make_reference('reference')
2220 try:
2221 tree.add_reference(subtree)
2222- self._commit_renamed_check_changed(tree, 'reference',
2223- subtree.get_root_id(),
2224- mini_commit=self.mini_commit_record_iter_changes)
2225+ self._commit_renamed_check_changed(tree, 'reference')
2226 except errors.UnsupportedOperation:
2227 return
2228
2229 def _add_commit_reparent_check_changed(self, tree, name,
2230- expect_fs_hash=False, mini_commit=None):
2231+ expect_fs_hash=False):
2232 self.build_tree(['newparent/'])
2233 tree.add(['newparent'])
2234 def reparent():
2235 tree.rename_one(name, 'newparent/new_' + name)
2236- self._add_commit_change_check_changed(tree, name, reparent,
2237- expect_fs_hash=expect_fs_hash, mini_commit=mini_commit)
2238+ self._add_commit_change_check_changed(
2239+ tree, (name, 'newparent/new_' + name), reparent,
2240+ expect_fs_hash=expect_fs_hash)
2241
2242 def test_last_modified_revision_after_reparent_dir_changes(self):
2243 # reparenting a dir changes the last modified.
2244 tree = self.make_branch_and_tree('.')
2245 self.build_tree(['dir/'])
2246- self._add_commit_reparent_check_changed(tree, 'dir',
2247- mini_commit=self.mini_commit_record_iter_changes)
2248+ self._add_commit_reparent_check_changed(tree, 'dir')
2249
2250 def test_last_modified_revision_after_reparent_file_changes(self):
2251 # reparenting a file changes the last modified.
2252 tree = self.make_branch_and_tree('.')
2253 self.build_tree(['file'])
2254 self._add_commit_reparent_check_changed(tree, 'file',
2255- expect_fs_hash=True,
2256- mini_commit=self.mini_commit_record_iter_changes)
2257+ expect_fs_hash=True)
2258
2259 def test_last_modified_revision_after_reparent_link_changes(self):
2260 # reparenting a link changes the last modified.
2261 self.requireFeature(features.SymlinkFeature)
2262 tree = self.make_branch_and_tree('.')
2263 os.symlink('target', 'link')
2264- self._add_commit_reparent_check_changed(tree, 'link',
2265- mini_commit=self.mini_commit_record_iter_changes)
2266+ self._add_commit_reparent_check_changed(tree, 'link')
2267
2268- def _add_commit_change_check_changed(self, tree, name, changer,
2269- expect_fs_hash=False, mini_commit=None):
2270- tree.add([name])
2271- file_id = tree.path2id(name)
2272- self.assertIsNot(None, file_id)
2273+ def _add_commit_change_check_changed(self, tree, names, changer,
2274+ expect_fs_hash=False):
2275+ tree.add([names[0]])
2276+ self.assertTrue(tree.is_versioned(names[0]))
2277 self._commit_change_check_changed(
2278- tree, name, file_id,
2279- changer, expect_fs_hash=expect_fs_hash, mini_commit=mini_commit)
2280+ tree, names,
2281+ changer, expect_fs_hash=expect_fs_hash)
2282
2283- def _commit_change_check_changed(self, tree, name, file_id, changer,
2284- expect_fs_hash=False, mini_commit=None):
2285- rev1 = tree.commit('')
2286+ def _commit_change_check_changed(self, tree, names, changer,
2287+ expect_fs_hash=False):
2288+ rev1 = tree.commit('rev1')
2289 changer()
2290- rev2 = mini_commit(tree, name, tree.id2path(file_id),
2291- expect_fs_hash=expect_fs_hash)
2292+ rev2 = self.mini_commit_record_iter_changes(
2293+ tree, names[0], names[1], expect_fs_hash=expect_fs_hash)
2294 tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
2295- self.assertEqual(rev1, tree1.get_file_revision(tree1.id2path(file_id)))
2296- self.assertEqual(rev2, tree2.get_file_revision(tree2.id2path(file_id)))
2297+ self.assertEqual(rev1, tree1.get_file_revision(names[0]))
2298+ self.assertEqual(rev2, tree2.get_file_revision(names[1]))
2299+ file_id = tree1.path2id(names[0])
2300 expected_graph = {}
2301 expected_graph[(file_id, rev1)] = ()
2302 expected_graph[(file_id, rev2)] = ((file_id, rev1),)
2303@@ -488,6 +480,7 @@
2304 # record_iter_changes
2305 parent_ids = tree.get_parent_ids()
2306 builder = tree.branch.get_commit_builder(parent_ids)
2307+<<<<<<< TREE
2308 try:
2309 parent_tree = tree.basis_tree()
2310 parent_tree.lock_read()
2311@@ -521,6 +514,36 @@
2312 except:
2313 builder.abort()
2314 raise
2315+=======
2316+ try:
2317+ parent_tree = tree.basis_tree()
2318+ with parent_tree.lock_read():
2319+ changes = list(tree.iter_changes(parent_tree))
2320+ result = list(builder.record_iter_changes(tree, parent_ids[0],
2321+ changes))
2322+ file_id = tree.path2id(new_name)
2323+ self.assertIsNot(None, file_id)
2324+ if expect_fs_hash:
2325+ tree_file_stat = tree.get_file_with_stat(new_name)
2326+ tree_file_stat[0].close()
2327+ self.assertLength(1, result)
2328+ result = result[0]
2329+ self.assertEqual(result[:2], (file_id, new_name))
2330+ self.assertEqual(result[2][0], tree.get_file_sha1(new_name))
2331+ self.assertEqualStat(result[2][1], tree_file_stat[1])
2332+ else:
2333+ self.assertEqual([], result)
2334+ builder.finish_inventory()
2335+ if tree.branch.repository._format.supports_full_versioned_files:
2336+ inv_key = (builder._new_revision_id,)
2337+ inv_sha1 = tree.branch.repository.inventories.get_sha1s(
2338+ [inv_key])[inv_key]
2339+ self.assertEqual(inv_sha1, builder.inv_sha1)
2340+ rev2 = builder.commit('rev2')
2341+ except BaseException:
2342+ builder.abort()
2343+ raise
2344+>>>>>>> MERGE-SOURCE
2345 delta = builder.get_basis_delta()
2346 delta_dict = dict((change[2], change) for change in delta)
2347 version_recorded = (file_id in delta_dict and
2348@@ -531,11 +554,20 @@
2349 else:
2350 self.assertFalse(version_recorded)
2351
2352+<<<<<<< TREE
2353 revtree = builder.revision_tree()
2354 new_entry = revtree.iter_entries_by_dir(specific_file_ids=[file_id]).next()[1]
2355
2356+=======
2357+ revtree = builder.revision_tree()
2358+ new_entry = revtree.iter_entries_by_dir(specific_files=[new_name]).next()[1]
2359+
2360+>>>>>>> MERGE-SOURCE
2361 if delta_against_basis:
2362- expected_delta = (name, new_name, file_id, new_entry)
2363+ if tree.supports_rename_tracking() or name == new_name:
2364+ expected_delta = (name, new_name, file_id, new_entry)
2365+ else:
2366+ expected_delta = (None, new_name, file_id, new_entry)
2367 self.assertEqual(expected_delta, delta_dict[file_id])
2368 else:
2369 expected_delta = None
2370@@ -557,9 +589,8 @@
2371 self.build_tree(['file'])
2372 def change_file():
2373 tree.put_file_bytes_non_atomic('file', 'new content')
2374- self._add_commit_change_check_changed(tree, 'file', change_file,
2375- expect_fs_hash=True,
2376- mini_commit=self.mini_commit_record_iter_changes)
2377+ self._add_commit_change_check_changed(tree, ('file', 'file'), change_file,
2378+ expect_fs_hash=True)
2379
2380 def _test_last_mod_rev_after_content_link_changes(
2381 self, link, target, newtarget):
2382@@ -571,8 +602,7 @@
2383 os.unlink(link)
2384 os.symlink(newtarget, link)
2385 self._add_commit_change_check_changed(
2386- tree, link, change_link,
2387- mini_commit=self.mini_commit_record_iter_changes)
2388+ tree, (link, link), change_link)
2389
2390 def test_last_modified_rev_after_content_link_changes(self):
2391 self._test_last_mod_rev_after_content_link_changes(
2392@@ -585,24 +615,23 @@
2393
2394 def _commit_sprout(self, tree, name):
2395 tree.add([name])
2396- rev_id = tree.commit('')
2397+ rev_id = tree.commit('rev')
2398 return rev_id, tree.controldir.sprout('t2').open_workingtree()
2399
2400- def _rename_in_tree(self, tree, name):
2401+ def _rename_in_tree(self, tree, name, message):
2402 tree.rename_one(name, 'new_' + name)
2403- return tree.commit('')
2404+ return tree.commit(message)
2405
2406- def _commit_sprout_rename_merge(self, tree1, name, expect_fs_hash=False,
2407- mini_commit=None):
2408+ def _commit_sprout_rename_merge(self, tree1, name, expect_fs_hash=False):
2409 """Do a rename in both trees."""
2410 rev1, tree2 = self._commit_sprout(tree1, name)
2411 file_id = tree2.path2id(name)
2412 self.assertIsNot(None, file_id)
2413 # change both sides equally
2414- rev2 = self._rename_in_tree(tree1, name)
2415- rev3 = self._rename_in_tree(tree2, name)
2416+ rev2 = self._rename_in_tree(tree1, name, 'rev2')
2417+ rev3 = self._rename_in_tree(tree2, name, 'rev3')
2418 tree1.merge_from_branch(tree2.branch)
2419- rev4 = mini_commit(tree1, 'new_' + name, 'new_' + name,
2420+ rev4 = self.mini_commit_record_iter_changes(tree1, 'new_' + name, 'new_' + name,
2421 expect_fs_hash=expect_fs_hash)
2422 tree3, = self._get_revtrees(tree1, [rev4])
2423 self.assertEqual(rev4, tree3.get_file_revision(tree3.id2path(file_id)))
2424@@ -620,26 +649,22 @@
2425 raise tests.TestNotApplicable(
2426 'Format does not support versioned directories')
2427 self.build_tree(['t1/dir/'])
2428- self._commit_sprout_rename_merge(tree1, 'dir',
2429- mini_commit=self.mini_commit_record_iter_changes)
2430+ self._commit_sprout_rename_merge(tree1, 'dir')
2431
2432 def test_last_modified_revision_after_merge_file_changes(self):
2433 # merge a file changes the last modified.
2434 tree1 = self.make_branch_and_tree('t1')
2435 self.build_tree(['t1/file'])
2436- self._commit_sprout_rename_merge(tree1, 'file', expect_fs_hash=True,
2437- mini_commit=self.mini_commit_record_iter_changes)
2438+ self._commit_sprout_rename_merge(tree1, 'file', expect_fs_hash=True)
2439
2440 def test_last_modified_revision_after_merge_link_changes(self):
2441 # merge a link changes the last modified.
2442 self.requireFeature(features.SymlinkFeature)
2443 tree1 = self.make_branch_and_tree('t1')
2444 os.symlink('target', 't1/link')
2445- self._commit_sprout_rename_merge(tree1, 'link',
2446- mini_commit=self.mini_commit_record_iter_changes)
2447+ self._commit_sprout_rename_merge(tree1, 'link')
2448
2449- def _commit_sprout_rename_merge_converged(self, tree1, name,
2450- mini_commit=None):
2451+ def _commit_sprout_rename_merge_converged(self, tree1, name):
2452 # Make a merge which just incorporates a change from a branch:
2453 # The per-file graph is straight line, and no alteration occurs
2454 # in the inventory.
2455@@ -648,11 +673,12 @@
2456 file_id = tree2.path2id(name)
2457 self.assertIsNot(None, file_id)
2458 # change on the other side to merge back
2459- rev2 = self._rename_in_tree(tree2, name)
2460+ rev2 = self._rename_in_tree(tree2, name, 'rev2')
2461 tree1.merge_from_branch(tree2.branch)
2462 def _check_graph(in_tree, changed_in_tree):
2463- rev3 = mini_commit(in_tree, name, 'new_' + name, False,
2464- delta_against_basis=changed_in_tree)
2465+ rev3 = self.mini_commit_record_iter_changes(
2466+ in_tree, name, 'new_' + name, False,
2467+ delta_against_basis=changed_in_tree)
2468 tree3, = self._get_revtrees(in_tree, [rev2])
2469 self.assertEqual(
2470 rev2,
2471@@ -666,27 +692,27 @@
2472 # change to name, branch tree1 and give it an unrelated change, then
2473 # merge that to t2.
2474 other_tree = tree1.controldir.sprout('t3').open_workingtree()
2475- other_rev = other_tree.commit('')
2476+ other_rev = other_tree.commit('other_rev')
2477 tree2.merge_from_branch(other_tree.branch)
2478 _check_graph(tree2, False)
2479
2480- def _commit_sprout_make_merge(self, tree1, make, mini_commit=None):
2481+ def _commit_sprout_make_merge(self, tree1, make):
2482 # Make a merge which incorporates the addition of a new object to
2483 # another branch. The per-file graph shows no additional change
2484 # in the merge because its a straight line.
2485- rev1 = tree1.commit('')
2486+ rev1 = tree1.commit('rev1')
2487 tree2 = tree1.controldir.sprout('t2').open_workingtree()
2488 # make and commit on the other side to merge back
2489 make('t2/name')
2490 tree2.add(['name'])
2491- file_id = tree2.path2id('name')
2492- self.assertIsNot(None, file_id)
2493- rev2 = tree2.commit('')
2494+ self.assertTrue(tree2.is_versioned('name'))
2495+ rev2 = tree2.commit('rev2')
2496 tree1.merge_from_branch(tree2.branch)
2497- rev3 = mini_commit(tree1, None, 'name', False)
2498+ rev3 = self.mini_commit_record_iter_changes(tree1, None, 'name', False)
2499 tree3, = self._get_revtrees(tree1, [rev2])
2500 # in rev2, name should be only changed in rev2
2501- self.assertEqual(rev2, tree3.get_file_revision(tree3.id2path(file_id)))
2502+ self.assertEqual(rev2, tree3.get_file_revision('name'))
2503+ file_id = tree2.path2id('name')
2504 expected_graph = {}
2505 expected_graph[(file_id, rev2)] = ()
2506 self.assertFileGraph(expected_graph, tree1, (file_id, rev2))
2507@@ -698,41 +724,38 @@
2508 raise tests.TestNotApplicable(
2509 'Format does not support versioned directories')
2510 self.build_tree(['t1/dir/'])
2511- self._commit_sprout_rename_merge_converged(tree1, 'dir',
2512- mini_commit=self.mini_commit_record_iter_changes)
2513+ self._commit_sprout_rename_merge_converged(tree1, 'dir')
2514
2515 def test_last_modified_revision_after_converged_merge_file_unchanged(self):
2516 # merge a file that changed preserves the last modified.
2517 tree1 = self.make_branch_and_tree('t1')
2518 self.build_tree(['t1/file'])
2519- self._commit_sprout_rename_merge_converged(tree1, 'file',
2520- mini_commit=self.mini_commit_record_iter_changes)
2521+ self._commit_sprout_rename_merge_converged(tree1, 'file')
2522
2523 def test_last_modified_revision_after_converged_merge_link_unchanged(self):
2524 # merge a link that changed preserves the last modified.
2525 self.requireFeature(features.SymlinkFeature)
2526 tree1 = self.make_branch_and_tree('t1')
2527 os.symlink('target', 't1/link')
2528- self._commit_sprout_rename_merge_converged(tree1, 'link',
2529- mini_commit=self.mini_commit_record_iter_changes)
2530+ self._commit_sprout_rename_merge_converged(tree1, 'link')
2531
2532 def test_last_modified_revision_after_merge_new_dir_unchanged(self):
2533 # merge a new dir does not change the last modified.
2534 tree1 = self.make_branch_and_tree('t1')
2535- self._commit_sprout_make_merge(tree1, self.make_dir,
2536- mini_commit=self.mini_commit_record_iter_changes)
2537+ if not tree1.has_versioned_directories():
2538+ raise tests.TestNotApplicable(
2539+ 'Format does not support versioned directories')
2540+ self._commit_sprout_make_merge(tree1, self.make_dir)
2541
2542 def test_last_modified_revision_after_merge_new_file_unchanged(self):
2543 # merge a new file does not change the last modified.
2544 tree1 = self.make_branch_and_tree('t1')
2545- self._commit_sprout_make_merge(tree1, self.make_file,
2546- mini_commit=self.mini_commit_record_iter_changes)
2547+ self._commit_sprout_make_merge(tree1, self.make_file)
2548
2549 def test_last_modified_revision_after_merge_new_link_unchanged(self):
2550 # merge a new link does not change the last modified.
2551 tree1 = self.make_branch_and_tree('t1')
2552- self._commit_sprout_make_merge(tree1, self.make_link,
2553- mini_commit=self.mini_commit_record_iter_changes)
2554+ self._commit_sprout_make_merge(tree1, self.make_link)
2555
2556 def make_dir(self, name):
2557 self.build_tree([name + '/'])
2558@@ -749,8 +772,7 @@
2559 tree.commit('foo')
2560 return tree
2561
2562- def _check_kind_change(self, make_before, make_after, expect_fs_hash=False,
2563- mini_commit=None):
2564+ def _check_kind_change(self, make_before, make_after, expect_fs_hash=False):
2565 tree = self.make_branch_and_tree('.')
2566 path = 'name'
2567 make_before(path)
2568@@ -762,8 +784,8 @@
2569 osutils.delete_any(path)
2570 make_after(path)
2571
2572- self._add_commit_change_check_changed(tree, path, change_kind,
2573- expect_fs_hash=expect_fs_hash, mini_commit=mini_commit)
2574+ self._add_commit_change_check_changed(tree, (path, path), change_kind,
2575+ expect_fs_hash=expect_fs_hash)
2576
2577 def test_last_modified_dir_file(self):
2578 if not self.repository_format.supports_versioned_directories:
2579@@ -773,8 +795,7 @@
2580 'format does not support versioned directories')
2581 try:
2582 self._check_kind_change(self.make_dir, self.make_file,
2583- expect_fs_hash=True,
2584- mini_commit=self.mini_commit_record_iter_changes)
2585+ expect_fs_hash=True)
2586 except errors.UnsupportedKindChange:
2587 raise tests.TestSkipped(
2588 "tree does not support changing entry kind from "
2589@@ -787,8 +808,7 @@
2590 raise tests.TestNotApplicable(
2591 'format does not support versioned directories')
2592 try:
2593- self._check_kind_change(self.make_dir, self.make_link,
2594- mini_commit=self.mini_commit_record_iter_changes)
2595+ self._check_kind_change(self.make_dir, self.make_link)
2596 except errors.UnsupportedKindChange:
2597 raise tests.TestSkipped(
2598 "tree does not support changing entry kind from "
2599@@ -796,8 +816,7 @@
2600
2601 def test_last_modified_link_file(self):
2602 self._check_kind_change(self.make_link, self.make_file,
2603- expect_fs_hash=True,
2604- mini_commit=self.mini_commit_record_iter_changes)
2605+ expect_fs_hash=True)
2606
2607 def test_last_modified_link_dir(self):
2608 if not self.repository_format.supports_versioned_directories:
2609@@ -806,8 +825,7 @@
2610 raise tests.TestNotApplicable(
2611 'format does not support versioned directories')
2612
2613- self._check_kind_change(self.make_link, self.make_dir,
2614- mini_commit=self.mini_commit_record_iter_changes)
2615+ self._check_kind_change(self.make_link, self.make_dir)
2616
2617 def test_last_modified_file_dir(self):
2618 if not self.repository_format.supports_versioned_directories:
2619@@ -816,12 +834,10 @@
2620 raise tests.TestNotApplicable(
2621 'format does not support versioned directories')
2622
2623- self._check_kind_change(self.make_file, self.make_dir,
2624- mini_commit=self.mini_commit_record_iter_changes)
2625+ self._check_kind_change(self.make_file, self.make_dir)
2626
2627 def test_last_modified_file_link(self):
2628- self._check_kind_change(self.make_file, self.make_link,
2629- mini_commit=self.mini_commit_record_iter_changes)
2630+ self._check_kind_change(self.make_file, self.make_link)
2631
2632 def test_get_commit_builder_with_invalid_revprops(self):
2633 branch = self.make_branch('.')
2634
2635=== modified file 'breezy/tests/per_repository_vf/test_fileid_involved.py'
2636--- breezy/tests/per_repository_vf/test_fileid_involved.py 2017-11-16 10:35:32 +0000
2637+++ breezy/tests/per_repository_vf/test_fileid_involved.py 2018-03-24 17:11:56 +0000
2638@@ -429,10 +429,9 @@
2639 os.chmod() doesn't work on windows. But TreeTransform can mark or
2640 unmark a file as executable.
2641 """
2642- file_id = wt.path2id(path)
2643 tt = transform.TreeTransform(wt)
2644 try:
2645- tt.set_executability(executable, tt.trans_id_tree_file_id(file_id))
2646+ tt.set_executability(executable, tt.trans_id_tree_path(path))
2647 tt.apply()
2648 finally:
2649 tt.finalize()
2650
2651=== modified file 'breezy/tests/per_tree/__init__.py'
2652--- breezy/tests/per_tree/__init__.py 2018-02-21 02:35:42 +0000
2653+++ breezy/tests/per_tree/__init__.py 2018-03-24 17:11:56 +0000
2654@@ -277,56 +277,6 @@
2655 tt.apply()
2656 return self.workingtree_to_test_tree(tree)
2657
2658- def get_tree_with_utf8(self, tree):
2659- """Generate a tree with a utf8 revision and unicode paths."""
2660- self._create_tree_with_utf8(tree)
2661- return self.workingtree_to_test_tree(tree)
2662-
2663- def _create_tree_with_utf8(self, tree):
2664- """Generate a tree with a utf8 revision and unicode paths."""
2665- self.requireFeature(features.UnicodeFilenameFeature)
2666- # We avoid combining characters in file names here, normalization
2667- # checks (as performed by some file systems (OSX) are outside the scope
2668- # of these tests). We use the euro sign \N{Euro Sign} or \u20ac in
2669- # unicode strings or '\xe2\x82\ac' (its utf-8 encoding) in raw strings.
2670- paths = [u'',
2671- u'fo\N{Euro Sign}o',
2672- u'ba\N{Euro Sign}r/',
2673- u'ba\N{Euro Sign}r/ba\N{Euro Sign}z',
2674- ]
2675- # bzr itself does not create unicode file ids, but we want them for
2676- # testing.
2677- file_ids = ['TREE_ROOT',
2678- 'fo\xe2\x82\xaco-id',
2679- 'ba\xe2\x82\xacr-id',
2680- 'ba\xe2\x82\xacz-id',
2681- ]
2682- self.build_tree(paths[1:])
2683- if tree.get_root_id() is None:
2684- # Some trees do not have a root yet.
2685- tree.add(paths, file_ids)
2686- else:
2687- # Some trees will already have a root
2688- tree.set_root_id(file_ids[0])
2689- tree.add(paths[1:], file_ids[1:])
2690- try:
2691- tree.commit(u'in\xedtial', rev_id=u'r\xe9v-1'.encode('utf8'))
2692- except errors.NonAsciiRevisionId:
2693- raise tests.TestSkipped('non-ascii revision ids not supported')
2694-
2695- def get_tree_with_merged_utf8(self, tree):
2696- """Generate a tree with utf8 ancestors."""
2697- self._create_tree_with_utf8(tree)
2698- tree2 = tree.controldir.sprout('tree2').open_workingtree()
2699- self.build_tree([u'tree2/ba\N{Euro Sign}r/qu\N{Euro Sign}x'])
2700- tree2.add([u'ba\N{Euro Sign}r/qu\N{Euro Sign}x'],
2701- [u'qu\N{Euro Sign}x-id'.encode('utf-8')])
2702- tree2.commit(u'to m\xe9rge', rev_id=u'r\xe9v-2'.encode('utf8'))
2703-
2704- tree.merge_from_branch(tree2.branch)
2705- tree.commit(u'm\xe9rge', rev_id=u'r\xe9v-3'.encode('utf8'))
2706- return self.workingtree_to_test_tree(tree)
2707-
2708
2709 def make_scenarios(transport_server, transport_readonly_server, formats):
2710 """Generate test suites for each Tree implementation in breezy.
2711
2712=== modified file 'breezy/tests/per_tree/test_inv.py'
2713--- breezy/tests/per_tree/test_inv.py 2017-08-01 01:44:41 +0000
2714+++ breezy/tests/per_tree/test_inv.py 2018-03-24 17:11:56 +0000
2715@@ -33,8 +33,8 @@
2716 )
2717
2718
2719-def get_entry(tree, file_id):
2720- return tree.iter_entries_by_dir([file_id]).next()[1]
2721+def get_entry(tree, path):
2722+ return tree.iter_entries_by_dir(specific_files=[path]).next()[1]
2723
2724
2725 class TestInventoryWithSymlinks(per_tree.TestCaseWithTree):
2726@@ -52,7 +52,7 @@
2727 raise TestSkipped(
2728 'symlinks not accurately represented in working trees and'
2729 ' preview trees')
2730- entry = get_entry(self.tree, self.tree.path2id('symlink'))
2731+ entry = get_entry(self.tree, 'symlink')
2732 self.assertEqual(entry.symlink_target, 'link-target')
2733
2734 def test_symlink_target_tree(self):
2735@@ -64,7 +64,7 @@
2736 self.assertIs(None, self.tree.get_file_size('symlink'))
2737
2738 def test_symlink(self):
2739- entry = get_entry(self.tree, self.tree.path2id('symlink'))
2740+ entry = get_entry(self.tree, 'symlink')
2741 self.assertEqual(entry.kind, 'symlink')
2742 self.assertEqual(None, entry.text_size)
2743
2744@@ -76,6 +76,9 @@
2745 self.build_tree(['tree/dir/', 'tree/dir/file'])
2746 work_tree.add(['dir', 'dir/file'])
2747 tree = self._convert_tree(work_tree)
2748+ if not isinstance(tree, InventoryTree):
2749+ raise tests.TestNotApplicable(
2750+ "test not applicable on non-inventory tests")
2751 tree.lock_read()
2752 self.addCleanup(tree.unlock)
2753 self.assertEqual({tree.path2id('dir'), tree.path2id('dir/file')},
2754@@ -88,6 +91,9 @@
2755 work_tree.commit('commit old state')
2756 work_tree.remove('file')
2757 tree = self._convert_tree(work_tree)
2758+ if not isinstance(tree, InventoryTree):
2759+ raise tests.TestNotApplicable(
2760+ "test not applicable on non-inventory tests")
2761 tree.lock_read()
2762 self.addCleanup(tree.unlock)
2763 self.assertEqual(set([]), tree.paths2ids(['file'],
2764
2765=== modified file 'breezy/tests/per_tree/test_test_trees.py'
2766--- breezy/tests/per_tree/test_test_trees.py 2018-03-02 16:32:39 +0000
2767+++ breezy/tests/per_tree/test_test_trees.py 2018-03-24 17:11:56 +0000
2768@@ -16,9 +16,11 @@
2769
2770 """Tests for the test trees used by the per_tree tests."""
2771
2772+from breezy import errors
2773 from breezy.tests import per_tree
2774 from breezy.tests import (
2775 TestNotApplicable,
2776+ TestSkipped,
2777 features,
2778 )
2779
2780@@ -138,7 +140,10 @@
2781 self.addCleanup(tree.unlock)
2782 self.assertEqual([], tree.get_parent_ids())
2783 self.assertEqual([], tree.conflicts())
2784- self.assertEqual([], list(tree.unknowns()))
2785+ if tree.has_versioned_directories():
2786+ self.assertEqual([], list(tree.unknowns()))
2787+ else:
2788+ self.assertEqual(['b'], list(tree.unknowns()))
2789 # __iter__ has no strongly defined order
2790 expected_paths = (
2791 ['', 'a'] +
2792@@ -163,25 +168,45 @@
2793 self.addCleanup(tree.unlock)
2794 self.assertEqual([], tree.get_parent_ids())
2795 self.assertEqual([], tree.conflicts())
2796- self.assertEqual([], list(tree.unknowns()))
2797+ if tree.has_versioned_directories():
2798+ self.assertEqual([], list(tree.unknowns()))
2799+ else:
2800+ self.assertEqual(['1top-dir/1dir-in-1topdir'], list(tree.unknowns()))
2801 # __iter__ has no strongly defined order
2802 tree_root = tree.path2id('')
2803- self.assertEqual(
2804- {tree.path2id(p) for p in [
2805- '', '0file', '1top-dir', '1top-dir/1dir-in-1topdir',
2806- '1top-dir/0file-in-1topdir', 'symlink', u'2utf\u1234file']},
2807- set(tree.all_file_ids()))
2808- # note that the order of the paths and fileids is deliberately
2809- # mismatched to ensure that the result order is path based.
2810- self.assertEqual(
2811- [('', 'directory'),
2812- ('0file', 'file'),
2813- ('1top-dir', 'directory'),
2814- (u'2utf\u1234file', 'file'),
2815- ('symlink', 'symlink'),
2816- ('1top-dir/0file-in-1topdir', 'file'),
2817- ('1top-dir/1dir-in-1topdir', 'directory')],
2818- [(path, node.kind) for path, node in tree.iter_entries_by_dir()])
2819+ if tree.has_versioned_directories():
2820+ self.assertEqual(
2821+ {tree.path2id(p) for p in [
2822+ '', '0file', '1top-dir', '1top-dir/1dir-in-1topdir',
2823+ '1top-dir/0file-in-1topdir', 'symlink', u'2utf\u1234file']},
2824+ set(tree.all_file_ids()))
2825+ # note that the order of the paths and fileids is deliberately
2826+ # mismatched to ensure that the result order is path based.
2827+ self.assertEqual(
2828+ [('', 'directory'),
2829+ ('0file', 'file'),
2830+ ('1top-dir', 'directory'),
2831+ (u'2utf\u1234file', 'file'),
2832+ ('symlink', 'symlink'),
2833+ ('1top-dir/0file-in-1topdir', 'file'),
2834+ ('1top-dir/1dir-in-1topdir', 'directory')],
2835+ [(path, node.kind) for path, node in tree.iter_entries_by_dir()])
2836+ else:
2837+ self.assertEqual(
2838+ {tree.path2id(p) for p in [
2839+ '', '0file', '1top-dir',
2840+ '1top-dir/0file-in-1topdir', 'symlink', u'2utf\u1234file']},
2841+ set(tree.all_file_ids()))
2842+ # note that the order of the paths and fileids is deliberately
2843+ # mismatched to ensure that the result order is path based.
2844+ self.assertEqual(
2845+ [('', 'directory'),
2846+ ('0file', 'file'),
2847+ ('1top-dir', 'directory'),
2848+ (u'2utf\u1234file', 'file'),
2849+ ('symlink', 'symlink'),
2850+ ('1top-dir/0file-in-1topdir', 'file')],
2851+ [(path, node.kind) for path, node in tree.iter_entries_by_dir()])
2852
2853 def test_tree_with_subdirs_and_all_content_types_wo_symlinks(self):
2854 # currently this test tree requires unicode. It might be good
2855@@ -192,30 +217,90 @@
2856 self.addCleanup(tree.unlock)
2857 self.assertEqual([], tree.get_parent_ids())
2858 self.assertEqual([], tree.conflicts())
2859- self.assertEqual([], list(tree.unknowns()))
2860+ if tree.has_versioned_directories():
2861+ self.assertEqual([], list(tree.unknowns()))
2862+ else:
2863+ self.assertEqual(['1top-dir/1dir-in-1topdir'], list(tree.unknowns()))
2864 # __iter__ has no strongly defined order
2865 tree_root = tree.path2id('')
2866- self.assertEqual(
2867- {'', '0file', '1top-dir', '1top-dir/0file-in-1topdir',
2868- '1top-dir/1dir-in-1topdir', u'2utf\u1234file'},
2869- set(tree.all_versioned_paths()))
2870- # note that the order of the paths and fileids is deliberately
2871- # mismatched to ensure that the result order is path based.
2872- self.assertEqual(
2873- [('', 'directory'),
2874- ('0file', 'file'),
2875- ('1top-dir', 'directory'),
2876- (u'2utf\u1234file', 'file'),
2877- ('1top-dir/0file-in-1topdir', 'file'),
2878- ('1top-dir/1dir-in-1topdir', 'directory')],
2879- [(path, node.kind) for path, node in tree.iter_entries_by_dir()])
2880+ if tree.has_versioned_directories():
2881+ self.assertEqual(
2882+ {'', '0file', '1top-dir', '1top-dir/0file-in-1topdir',
2883+ '1top-dir/1dir-in-1topdir', u'2utf\u1234file'},
2884+ set(tree.all_versioned_paths()))
2885+ # note that the order of the paths and fileids is deliberately
2886+ # mismatched to ensure that the result order is path based.
2887+ self.assertEqual(
2888+ [('', 'directory'),
2889+ ('0file', 'file'),
2890+ ('1top-dir', 'directory'),
2891+ (u'2utf\u1234file', 'file'),
2892+ ('1top-dir/0file-in-1topdir', 'file'),
2893+ ('1top-dir/1dir-in-1topdir', 'directory')],
2894+ [(path, node.kind) for path, node in tree.iter_entries_by_dir()])
2895+ else:
2896+ self.assertEqual(
2897+ {'', '0file', '1top-dir', '1top-dir/0file-in-1topdir',
2898+ u'2utf\u1234file'},
2899+ set(tree.all_versioned_paths()))
2900+ # note that the order of the paths and fileids is deliberately
2901+ # mismatched to ensure that the result order is path based.
2902+ self.assertEqual(
2903+ [('', 'directory'),
2904+ ('0file', 'file'),
2905+ ('1top-dir', 'directory'),
2906+ (u'2utf\u1234file', 'file'),
2907+ ('1top-dir/0file-in-1topdir', 'file')],
2908+ [(path, node.kind) for path, node in tree.iter_entries_by_dir()])
2909+
2910+ def _create_tree_with_utf8(self, tree):
2911+ self.requireFeature(features.UnicodeFilenameFeature)
2912+
2913+ # We avoid combining characters in file names here, normalization
2914+ # checks (as performed by some file systems (OSX) are outside the scope
2915+ # of these tests). We use the euro sign \N{Euro Sign} or \u20ac in
2916+ # unicode strings or '\xe2\x82\ac' (its utf-8 encoding) in raw strings.
2917+ paths = [u'',
2918+ u'fo\N{Euro Sign}o',
2919+ u'ba\N{Euro Sign}r/',
2920+ u'ba\N{Euro Sign}r/ba\N{Euro Sign}z',
2921+ ]
2922+ # bzr itself does not create unicode file ids, but we want them for
2923+ # testing.
2924+ file_ids = ['TREE_ROOT',
2925+ 'fo\xe2\x82\xaco-id',
2926+ 'ba\xe2\x82\xacr-id',
2927+ 'ba\xe2\x82\xacz-id',
2928+ ]
2929+ self.build_tree(paths[1:])
2930+ if tree.get_root_id() is None:
2931+ # Some trees do not have a root yet.
2932+ tree.add(paths, file_ids)
2933+ else:
2934+ # Some trees will already have a root
2935+ if tree.supports_setting_file_ids():
2936+ tree.set_root_id(file_ids[0])
2937+ tree.add(paths[1:], file_ids[1:])
2938+ else:
2939+ tree.add(paths[1:])
2940+ if tree.branch.repository._format.supports_setting_revision_ids:
2941+ try:
2942+ tree.commit(u'in\xedtial', rev_id=u'r\xe9v-1'.encode('utf8'))
2943+ except errors.NonAsciiRevisionId:
2944+ raise TestSkipped('non-ascii revision ids not supported')
2945+ else:
2946+ tree.commit(u'in\xedtial')
2947+
2948+ return tree
2949
2950 def test_tree_with_utf8(self):
2951 tree = self.make_branch_and_tree('.')
2952 if not tree.supports_setting_file_ids():
2953 raise TestNotApplicable(
2954 'format does not support custom file ids')
2955- tree = self.get_tree_with_utf8(tree)
2956+ self._create_tree_with_utf8(tree)
2957+
2958+ tree = self.workingtree_to_test_tree(tree)
2959
2960 revision_id = u'r\xe9v-1'.encode('utf8')
2961 root_id = 'TREE_ROOT'
2962@@ -228,11 +313,8 @@
2963 (u'ba\N{Euro Sign}r/ba\N{Euro Sign}z',
2964 baz_id, bar_id, revision_id),
2965 ]
2966- tree.lock_read()
2967- try:
2968+ with tree.lock_read():
2969 path_entries = list(tree.iter_entries_by_dir())
2970- finally:
2971- tree.unlock()
2972
2973 for expected, (path, ie) in zip(path_and_ids, path_entries):
2974 self.assertEqual(expected[0], path) # Paths should match
2975@@ -258,8 +340,31 @@
2976 self.assertIsInstance(last_revision(), str)
2977
2978 def test_tree_with_merged_utf8(self):
2979- tree = self.make_branch_and_tree('.')
2980- tree = self.get_tree_with_merged_utf8(tree)
2981+ wt = self.make_branch_and_tree('.')
2982+
2983+ self._create_tree_with_utf8(wt)
2984+
2985+ tree2 = wt.controldir.sprout('tree2').open_workingtree()
2986+ self.build_tree([u'tree2/ba\N{Euro Sign}r/qu\N{Euro Sign}x'])
2987+ if wt.supports_setting_file_ids():
2988+ tree2.add([u'ba\N{Euro Sign}r/qu\N{Euro Sign}x'],
2989+ [u'qu\N{Euro Sign}x-id'.encode('utf-8')])
2990+ else:
2991+ tree2.add([u'ba\N{Euro Sign}r/qu\N{Euro Sign}x'])
2992+ if wt.branch.repository._format.supports_setting_revision_ids:
2993+ tree2.commit(u'to m\xe9rge', rev_id=u'r\xe9v-2'.encode('utf8'))
2994+ else:
2995+ tree2.commit(u'to m\xe9rge')
2996+
2997+ self.assertTrue(tree2.is_versioned(u'ba\N{Euro Sign}r/qu\N{Euro Sign}x'))
2998+ wt.merge_from_branch(tree2.branch)
2999+ self.assertTrue(wt.is_versioned(u'ba\N{Euro Sign}r/qu\N{Euro Sign}x'))
3000+
3001+ if wt.branch.repository._format.supports_setting_revision_ids:
3002+ wt.commit(u'm\xe9rge', rev_id=u'r\xe9v-3'.encode('utf8'))
3003+ else:
3004+ wt.commit(u'm\xe9rge')
3005+ tree = self.workingtree_to_test_tree(wt)
3006
3007 revision_id_1 = u'r\xe9v-1'.encode('utf8')
3008 revision_id_2 = u'r\xe9v-2'.encode('utf8')
3009@@ -276,21 +381,19 @@
3010 (u'ba\N{Euro Sign}r/qu\N{Euro Sign}x',
3011 qux_id, bar_id, revision_id_2),
3012 ]
3013- tree.lock_read()
3014- try:
3015+ with tree.lock_read():
3016 path_entries = list(tree.iter_entries_by_dir())
3017- finally:
3018- tree.unlock()
3019
3020 for (epath, efid, eparent, erev), (path, ie) in zip(path_and_ids,
3021 path_entries):
3022 self.assertEqual(epath, path) # Paths should match
3023 self.assertIsInstance(path, unicode)
3024- self.assertEqual(efid, ie.file_id)
3025- self.assertIsInstance(ie.file_id, str)
3026- self.assertEqual(eparent, ie.parent_id)
3027+ self.assertIsInstance(ie.file_id, bytes)
3028+ if wt.supports_setting_file_ids():
3029+ self.assertEqual(efid, ie.file_id)
3030+ self.assertEqual(eparent, ie.parent_id)
3031 if eparent is not None:
3032- self.assertIsInstance(ie.parent_id, str)
3033+ self.assertIsInstance(ie.parent_id, bytes)
3034 # WorkingTree's return None for the last modified revision
3035 if ie.revision is not None:
3036 self.assertIsInstance(ie.revision, str)
3037@@ -299,10 +402,13 @@
3038 # but not all will
3039 continue
3040 self.assertEqual(erev, ie.revision)
3041- self.assertEqual(len(path_and_ids), len(path_entries))
3042+ self.assertEqual(len(path_and_ids), len(path_entries),
3043+ "%r vs %r" % (
3044+ [p for (p, f, pf, r) in path_and_ids],
3045+ [p for (p, e) in path_entries]))
3046 get_revision_id = getattr(tree, 'get_revision_id', None)
3047 if get_revision_id is not None:
3048- self.assertIsInstance(get_revision_id(), str)
3049+ self.assertIsInstance(get_revision_id(), bytes)
3050 last_revision = getattr(tree, 'last_revision', None)
3051 if last_revision is not None:
3052- self.assertIsInstance(last_revision(), str)
3053+ self.assertIsInstance(last_revision(), bytes)
3054
3055=== modified file 'breezy/tests/per_tree/test_tree.py'
3056--- breezy/tests/per_tree/test_tree.py 2018-03-04 17:22:37 +0000
3057+++ breezy/tests/per_tree/test_tree.py 2018-03-24 17:11:56 +0000
3058@@ -359,4 +359,12 @@
3059 def test_has_versioned_directories(self):
3060 work_tree = self.make_branch_and_tree('tree')
3061 tree = self._convert_tree(work_tree)
3062- self.assertSubset([tree.has_versioned_directories()], (True, False))
3063+ self.assertIn(tree.has_versioned_directories(), (True, False))
3064+
3065+
3066+class TestSupportsRenameTracking(TestCaseWithTree):
3067+
3068+ def test_supports_rename_tracking(self):
3069+ work_tree = self.make_branch_and_tree('tree')
3070+ tree = self._convert_tree(work_tree)
3071+ self.assertSubset([tree.supports_rename_tracking()], (True, False))
3072
3073=== modified file 'breezy/tests/per_tree/test_walkdirs.py'
3074--- breezy/tests/per_tree/test_walkdirs.py 2018-03-12 05:56:02 +0000
3075+++ breezy/tests/per_tree/test_walkdirs.py 2018-03-24 17:11:56 +0000
3076@@ -48,7 +48,7 @@
3077 ]
3078 if symlinks:
3079 dirblocks[0][1].append(('symlink', 'symlink', 'symlink', None,
3080- 'symlink', 'symlink'))
3081+ tree.path2id('symlink'), 'symlink'))
3082 return dirblocks
3083
3084 def test_walkdir_root(self):
3085
3086=== modified file 'breezy/tests/per_workingtree/test_check_state.py'
3087--- breezy/tests/per_workingtree/test_check_state.py 2017-05-21 18:10:28 +0000
3088+++ breezy/tests/per_workingtree/test_check_state.py 2018-03-24 17:11:56 +0000
3089@@ -81,8 +81,11 @@
3090 tree = self.make_initial_tree()
3091 foo_id = tree.path2id('foo')
3092 tree.rename_one('foo', 'baz')
3093- self.assertEqual(None, tree.path2id('foo'))
3094- self.assertEqual(foo_id, tree.path2id('baz'))
3095+ self.assertFalse(tree.is_versioned('foo'))
3096+ if tree.supports_rename_tracking():
3097+ self.assertEqual(foo_id, tree.path2id('baz'))
3098+ else:
3099+ self.assertTrue(tree.is_versioned('baz'))
3100 tree.reset_state()
3101 # After reset, we should have forgotten about the rename, but we won't
3102 # have
3103
3104=== modified file 'breezy/tests/per_workingtree/test_executable.py'
3105=== modified file 'breezy/tests/per_workingtree/test_inv.py'
3106--- breezy/tests/per_workingtree/test_inv.py 2018-02-15 19:38:33 +0000
3107+++ breezy/tests/per_workingtree/test_inv.py 2018-03-24 17:11:56 +0000
3108@@ -178,6 +178,6 @@
3109 # wt.current_dirstate()'s idea about what files are where.
3110 ie = base.inventory['subdir-id']
3111 self.assertEqual('directory', ie.kind)
3112- path, ie = next(base.iter_entries_by_dir(['subdir-id']))
3113+ path, ie = next(base.iter_entries_by_dir(specific_files=['subdir']))
3114 self.assertEqual('subdir', path)
3115 self.assertEqual('tree-reference', ie.kind)
3116
3117=== modified file 'breezy/tests/per_workingtree/test_merge_from_branch.py'
3118--- breezy/tests/per_workingtree/test_merge_from_branch.py 2018-03-08 02:01:07 +0000
3119+++ breezy/tests/per_workingtree/test_merge_from_branch.py 2018-03-24 17:11:56 +0000
3120@@ -111,7 +111,7 @@
3121 self.build_tree_contents([('this/foo', 'baz')])
3122 this.commit('content -> baz')
3123 class QuxMerge(merge.Merge3Merger):
3124- def text_merge(self, file_id, trans_id):
3125+ def text_merge(self, trans_id, paths, file_id):
3126 self.tt.create_file('qux', trans_id)
3127 this.merge_from_branch(other.branch, merge_type=QuxMerge)
3128 self.assertEqual('qux', this.get_file_text('foo'))
3129
3130=== modified file 'breezy/tests/per_workingtree/test_move.py'
3131--- breezy/tests/per_workingtree/test_move.py 2018-03-12 05:18:13 +0000
3132+++ breezy/tests/per_workingtree/test_move.py 2018-03-24 17:11:56 +0000
3133@@ -137,13 +137,25 @@
3134 tree.move, ['d', 'c', 'b'], 'a')
3135 if osutils.lexists('a/c'):
3136 # If 'c' was actually moved, then 'd' should have also been moved
3137+<<<<<<< TREE
3138 self.assertPathRelations(
3139 tree.basis_tree(), tree,
3140 [('', ''), ('a/', 'a'), ('a/c', 'c'), ('a/d', 'd')])
3141+=======
3142+ self.assertPathRelations(
3143+ tree.basis_tree(), tree,
3144+ [('', ''), ('a/', 'a/'), ('a/c', 'c'), ('a/d', 'd')])
3145+>>>>>>> MERGE-SOURCE
3146 else:
3147+<<<<<<< TREE
3148 self.assertPathRelations(
3149 tree.basis_tree(), tree,
3150 [('', ''), ( 'a/', 'a'), ('c', 'c'), ('d', 'd')])
3151+=======
3152+ self.assertPathRelations(
3153+ tree.basis_tree(), tree,
3154+ [('', ''), ( 'a/', 'a/'), ('c', 'c'), ('d', 'd')])
3155+>>>>>>> MERGE-SOURCE
3156 tree._validate()
3157
3158 def test_move_over_deleted(self):
3159@@ -154,9 +166,15 @@
3160
3161 tree.remove(['a/b'], keep_files=False)
3162 self.assertEqual([('b', 'a/b')], tree.move(['b'], 'a'))
3163+<<<<<<< TREE
3164 self.assertPathRelations(
3165 tree.basis_tree(), tree,
3166 [('', ''), ('a/', 'a'), ('a/b', 'b')])
3167+=======
3168+ self.assertPathRelations(
3169+ tree.basis_tree(), tree,
3170+ [('', ''), ('a/', 'a/'), ('a/b', 'b')])
3171+>>>>>>> MERGE-SOURCE
3172 tree._validate()
3173
3174 def test_move_subdir(self):
3175@@ -164,6 +182,7 @@
3176 self.build_tree(['a', 'b/', 'b/c'])
3177 tree.add(['a', 'b', 'b/c'])
3178 tree.commit('initial')
3179+<<<<<<< TREE
3180 self.assertPathRelations(
3181 tree.basis_tree(), tree,
3182 [('', ''), ('a', 'a'), ('b/', 'b'), ('b/c', 'b/c')])
3183@@ -172,6 +191,16 @@
3184 self.assertPathRelations(
3185 tree.basis_tree(), tree,
3186 [('', ''), ('b/', 'b'), ('b/a', 'a'), ('b/c', 'b/c')])
3187+=======
3188+ self.assertPathRelations(
3189+ tree.basis_tree(), tree,
3190+ [('', ''), ('a', 'a'), ('b/', 'b/'), ('b/c', 'b/c')])
3191+ a_contents = tree.get_file_text('a')
3192+ self.assertEqual([('a', 'b/a')], tree.move(['a'], 'b'))
3193+ self.assertPathRelations(
3194+ tree.basis_tree(), tree,
3195+ [('', ''), ('b/', 'b/'), ('b/a', 'a'), ('b/c', 'b/c')])
3196+>>>>>>> MERGE-SOURCE
3197 self.assertPathDoesNotExist('a')
3198 self.assertFileEqual(a_contents, 'b/a')
3199 tree._validate()
3200@@ -184,9 +213,15 @@
3201 c_contents = tree.get_file_text('b/c')
3202 self.assertEqual([('b/c', 'c')],
3203 tree.move(['b/c'], ''))
3204+<<<<<<< TREE
3205 self.assertPathRelations(
3206 tree.basis_tree(), tree,
3207 [('', ''), ('a', 'a'), ('b/', 'b'), ('c', 'b/c')])
3208+=======
3209+ self.assertPathRelations(
3210+ tree.basis_tree(), tree,
3211+ [('', ''), ('a', 'a'), ('b/', 'b/'), ('c', 'b/c')])
3212+>>>>>>> MERGE-SOURCE
3213 self.assertPathDoesNotExist('b/c')
3214 self.assertFileEqual(c_contents, 'c')
3215 tree._validate()
3216@@ -202,14 +237,26 @@
3217 # 'c' may or may not have been moved, but either way the tree should
3218 # maintain a consistent state.
3219 if osutils.lexists('c'):
3220+<<<<<<< TREE
3221 self.assertPathRelations(
3222 tree.basis_tree(), tree,
3223 [('', ''), ('a', 'a'), ('b/', 'b'), ('c', 'c')])
3224+=======
3225+ self.assertPathRelations(
3226+ tree.basis_tree(), tree,
3227+ [('', ''), ('a', 'a'), ('b/', 'b/'), ('c', 'c')])
3228+>>>>>>> MERGE-SOURCE
3229 else:
3230 self.assertPathExists('b/c')
3231+<<<<<<< TREE
3232 self.assertPathRelations(
3233 tree.basis_tree(), tree,
3234 [('', ''), ('a', 'a'), ('b/', 'b'), ('b/c', 'c')])
3235+=======
3236+ self.assertPathRelations(
3237+ tree.basis_tree(), tree,
3238+ [('', ''), ('a', 'a'), ('b/', 'b/'), ('b/c', 'c')])
3239+>>>>>>> MERGE-SOURCE
3240 tree._validate()
3241
3242 def test_move_onto_self(self):
3243@@ -239,16 +286,28 @@
3244 tree.commit('initial')
3245 os.rename('a', 'b/a')
3246
3247+<<<<<<< TREE
3248 self.assertPathRelations(
3249 tree.basis_tree(), tree,
3250 [('', ''), ('a', 'a'), ('b/', 'b')])
3251+=======
3252+ self.assertPathRelations(
3253+ tree.basis_tree(), tree,
3254+ [('', ''), ('a', 'a'), ('b/', 'b/')])
3255+>>>>>>> MERGE-SOURCE
3256 # We don't need after=True as long as source is missing and target
3257 # exists.
3258 self.assertEqual([('a', 'b/a')],
3259 tree.move(['a'], 'b'))
3260+<<<<<<< TREE
3261 self.assertPathRelations(
3262 tree.basis_tree(), tree,
3263 [('', ''), ('b/', 'b'), ('b/a', 'a')])
3264+=======
3265+ self.assertPathRelations(
3266+ tree.basis_tree(), tree,
3267+ [('', ''), ('b/', 'b/'), ('b/a', 'a')])
3268+>>>>>>> MERGE-SOURCE
3269 tree._validate()
3270
3271 def test_move_after_with_after(self):
3272@@ -258,14 +317,27 @@
3273 tree.commit('initial')
3274 os.rename('a', 'b/a')
3275
3276+<<<<<<< TREE
3277 self.assertPathRelations(
3278 tree.basis_tree(), tree,
3279 [('', ''), ('a', 'a'), ('b/', 'b')])
3280+=======
3281+ self.assertPathRelations(
3282+ tree.basis_tree(), tree,
3283+ [('', ''), ('a', 'a'), ('b/', 'b/')])
3284+>>>>>>> MERGE-SOURCE
3285 # Passing after=True should work as well
3286+<<<<<<< TREE
3287 self.assertEqual([('a', 'b/a')], tree.move(['a'], 'b', after=True))
3288 self.assertPathRelations(
3289 tree.basis_tree(), tree,
3290 [('', ''), ('b/', 'b'), ('b/a', 'a')])
3291+=======
3292+ self.assertEqual([('a', 'b/a')], tree.move(['a'], 'b', after=True))
3293+ self.assertPathRelations(
3294+ tree.basis_tree(), tree,
3295+ [('', ''), ('b/', 'b/'), ('b/a', 'a')])
3296+>>>>>>> MERGE-SOURCE
3297 tree._validate()
3298
3299 def test_move_after_no_target(self):
3300@@ -303,9 +375,15 @@
3301 # But you can pass after=True
3302 self.assertEqual([('a', 'b/a')],
3303 tree.move(['a'], 'b', after=True))
3304+<<<<<<< TREE
3305 self.assertPathRelations(
3306 tree.basis_tree(), tree,
3307 [('', ''), ('b/', 'b'), ('b/a', 'a')])
3308+=======
3309+ self.assertPathRelations(
3310+ tree.basis_tree(), tree,
3311+ [('', ''), ('b/', 'b/'), ('b/a', 'a')])
3312+>>>>>>> MERGE-SOURCE
3313 # But it shouldn't actually move anything
3314 self.assertFileEqual(a_text, 'a')
3315 self.assertFileEqual(ba_text, 'b/a')
3316@@ -317,11 +395,19 @@
3317 tree.add(['a', 'a/b', 'a/c', 'a/c/d', 'e'])
3318 tree.commit('initial')
3319
3320+<<<<<<< TREE
3321 self.assertEqual([('a', 'e/a')], tree.move(['a'], 'e'))
3322 self.assertPathRelations(
3323 tree.basis_tree(), tree,
3324 [('', ''), ('e/', 'e'), ('e/a/', 'a'), ('e/a/b', 'a/b'),
3325 ('e/a/c/', 'a/c'), ('e/a/c/d', 'a/c/d')])
3326+=======
3327+ self.assertEqual([('a', 'e/a')], tree.move(['a'], 'e'))
3328+ self.assertPathRelations(
3329+ tree.basis_tree(), tree,
3330+ [('', ''), ('e/', 'e/'), ('e/a/', 'a/'), ('e/a/b', 'a/b'),
3331+ ('e/a/c/', 'a/c/'), ('e/a/c/d', 'a/c/d')])
3332+>>>>>>> MERGE-SOURCE
3333 tree._validate()
3334
3335 def test_move_directory_into_parent(self):
3336@@ -335,12 +421,21 @@
3337
3338 self.assertEqual([('c/b', 'b')],
3339 tree.move(['c/b'], ''))
3340+<<<<<<< TREE
3341 self.assertPathRelations(
3342 tree.basis_tree(), tree,
3343 [('', ''),
3344 ('b/', 'c/b'),
3345 ('c/', 'c'),
3346 ('b/d/', 'c/b/d')])
3347+=======
3348+ self.assertPathRelations(
3349+ tree.basis_tree(), tree,
3350+ [('', ''),
3351+ ('b/', 'c/b/'),
3352+ ('c/', 'c/'),
3353+ ('b/d/', 'c/b/d/')])
3354+>>>>>>> MERGE-SOURCE
3355 tree._validate()
3356
3357 def test_move_directory_with_children_in_subdir(self):
3358@@ -350,6 +445,7 @@
3359 tree.commit('initial')
3360
3361 tree.rename_one('a/b', 'a/c/b')
3362+<<<<<<< TREE
3363 self.assertPathRelations(
3364 tree.basis_tree(), tree,
3365 [('', ''),
3366@@ -358,8 +454,19 @@
3367 ('a/c/', 'a/c'),
3368 ('a/c/b', 'a/b'),
3369 ])
3370+=======
3371+ self.assertPathRelations(
3372+ tree.basis_tree(), tree,
3373+ [('', ''),
3374+ ('a/', 'a/'),
3375+ ('d/', 'd/'),
3376+ ('a/c/', 'a/c/'),
3377+ ('a/c/b', 'a/b'),
3378+ ])
3379+>>>>>>> MERGE-SOURCE
3380 self.assertEqual([('a', 'd/a')],
3381 tree.move(['a'], 'd'))
3382+<<<<<<< TREE
3383 self.assertPathRelations(
3384 tree.basis_tree(), tree,
3385 [('', ''),
3386@@ -368,6 +475,16 @@
3387 ('d/a/c/', 'a/c'),
3388 ('d/a/c/b', 'a/b'),
3389 ])
3390+=======
3391+ self.assertPathRelations(
3392+ tree.basis_tree(), tree,
3393+ [('', ''),
3394+ ('d/', 'd/'),
3395+ ('d/a/', 'a/'),
3396+ ('d/a/c/', 'a/c/'),
3397+ ('d/a/c/b', 'a/b'),
3398+ ])
3399+>>>>>>> MERGE-SOURCE
3400 tree._validate()
3401
3402 def test_move_directory_with_deleted_children(self):
3403@@ -380,12 +497,21 @@
3404
3405 self.assertEqual([('a', 'b/a')],
3406 tree.move(['a'], 'b'))
3407+<<<<<<< TREE
3408 self.assertPathRelations(
3409 tree.basis_tree(), tree,
3410 [('', ''),
3411 ('b/', 'b'),
3412 ('b/a/', 'a'),
3413 ('b/a/c', 'a/c')])
3414+=======
3415+ self.assertPathRelations(
3416+ tree.basis_tree(), tree,
3417+ [('', ''),
3418+ ('b/', 'b/'),
3419+ ('b/a/', 'a/'),
3420+ ('b/a/c', 'a/c')])
3421+>>>>>>> MERGE-SOURCE
3422 tree._validate()
3423
3424 def test_move_directory_with_new_children(self):
3425@@ -398,6 +524,7 @@
3426 tree.add(['a/b', 'a/d'])
3427
3428 self.assertEqual([('a', 'b/a')], tree.move(['a'], 'b'))
3429+<<<<<<< TREE
3430 self.assertPathRelations(
3431 tree.basis_tree(), tree,
3432 [('', ''),
3433@@ -407,6 +534,17 @@
3434 ('b/a/c', 'a/c'),
3435 ('b/a/d', None),
3436 ])
3437+=======
3438+ self.assertPathRelations(
3439+ tree.basis_tree(), tree,
3440+ [('', ''),
3441+ ('b/', 'b/'),
3442+ ('b/a/', 'a/'),
3443+ ('b/a/b', None),
3444+ ('b/a/c', 'a/c'),
3445+ ('b/a/d', None),
3446+ ])
3447+>>>>>>> MERGE-SOURCE
3448 tree._validate()
3449
3450 def test_move_directory_with_moved_children(self):
3451@@ -417,6 +555,7 @@
3452
3453 self.assertEqual([('a/b', 'b')],
3454 tree.move(['a/b'], ''))
3455+<<<<<<< TREE
3456 self.assertPathRelations(
3457 tree.basis_tree(), tree,
3458 [('', ''),
3459@@ -426,8 +565,20 @@
3460 ('e/', 'e'),
3461 ('a/c', 'a/c'),
3462 ])
3463+=======
3464+ self.assertPathRelations(
3465+ tree.basis_tree(), tree,
3466+ [('', ''),
3467+ ('a/', 'a/'),
3468+ ('b', 'a/b'),
3469+ ('d', 'd'),
3470+ ('e/', 'e/'),
3471+ ('a/c', 'a/c'),
3472+ ])
3473+>>>>>>> MERGE-SOURCE
3474 self.assertEqual([('d', 'a/d')],
3475 tree.move(['d'], 'a'))
3476+<<<<<<< TREE
3477 self.assertPathRelations(
3478 tree.basis_tree(), tree,
3479 [('', ''),
3480@@ -437,8 +588,20 @@
3481 ('a/c', 'a/c'),
3482 ('a/d', 'd'),
3483 ])
3484+=======
3485+ self.assertPathRelations(
3486+ tree.basis_tree(), tree,
3487+ [('', ''),
3488+ ('a/', 'a/'),
3489+ ('b', 'a/b'),
3490+ ('e/', 'e/'),
3491+ ('a/c', 'a/c'),
3492+ ('a/d', 'd'),
3493+ ])
3494+>>>>>>> MERGE-SOURCE
3495 self.assertEqual([('a', 'e/a')],
3496 tree.move(['a'], 'e'))
3497+<<<<<<< TREE
3498 self.assertPathRelations(
3499 tree.basis_tree(), tree,
3500 [('', ''),
3501@@ -448,6 +611,17 @@
3502 ('e/a/c', 'a/c'),
3503 ('e/a/d', 'd'),
3504 ])
3505+=======
3506+ self.assertPathRelations(
3507+ tree.basis_tree(), tree,
3508+ [('', ''),
3509+ ('b', 'a/b'),
3510+ ('e/', 'e/'),
3511+ ('e/a/', 'a/'),
3512+ ('e/a/c', 'a/c'),
3513+ ('e/a/d', 'd'),
3514+ ])
3515+>>>>>>> MERGE-SOURCE
3516 tree._validate()
3517
3518 def test_move_directory_with_renamed_child(self):
3519@@ -457,6 +631,7 @@
3520 tree.commit('initial')
3521
3522 tree.rename_one('a/b', 'a/d')
3523+<<<<<<< TREE
3524 self.assertPathRelations(
3525 tree.basis_tree(), tree,
3526 [('', ''),
3527@@ -465,8 +640,19 @@
3528 ('a/c', 'a/c'),
3529 ('a/d', 'a/b')])
3530
3531+=======
3532+ self.assertPathRelations(
3533+ tree.basis_tree(), tree,
3534+ [('', ''),
3535+ ('a/', 'a/'),
3536+ ('d/', 'd/'),
3537+ ('a/c', 'a/c'),
3538+ ('a/d', 'a/b')])
3539+
3540+>>>>>>> MERGE-SOURCE
3541 self.assertEqual([('a', 'd/a')],
3542 tree.move(['a'], 'd'))
3543+<<<<<<< TREE
3544 self.assertPathRelations(
3545 tree.basis_tree(), tree,
3546 [('', ''),
3547@@ -474,6 +660,15 @@
3548 ('d/a/', 'a'),
3549 ('d/a/c', 'a/c'),
3550 ('d/a/d', 'a/b')])
3551+=======
3552+ self.assertPathRelations(
3553+ tree.basis_tree(), tree,
3554+ [('', ''),
3555+ ('d/', 'd/'),
3556+ ('d/a/', 'a/'),
3557+ ('d/a/c', 'a/c'),
3558+ ('d/a/d', 'a/b')])
3559+>>>>>>> MERGE-SOURCE
3560 tree._validate()
3561
3562 def test_move_directory_with_swapped_children(self):
3563@@ -485,6 +680,7 @@
3564 tree.rename_one('a/b', 'a/bb')
3565 tree.rename_one('a/d', 'a/b')
3566 tree.rename_one('a/bb', 'a/d')
3567+<<<<<<< TREE
3568 self.assertPathRelations(
3569 tree.basis_tree(), tree,
3570 [('', ''),
3571@@ -493,8 +689,19 @@
3572 ('a/b', 'a/d'),
3573 ('a/c', 'a/c'),
3574 ('a/d', 'a/b')])
3575+=======
3576+ self.assertPathRelations(
3577+ tree.basis_tree(), tree,
3578+ [('', ''),
3579+ ('a/', 'a/'),
3580+ ('e/', 'e/'),
3581+ ('a/b', 'a/d'),
3582+ ('a/c', 'a/c'),
3583+ ('a/d', 'a/b')])
3584+>>>>>>> MERGE-SOURCE
3585 self.assertEqual([('a', 'e/a')],
3586 tree.move(['a'], 'e'))
3587+<<<<<<< TREE
3588 self.assertPathRelations(
3589 tree.basis_tree(), tree,
3590 [('', ''),
3591@@ -503,6 +710,16 @@
3592 ('e/a/b', 'a/d'),
3593 ('e/a/c', 'a/c'),
3594 ('e/a/d', 'a/b')])
3595+=======
3596+ self.assertPathRelations(
3597+ tree.basis_tree(), tree,
3598+ [('', ''),
3599+ ('e/', 'e/'),
3600+ ('e/a/', 'a/'),
3601+ ('e/a/b', 'a/d'),
3602+ ('e/a/c', 'a/c'),
3603+ ('e/a/d', 'a/b')])
3604+>>>>>>> MERGE-SOURCE
3605 tree._validate()
3606
3607 def test_move_moved(self):
3608@@ -514,14 +731,27 @@
3609
3610 self.assertEqual([('a/b', 'c/b')],
3611 tree.move(['a/b'], 'c'))
3612+<<<<<<< TREE
3613 self.assertPathRelations(
3614 tree.basis_tree(), tree,
3615 [('', ''), ('a/', 'a'), ('c/', 'c'), ('c/b', 'a/b')])
3616+=======
3617+ self.assertPathRelations(
3618+ tree.basis_tree(), tree,
3619+ [('', ''), ('a/', 'a/'), ('c/', 'c/'), ('c/b', 'a/b')])
3620+>>>>>>> MERGE-SOURCE
3621
3622+<<<<<<< TREE
3623 self.assertEqual([('c/b', 'b')], tree.move(['c/b'], ''))
3624 self.assertPathRelations(
3625 tree.basis_tree(), tree,
3626 [('', ''), ('a/', 'a'), ('b', 'a/b'), ('c/', 'c')])
3627+=======
3628+ self.assertEqual([('c/b', 'b')], tree.move(['c/b'], ''))
3629+ self.assertPathRelations(
3630+ tree.basis_tree(), tree,
3631+ [('', ''), ('a/', 'a/'), ('b', 'a/b'), ('c/', 'c/')])
3632+>>>>>>> MERGE-SOURCE
3633 tree._validate()
3634
3635 def test_move_to_unversioned_non_ascii_dir(self):
3636
3637=== modified file 'breezy/tests/per_workingtree/test_nested_specifics.py'
3638--- breezy/tests/per_workingtree/test_nested_specifics.py 2018-02-16 19:38:39 +0000
3639+++ breezy/tests/per_workingtree/test_nested_specifics.py 2018-03-24 17:11:56 +0000
3640@@ -79,5 +79,5 @@
3641
3642 def test_iter_entries_by_dir_autodetects_subtree(self):
3643 tree = self.prepare_with_subtree()
3644- path, ie = next(tree.iter_entries_by_dir(['subtree-id']))
3645+ path, ie = next(tree.iter_entries_by_dir(specific_files=['subtree']))
3646 self.assertEqual('tree-reference', ie.kind)
3647
3648=== modified file 'breezy/tests/per_workingtree/test_paths2ids.py'
3649--- breezy/tests/per_workingtree/test_paths2ids.py 2018-02-03 13:39:29 +0000
3650+++ breezy/tests/per_workingtree/test_paths2ids.py 2018-03-24 17:11:56 +0000
3651@@ -22,6 +22,7 @@
3652 """
3653
3654 from breezy import errors
3655+from breezy.bzr.inventorytree import InventoryTree
3656 from breezy.tests import (
3657 features,
3658 TestNotApplicable,
3659@@ -62,16 +63,30 @@
3660
3661 def test_paths_none_result_none(self):
3662 tree = self.make_branch_and_tree('tree')
3663+ if not isinstance(tree, InventoryTree):
3664+ raise TestNotApplicable(
3665+ "test not applicable on non-inventory tests")
3666+
3667 tree.lock_read()
3668 self.assertEqual(None, tree.paths2ids(None))
3669 tree.unlock()
3670
3671 def test_find_single_root(self):
3672 tree = self.make_branch_and_tree('tree')
3673+ if not isinstance(tree, InventoryTree):
3674+ raise TestNotApplicable(
3675+ "test not applicable on non-inventory tests")
3676+
3677+
3678 self.assertExpectedIds([tree.path2id('')], tree, [''])
3679
3680 def test_find_tree_and_clone_roots(self):
3681 tree = self.make_branch_and_tree('tree')
3682+ if not isinstance(tree, InventoryTree):
3683+ raise TestNotApplicable(
3684+ "test not applicable on non-inventory tests")
3685+
3686+
3687 clone = tree.controldir.clone('clone').open_workingtree()
3688 clone.lock_tree_write()
3689 clone_root_id = 'new-id'
3690@@ -136,6 +151,11 @@
3691 new-child because its under dir in new.
3692 """
3693 tree = self.make_branch_and_tree('tree')
3694+ if not isinstance(tree, InventoryTree):
3695+ raise TestNotApplicable(
3696+ "test not applicable on non-inventory tests")
3697+
3698+
3699 self.build_tree(
3700 ['tree/dir/', 'tree/dir/child-moves', 'tree/dir/child-stays',
3701 'tree/dir/child-goes'])
3702@@ -161,6 +181,11 @@
3703
3704 def test_unversioned_one_tree(self):
3705 tree = self.make_branch_and_tree('tree')
3706+ if not isinstance(tree, InventoryTree):
3707+ raise TestNotApplicable(
3708+ "test not applicable on non-inventory tests")
3709+
3710+
3711 self.build_tree(['tree/unversioned'])
3712 self.assertExpectedIds([], tree, ['unversioned'], require_versioned=False)
3713 tree.lock_read()
3714@@ -172,6 +197,10 @@
3715 # should not raise an error: it must be unversioned in *all* trees to
3716 # error.
3717 tree = self.make_branch_and_tree('tree')
3718+ if not isinstance(tree, InventoryTree):
3719+ raise TestNotApplicable(
3720+ "test not applicable on non-inventory tests")
3721+
3722 if not tree.supports_setting_file_ids():
3723 raise TestNotApplicable('tree does not support setting file ids')
3724 tree.commit('make basis')
3725@@ -185,6 +214,10 @@
3726 # should not raise an error: it must be unversioned in *all* trees to
3727 # error.
3728 tree = self.make_branch_and_tree('tree')
3729+ if not isinstance(tree, InventoryTree):
3730+ raise TestNotApplicable(
3731+ "test not applicable on non-inventory tests")
3732+
3733 tree.commit('make basis')
3734 basis = tree.basis_tree()
3735 self.assertExpectedIds([], tree, ['unversioned'], [basis],
3736@@ -201,6 +234,10 @@
3737 def test_unversioned_non_ascii_one_tree(self):
3738 self.requireFeature(features.UnicodeFilenameFeature)
3739 tree = self.make_branch_and_tree('.')
3740+ if not isinstance(tree, InventoryTree):
3741+ raise TestNotApplicable(
3742+ "test not applicable on non-inventory tests")
3743+
3744 self.build_tree([u"\xa7"])
3745 self.assertExpectedIds([], tree, [u"\xa7"], require_versioned=False)
3746 self.addCleanup(tree.lock_read().unlock)
3747
3748=== modified file 'breezy/tests/per_workingtree/test_pull.py'
3749--- breezy/tests/per_workingtree/test_pull.py 2018-01-12 08:52:43 +0000
3750+++ breezy/tests/per_workingtree/test_pull.py 2018-03-24 17:11:56 +0000
3751@@ -103,7 +103,7 @@
3752 trunk = self.make_branch_deleting_dir('trunk')
3753 work = trunk.controldir.sprout('work', revision_id='2').open_workingtree()
3754 work.branch.get_config_stack().set(
3755- 'bzr.transform.orphan_policy', 'move')
3756+ 'transform.orphan_policy', 'move')
3757 # Add some unversioned files in dir
3758 self.build_tree(['work/dir/foo',
3759 'work/dir/subdir/',
3760
3761=== modified file 'breezy/tests/per_workingtree/test_rename_one.py'
3762--- breezy/tests/per_workingtree/test_rename_one.py 2018-03-12 05:18:13 +0000
3763+++ breezy/tests/per_workingtree/test_rename_one.py 2018-03-24 17:11:56 +0000
3764@@ -82,9 +82,15 @@
3765
3766 a_contents = tree.get_file_text('a')
3767 tree.rename_one('a', 'foo')
3768+<<<<<<< TREE
3769 self.assertPathRelations(
3770 tree.basis_tree(), tree,
3771 [('', ''), ('b/', 'b'), ('foo', 'a')])
3772+=======
3773+ self.assertPathRelations(
3774+ tree.basis_tree(), tree,
3775+ [('', ''), ('b/', 'b/'), ('foo', 'a')])
3776+>>>>>>> MERGE-SOURCE
3777 self.assertPathDoesNotExist('a')
3778 self.assertFileEqual(a_contents, 'foo')
3779
3780@@ -96,9 +102,15 @@
3781
3782 a_contents = tree.get_file_text('a')
3783 tree.rename_one('a', 'b/foo')
3784+<<<<<<< TREE
3785 self.assertPathRelations(
3786 tree.basis_tree(), tree,
3787 [('', ''), ('b/', 'b'), ('b/foo', 'a')])
3788+=======
3789+ self.assertPathRelations(
3790+ tree.basis_tree(), tree,
3791+ [('', ''), ('b/', 'b/'), ('b/foo', 'a')])
3792+>>>>>>> MERGE-SOURCE
3793 self.assertPathDoesNotExist('tree/a')
3794 self.assertFileEqual(a_contents, 'tree/b/foo')
3795
3796@@ -107,14 +119,27 @@
3797 self.build_tree(['a', 'b/', 'b/c'])
3798 tree.add(['a', 'b', 'b/c'])
3799 tree.commit('initial')
3800+<<<<<<< TREE
3801 self.assertPathRelations(
3802 tree.basis_tree(), tree,
3803 [('', ''), ('a', 'a'), ('b/', 'b'), ('b/c', 'b/c')])
3804 a_contents = tree.get_file_text('a')
3805+=======
3806+ self.assertPathRelations(
3807+ tree.basis_tree(), tree,
3808+ [('', ''), ('a', 'a'), ('b/', 'b/'), ('b/c', 'b/c')])
3809+ a_contents = tree.get_file_text('a')
3810+>>>>>>> MERGE-SOURCE
3811 tree.rename_one('a', 'b/d')
3812+<<<<<<< TREE
3813 self.assertPathRelations(
3814 tree.basis_tree(), tree,
3815 [('', ''), ('b/', 'b'), ('b/c', 'b/c'), ('b/d', 'a')])
3816+=======
3817+ self.assertPathRelations(
3818+ tree.basis_tree(), tree,
3819+ [('', ''), ('b/', 'b/'), ('b/c', 'b/c'), ('b/d', 'a')])
3820+>>>>>>> MERGE-SOURCE
3821 self.assertPathDoesNotExist('a')
3822 self.assertFileEqual(a_contents, 'b/d')
3823
3824@@ -125,9 +150,15 @@
3825 tree.commit('initial')
3826 c_contents = tree.get_file_text('b/c')
3827 tree.rename_one('b/c', 'd')
3828+<<<<<<< TREE
3829 self.assertPathRelations(
3830 tree.basis_tree(), tree,
3831 [('', ''), ('a', 'a'), ('b/', 'b'), ('d', 'b/c')])
3832+=======
3833+ self.assertPathRelations(
3834+ tree.basis_tree(), tree,
3835+ [('', ''), ('a', 'a'), ('b/', 'b/'), ('d', 'b/c')])
3836+>>>>>>> MERGE-SOURCE
3837 self.assertPathDoesNotExist('b/c')
3838 self.assertFileEqual(c_contents, 'd')
3839
3840@@ -139,9 +170,15 @@
3841 # Target already exists
3842 self.assertRaises(errors.RenameFailedFilesExist,
3843 tree.rename_one, 'a', 'b/a')
3844+<<<<<<< TREE
3845 self.assertPathRelations(
3846 tree.basis_tree(), tree,
3847 [('', ''), ('a', 'a'), ('b/', 'b'), ('c', 'c')])
3848+=======
3849+ self.assertPathRelations(
3850+ tree.basis_tree(), tree,
3851+ [('', ''), ('a', 'a'), ('b/', 'b/'), ('c', 'c')])
3852+>>>>>>> MERGE-SOURCE
3853
3854 def test_rename_one_onto_existing(self):
3855 tree = self.make_branch_and_tree('.')
3856@@ -177,16 +214,29 @@
3857 tree.commit('initial')
3858 os.rename('a', 'b/foo')
3859
3860+<<<<<<< TREE
3861 self.assertPathRelations(
3862 tree.basis_tree(), tree,
3863 [('', ''), ('a', 'a'), ('b/', 'b')])
3864
3865+=======
3866+ self.assertPathRelations(
3867+ tree.basis_tree(), tree,
3868+ [('', ''), ('a', 'a'), ('b/', 'b/')])
3869+
3870+>>>>>>> MERGE-SOURCE
3871 # We don't need after=True as long as source is missing and target
3872 # exists.
3873 tree.rename_one('a', 'b/foo')
3874+<<<<<<< TREE
3875 self.assertPathRelations(
3876 tree.basis_tree(), tree,
3877 [('', ''), ('b/', 'b'), ('b/foo', 'a')])
3878+=======
3879+ self.assertPathRelations(
3880+ tree.basis_tree(), tree,
3881+ [('', ''), ('b/', 'b/'), ('b/foo', 'a')])
3882+>>>>>>> MERGE-SOURCE
3883
3884 def test_rename_one_after_with_after(self):
3885 tree = self.make_branch_and_tree('.')
3886@@ -196,16 +246,26 @@
3887 os.rename('a', 'b/foo')
3888
3889 if tree.has_versioned_directories():
3890+<<<<<<< TREE
3891 self.assertPathRelations(tree.basis_tree(), tree,
3892 [('', ''), ('a', 'a'), ('b/', 'b')])
3893+=======
3894+ self.assertPathRelations(tree.basis_tree(), tree,
3895+ [('', ''), ('a', 'a'), ('b/', 'b/')])
3896+>>>>>>> MERGE-SOURCE
3897 else:
3898 self.assertPathRelations(tree.basis_tree(), tree,
3899 [('', ''), ('a', 'a')])
3900
3901 # Passing after=True should work as well
3902 tree.rename_one('a', 'b/foo', after=True)
3903+<<<<<<< TREE
3904 self.assertPathRelations(tree.basis_tree(), tree,
3905 [('', ''), ('b/', 'b'), ('b/foo', 'a')])
3906+=======
3907+ self.assertPathRelations(tree.basis_tree(), tree,
3908+ [('', ''), ('b/', 'b/'), ('b/foo', 'a')])
3909+>>>>>>> MERGE-SOURCE
3910
3911 def test_rename_one_after_dest_versioned(self):
3912 tree = self.make_branch_and_tree('.')
3913@@ -266,16 +326,29 @@
3914 os.rename('a', 'b/foo')
3915 tree.remove(['a'])
3916
3917+<<<<<<< TREE
3918 self.assertPathRelations(
3919 tree.basis_tree(), tree,
3920 [('', ''), ('b/', 'b')])
3921
3922+=======
3923+ self.assertPathRelations(
3924+ tree.basis_tree(), tree,
3925+ [('', ''), ('b/', 'b/')])
3926+
3927+>>>>>>> MERGE-SOURCE
3928 # We don't need after=True as long as source is missing and target
3929 # exists.
3930 tree.rename_one('a', 'b/foo')
3931+<<<<<<< TREE
3932 self.assertPathRelations(
3933 tree.basis_tree(), tree,
3934 [('', ''), ('b/', 'b'), ('b/foo', 'a')])
3935+=======
3936+ self.assertPathRelations(
3937+ tree.basis_tree(), tree,
3938+ [('', ''), ('b/', 'b/'), ('b/foo', 'a')])
3939+>>>>>>> MERGE-SOURCE
3940
3941 def test_rename_one_after_no_target(self):
3942 tree = self.make_branch_and_tree('.')
3943@@ -287,9 +360,15 @@
3944 # exception
3945 self.assertRaises(errors.BzrMoveFailedError,
3946 tree.rename_one, 'a', 'b/foo', after=True)
3947+<<<<<<< TREE
3948 self.assertPathRelations(
3949 tree.basis_tree(), tree,
3950 [('', ''), ('a', 'a'), ('b/', 'b')])
3951+=======
3952+ self.assertPathRelations(
3953+ tree.basis_tree(), tree,
3954+ [('', ''), ('a', 'a'), ('b/', 'b/')])
3955+>>>>>>> MERGE-SOURCE
3956
3957 def test_rename_one_after_source_and_dest(self):
3958 tree = self.make_branch_and_tree('.')
3959@@ -304,21 +383,39 @@
3960 with open('b/foo', 'r') as foo_file:
3961 foo_text = foo_file.read()
3962
3963+<<<<<<< TREE
3964 self.assertPathRelations(
3965 tree.basis_tree(), tree,
3966 [('', ''), ('a', 'a'), ('b/', 'b')])
3967+=======
3968+ self.assertPathRelations(
3969+ tree.basis_tree(), tree,
3970+ [('', ''), ('a', 'a'), ('b/', 'b/')])
3971+>>>>>>> MERGE-SOURCE
3972 self.assertRaises(errors.RenameFailedFilesExist,
3973 tree.rename_one, 'a', 'b/foo', after=False)
3974+<<<<<<< TREE
3975 self.assertPathRelations(
3976 tree.basis_tree(), tree,
3977 [('', ''), ('a', 'a'), ('b/', 'b')])
3978+=======
3979+ self.assertPathRelations(
3980+ tree.basis_tree(), tree,
3981+ [('', ''), ('a', 'a'), ('b/', 'b/')])
3982+>>>>>>> MERGE-SOURCE
3983 self.assertFileEqual(a_text, 'a')
3984 self.assertFileEqual(foo_text, 'b/foo')
3985 # But you can pass after=True
3986 tree.rename_one('a', 'b/foo', after=True)
3987+<<<<<<< TREE
3988 self.assertPathRelations(
3989 tree.basis_tree(), tree,
3990 [('', ''), ('b/', 'b'), ('b/foo', 'a')])
3991+=======
3992+ self.assertPathRelations(
3993+ tree.basis_tree(), tree,
3994+ [('', ''), ('b/', 'b/'), ('b/foo', 'a')])
3995+>>>>>>> MERGE-SOURCE
3996 # But it shouldn't actually move anything
3997 self.assertFileEqual(a_text, 'a')
3998 self.assertFileEqual(foo_text, 'b/foo')
3999@@ -330,11 +427,19 @@
4000 tree.commit('initial')
4001
4002 tree.rename_one('a', 'e/f')
4003+<<<<<<< TREE
4004 self.assertPathRelations(
4005 tree.basis_tree(), tree,
4006 [('', ''), ('e/', 'e'), ('e/f/', 'a'),
4007 ('e/f/b', 'a/b'), ('e/f/c/', 'a/c'),
4008 ('e/f/c/d', 'a/c/d')])
4009+=======
4010+ self.assertPathRelations(
4011+ tree.basis_tree(), tree,
4012+ [('', ''), ('e/', 'e/'), ('e/f/', 'a/'),
4013+ ('e/f/b', 'a/b'), ('e/f/c/', 'a/c/'),
4014+ ('e/f/c/d', 'a/c/d')])
4015+>>>>>>> MERGE-SOURCE
4016
4017 def test_rename_one_moved(self):
4018 """Moving a moved entry works as expected."""
4019@@ -345,14 +450,26 @@
4020 root_id = tree.get_root_id()
4021
4022 tree.rename_one('a/b', 'c/foo')
4023+<<<<<<< TREE
4024 self.assertPathRelations(
4025 tree.basis_tree(), tree,
4026 [('', ''), ('a/', 'a'), ('c/', 'c'), ('c/foo', 'a/b')])
4027+=======
4028+ self.assertPathRelations(
4029+ tree.basis_tree(), tree,
4030+ [('', ''), ('a/', 'a/'), ('c/', 'c/'), ('c/foo', 'a/b')])
4031+>>>>>>> MERGE-SOURCE
4032
4033 tree.rename_one('c/foo', 'bar')
4034+<<<<<<< TREE
4035 self.assertPathRelations(
4036 tree.basis_tree(), tree,
4037 [('', ''), ('a/', 'a'), ('bar', 'a/b'), ('c/', 'c')])
4038+=======
4039+ self.assertPathRelations(
4040+ tree.basis_tree(), tree,
4041+ [('', ''), ('a/', 'a/'), ('bar', 'a/b'), ('c/', 'c/')])
4042+>>>>>>> MERGE-SOURCE
4043
4044 def test_rename_to_denormalised_fails(self):
4045 if osutils.normalizes_filenames():
4046
4047=== modified file 'breezy/tests/per_workingtree/test_revision_tree.py'
4048--- breezy/tests/per_workingtree/test_revision_tree.py 2018-03-02 16:32:39 +0000
4049+++ breezy/tests/per_workingtree/test_revision_tree.py 2018-03-24 17:11:56 +0000
4050@@ -123,7 +123,7 @@
4051 basis = tree.revision_tree(parents[0])
4052 basis.lock_read()
4053 self.addCleanup(basis.unlock)
4054- self.assertRaises(errors.NoSuchId, basis.kind, 'a')
4055+ self.assertRaises(errors.NoSuchFile, basis.kind, 'a')
4056 self.assertEqual(['directory', 'file'],
4057 [basis.kind('b'), basis.kind('b/c')])
4058 try:
4059@@ -134,6 +134,6 @@
4060 % type(tree))
4061 other.lock_read()
4062 self.addCleanup(other.unlock)
4063- self.assertRaises(errors.NoSuchId, other.kind, 'b')
4064- self.assertRaises(errors.NoSuchId, other.kind, 'c')
4065+ self.assertRaises(errors.NoSuchFile, other.kind, 'b')
4066+ self.assertRaises(errors.NoSuchFile, other.kind, 'c')
4067 self.assertEqual('file', other.kind('a'))
4068
4069=== modified file 'breezy/tests/per_workingtree/test_workingtree.py'
4070--- breezy/tests/per_workingtree/test_workingtree.py 2018-03-09 00:05:39 +0000
4071+++ breezy/tests/per_workingtree/test_workingtree.py 2018-03-24 17:11:56 +0000
4072@@ -711,17 +711,17 @@
4073 with tree.lock_write():
4074 tree.add(['somefile'])
4075 d = {tree.path2id('somefile'): osutils.sha_string('hello')}
4076- try:
4077+ if tree.supports_merge_modified():
4078 tree.set_merge_modified(d)
4079- except errors.UnsupportedOperation:
4080+ mm = tree.merge_modified()
4081+ self.assertEqual(mm, d)
4082+ else:
4083+ self.assertRaises(
4084+ errors.UnsupportedOperation,
4085+ tree.set_merge_modified, d)
4086 mm = tree.merge_modified()
4087 self.assertEqual(mm, {})
4088- supports_merge_modified = False
4089- else:
4090- mm = tree.merge_modified()
4091- self.assertEqual(mm, d)
4092- supports_merge_modified = True
4093- if supports_merge_modified:
4094+ if tree.supports_merge_modified():
4095 mm = tree.merge_modified()
4096 self.assertEqual(mm, d)
4097 else:
4098
4099=== modified file 'breezy/tests/test_bundle.py'
4100--- breezy/tests/test_bundle.py 2018-02-15 19:38:33 +0000
4101+++ breezy/tests/test_bundle.py 2018-03-24 17:11:56 +0000
4102@@ -663,7 +663,7 @@
4103 , 'sub/sub'
4104 ])
4105 tt = TreeTransform(self.tree1)
4106- trans_id = tt.trans_id_tree_file_id('exe-1')
4107+ trans_id = tt.trans_id_tree_path('executable')
4108 tt.set_executability(False, trans_id)
4109 tt.apply()
4110 self.tree1.commit('removed', rev_id='a@cset-0-3')
4111@@ -731,7 +731,7 @@
4112 self.assertEqual(link_target, bund_tree.get_symlink_target(link_name))
4113
4114 tt = TreeTransform(self.tree1)
4115- trans_id = tt.trans_id_tree_file_id(link_id)
4116+ trans_id = tt.trans_id_tree_path(link_name)
4117 tt.adjust_path('link2', tt.root, trans_id)
4118 tt.delete_contents(trans_id)
4119 tt.create_symlink(new_link_target, trans_id)
4120@@ -745,7 +745,7 @@
4121 bund_tree.get_symlink_target('link2'))
4122
4123 tt = TreeTransform(self.tree1)
4124- trans_id = tt.trans_id_tree_file_id(link_id)
4125+ trans_id = tt.trans_id_tree_path('link2')
4126 tt.delete_contents(trans_id)
4127 tt.create_symlink('jupiter', trans_id)
4128 tt.apply()
4129@@ -753,7 +753,7 @@
4130 bundle = self.get_valid_bundle('l@cset-0-2', 'l@cset-0-3')
4131
4132 tt = TreeTransform(self.tree1)
4133- trans_id = tt.trans_id_tree_file_id(link_id)
4134+ trans_id = tt.trans_id_tree_path('link2')
4135 tt.delete_contents(trans_id)
4136 tt.apply()
4137 self.tree1.commit('Delete symlink', rev_id='l@cset-0-4')
4138@@ -783,7 +783,7 @@
4139
4140 # Delete
4141 tt = TreeTransform(self.tree1)
4142- trans_id = tt.trans_id_tree_file_id('binary-1')
4143+ trans_id = tt.trans_id_tree_path('file')
4144 tt.delete_contents(trans_id)
4145 tt.apply()
4146 self.tree1.commit('delete binary', rev_id='b@cset-0-2')
4147@@ -791,7 +791,7 @@
4148
4149 # Rename & modify
4150 tt = TreeTransform(self.tree1)
4151- trans_id = tt.trans_id_tree_file_id('binary-2')
4152+ trans_id = tt.trans_id_tree_path('file2')
4153 tt.adjust_path('file3', tt.root, trans_id)
4154 tt.delete_contents(trans_id)
4155 tt.create_file('file\rcontents\x00\n\x00', trans_id)
4156@@ -801,7 +801,7 @@
4157
4158 # Modify
4159 tt = TreeTransform(self.tree1)
4160- trans_id = tt.trans_id_tree_file_id('binary-2')
4161+ trans_id = tt.trans_id_tree_path('file3')
4162 tt.delete_contents(trans_id)
4163 tt.create_file('\x00file\rcontents', trans_id)
4164 tt.apply()
4165@@ -820,7 +820,7 @@
4166 self.tree1.commit('create file', rev_id='a@lmod-0-1')
4167
4168 tt = TreeTransform(self.tree1)
4169- trans_id = tt.trans_id_tree_file_id('file')
4170+ trans_id = tt.trans_id_tree_path('file')
4171 tt.delete_contents(trans_id)
4172 tt.create_file('file2', trans_id)
4173 tt.apply()
4174@@ -828,7 +828,7 @@
4175
4176 other = self.get_checkout('a@lmod-0-1')
4177 tt = TreeTransform(other)
4178- trans_id = tt.trans_id_tree_file_id('file')
4179+ trans_id = tt.trans_id_tree_path('file2')
4180 tt.delete_contents(trans_id)
4181 tt.create_file('file2', trans_id)
4182 tt.apply()
4183
4184=== modified file 'breezy/tests/test_bzrdir.py'
4185--- breezy/tests/test_bzrdir.py 2017-11-12 20:07:32 +0000
4186+++ breezy/tests/test_bzrdir.py 2018-03-24 17:11:56 +0000
4187@@ -864,7 +864,7 @@
4188 tree.commit('Initial commit')
4189 # The following line force the orhaning to reveal bug #634470
4190 tree.branch.get_config_stack().set(
4191- 'bzr.transform.orphan_policy', 'move')
4192+ 'transform.orphan_policy', 'move')
4193 tree.controldir.destroy_workingtree()
4194 # FIXME: subtree/.bzr is left here which allows the test to pass (or
4195 # fail :-( ) -- vila 20100909
4196
4197=== modified file 'breezy/tests/test_matchers.py'
4198--- breezy/tests/test_matchers.py 2018-03-12 02:24:39 +0000
4199+++ breezy/tests/test_matchers.py 2018-03-24 17:11:56 +0000
4200@@ -151,6 +151,7 @@
4201 set(mismatch.describe().split(" != ")))
4202
4203
4204+<<<<<<< TREE
4205 class TestHasPathRelations(TestCaseWithTransport):
4206
4207 def test__str__(self):
4208@@ -176,6 +177,33 @@
4209 self.assertIsNot(None, mismatch)
4210
4211
4212+=======
4213+class TestHasPathRelations(TestCaseWithTransport):
4214+
4215+ def test__str__(self):
4216+ t = self.make_branch_and_tree('.')
4217+ matcher = HasPathRelations(t, [("a", "b")])
4218+ self.assertEqual("HasPathRelations(%r, [('a', 'b')])" % t, str(matcher))
4219+
4220+ def test_match(self):
4221+ t = self.make_branch_and_tree('.')
4222+ self.build_tree(['a', 'b/', 'b/c'])
4223+ t.add(['a', 'b', 'b/c'])
4224+ self.assertThat(t, HasPathRelations(t,
4225+ [('', ''),
4226+ ('a', 'a'),
4227+ ('b/', 'b/'),
4228+ ('b/c', 'b/c')]))
4229+
4230+ def test_mismatch(self):
4231+ t = self.make_branch_and_tree('.')
4232+ self.build_tree(['a', 'b/', 'b/c'])
4233+ t.add(['a', 'b', 'b/c'])
4234+ mismatch = HasPathRelations(t, [('a', 'a')]).match(t)
4235+ self.assertIsNot(None, mismatch)
4236+
4237+
4238+>>>>>>> MERGE-SOURCE
4239 class TestContainsNoVfsCalls(TestCase):
4240
4241 def _make_call(self, method, args):
4242
4243=== modified file 'breezy/tests/test_merge.py'
4244--- breezy/tests/test_merge.py 2018-02-16 19:38:39 +0000
4245+++ breezy/tests/test_merge.py 2018-03-24 17:11:56 +0000
4246@@ -1265,8 +1265,7 @@
4247 builder.build_snapshot(['B-id', 'C-id'], [], revision_id='D-id')
4248 return builder
4249
4250- def make_Merger(self, builder, other_revision_id,
4251- interesting_files=None, interesting_ids=None):
4252+ def make_Merger(self, builder, other_revision_id, interesting_files=None):
4253 """Make a Merger object from a branch builder"""
4254 mem_tree = memorytree.MemoryTree.create_on_branch(builder.get_branch())
4255 mem_tree.lock_write()
4256@@ -1274,8 +1273,6 @@
4257 merger = _mod_merge.Merger.from_revision_ids(
4258 mem_tree, other_revision_id)
4259 merger.set_interesting_files(interesting_files)
4260- # It seems there is no matching function for set_interesting_ids
4261- merger.interesting_ids = interesting_ids
4262 merger.merge_type = _mod_merge.Merge3Merger
4263 return merger
4264
4265@@ -1400,10 +1397,9 @@
4266 class TestMergerEntriesLCA(TestMergerBase):
4267
4268 def make_merge_obj(self, builder, other_revision_id,
4269- interesting_files=None, interesting_ids=None):
4270+ interesting_files=None):
4271 merger = self.make_Merger(builder, other_revision_id,
4272- interesting_files=interesting_files,
4273- interesting_ids=interesting_ids)
4274+ interesting_files=interesting_files)
4275 return merger.make_merger()
4276
4277 def test_simple(self):
4278@@ -1435,6 +1431,7 @@
4279 # BASE, lca1, lca2, OTHER, THIS
4280 root_id = 'a-root-id'
4281 self.assertEqual([('a-id', True,
4282+ ((u'a', [u'a', u'a']), u'a', u'a'),
4283 ((root_id, [root_id, root_id]), root_id, root_id),
4284 ((u'a', [u'a', u'a']), u'a', u'a'),
4285 ((False, [False, False]), False, False)),
4286@@ -1480,6 +1477,7 @@
4287 entries = list(merge_obj._entries_lca())
4288 root_id = 'a-root-id'
4289 self.assertEqual([('bar-id', True,
4290+ ((None, [u'bar', u'bar']), u'bar', u'bar'),
4291 ((None, [root_id, root_id]), root_id, root_id),
4292 ((None, [u'bar', u'bar']), u'bar', u'bar'),
4293 ((None, [False, False]), False, False)),
4294@@ -1512,6 +1510,7 @@
4295 entries = list(merge_obj._entries_lca())
4296 root_id = 'a-root-id'
4297 self.assertEqual([('a-id', True,
4298+ ((u'a', [u'a', u'a']), u'a', None),
4299 ((root_id, [root_id, root_id]), root_id, None),
4300 ((u'a', [u'a', u'a']), u'a', None),
4301 ((False, [False, False]), False, None)),
4302@@ -1562,6 +1561,7 @@
4303 entries = list(merge_obj._entries_lca())
4304 root_id = 'a-root-id'
4305 self.assertEqual([('a-id', True,
4306+ ((u'a', [u'a', u'a']), None, u'a'),
4307 ((root_id, [root_id, root_id]), None, root_id),
4308 ((u'a', [u'a', u'a']), None, u'a'),
4309 ((False, [False, False]), None, False)),
4310@@ -1627,6 +1627,7 @@
4311 entries = list(merge_obj._entries_lca())
4312 root_id = 'a-root-id'
4313 self.assertEqual([('foo-id', True,
4314+ ((u'foo', [u'foo', None]), None, u'foo'),
4315 ((root_id, [root_id, None]), None, root_id),
4316 ((u'foo', [u'foo', None]), None, 'foo'),
4317 ((False, [False, None]), None, False)),
4318@@ -1681,6 +1682,7 @@
4319 entries = list(merge_obj._entries_lca())
4320 root_id = 'a-root-id'
4321 self.assertEqual([('a-id', True,
4322+ ((None, [None, None]), u'a', None),
4323 ((None, [None, None]), root_id, None),
4324 ((None, [None, None]), u'a', None),
4325 ((None, [None, None]), False, None)),
4326@@ -1843,6 +1845,7 @@
4327 entries = list(merge_obj._entries_lca())
4328 root_id = 'a-root-id'
4329 self.assertEqual([('foo-id', True,
4330+ ((u'foo', [u'foo', u'foo']), u'foo', u'foo'),
4331 ((root_id, [root_id, root_id]), root_id, root_id),
4332 ((u'foo', [u'foo', u'foo']), u'foo', u'foo'),
4333 ((False, [False, False]), False, False)),
4334@@ -1880,6 +1883,7 @@
4335 entries = list(merge_obj._entries_lca())
4336 root_id = 'a-root-id'
4337 self.assertEqual([('foo-id', True,
4338+ ((u'foo', [u'foo', u'foo']), u'foo', u'foo'),
4339 ((root_id, [root_id, root_id]), root_id, root_id),
4340 ((u'foo', [u'foo', u'foo']), u'foo', u'foo'),
4341 ((False, [False, False]), False, False)),
4342@@ -1941,6 +1945,7 @@
4343 root_id = 'a-root-id'
4344 # The content was not changed, only the path
4345 self.assertEqual([('a-id', False,
4346+ ((u'a', [u'b', u'b']), u'b', u'a'),
4347 ((root_id, [root_id, root_id]), root_id, root_id),
4348 ((u'a', [u'a', u'a']), u'b', u'a'),
4349 ((False, [False, False]), False, False)),
4350@@ -1966,6 +1971,7 @@
4351 root_id = 'a-root-id'
4352 # Only the kind was changed (content)
4353 self.assertEqual([('a-id', True,
4354+ ((u'a', [u'a', u'a']), u'a', u'a'),
4355 ((root_id, [root_id, root_id]), root_id, root_id),
4356 ((u'a', [u'a', u'a']), u'a', u'a'),
4357 ((False, [False, False]), False, False)),
4358@@ -2011,6 +2017,7 @@
4359 entries = list(merge_obj._entries_lca())
4360 root_id = 'a-root-id'
4361 self.assertEqual([('b-id', True,
4362+ ((u'b', [u'b', u'b']), u'b', u'b'),
4363 ((root_id, [root_id, root_id]), root_id, root_id),
4364 ((u'b', [u'b', u'b']), u'b', u'b'),
4365 ((False, [False, False]), False, False)),
4366@@ -2038,6 +2045,7 @@
4367 entries = list(merge_obj._entries_lca())
4368 root_id = 'a-root-id'
4369 self.assertEqual([('b-id', True,
4370+ ((u'b', [u'b', u'b']), u'b', u'c'),
4371 ((root_id, [root_id, root_id]), root_id, root_id),
4372 ((u'b', [u'b', u'b']), u'b', u'c'),
4373 ((False, [False, False]), False, False)),
4374@@ -2067,6 +2075,7 @@
4375 entries = list(merge_obj._entries_lca())
4376 root_id = 'a-root-id'
4377 self.assertEqual([('c-id', True,
4378+ ((u'c', [u'b', u'b']), u'b', u'b'),
4379 ((root_id, [root_id, root_id]), root_id, root_id),
4380 ((u'c', [u'b', u'b']), u'b', u'b'),
4381 ((False, [False, False]), False, False)),
4382@@ -2094,12 +2103,13 @@
4383 entries = list(merge_obj._entries_lca())
4384 root_id = 'a-root-id'
4385 self.assertEqual([('b-id', True,
4386+ ((u'b', [u'b', u'b']), u'b', u'b'),
4387 ((root_id, [root_id, root_id]), root_id, root_id),
4388 ((u'b', [u'c', u'b']), u'b', u'b'),
4389 ((False, [False, False]), False, False)),
4390 ], entries)
4391
4392- def test_interesting_ids(self):
4393+ def test_interesting_files(self):
4394 # Two files modified, but we should filter one of them
4395 builder = self.get_builder()
4396 builder.build_snapshot(None,
4397@@ -2114,10 +2124,11 @@
4398 ('modify', ('b-id', 'new-content\n'))], revision_id='E-id')
4399 builder.build_snapshot(['B-id', 'C-id'], [], revision_id='D-id')
4400 merge_obj = self.make_merge_obj(builder, 'E-id',
4401- interesting_ids=['b-id'])
4402+ interesting_files=['b'])
4403 entries = list(merge_obj._entries_lca())
4404 root_id = 'a-root-id'
4405 self.assertEqual([('b-id', True,
4406+ ((u'b', [u'b', u'b']), u'b', u'b'),
4407 ((root_id, [root_id, root_id]), root_id, root_id),
4408 ((u'b', [u'b', u'b']), u'b', u'b'),
4409 ((False, [False, False]), False, False)),
4410@@ -2253,7 +2264,7 @@
4411 wt = self.get_wt_from_builder(builder)
4412 tt = transform.TreeTransform(wt)
4413 try:
4414- tt.set_executability(True, tt.trans_id_tree_file_id('foo-id'))
4415+ tt.set_executability(True, tt.trans_id_tree_path('foo'))
4416 tt.apply()
4417 except:
4418 tt.finalize()
4419@@ -2432,6 +2443,7 @@
4420 entries = list(merge_obj._entries_lca())
4421 # No content change, just a path change
4422 self.assertEqual([('foo-id', False,
4423+ ((u'foo', [u'blah', u'blah']), u'blah', u'barry'),
4424 ((root_id, [root_id, root_id]), root_id, root_id),
4425 ((u'foo', [u'barry', u'foo']), u'blah', u'barry'),
4426 ((False, [False, False]), False, False)),
4427@@ -2536,6 +2548,7 @@
4428 entries = list(merge_obj._entries_lca())
4429 root_id = wt.path2id('')
4430 self.assertEqual([('foo-id', True,
4431+ ((None, [u'foo', None]), u'foo', u'foo'),
4432 ((None, [root_id, None]), root_id, root_id),
4433 ((None, [u'foo', None]), u'foo', u'foo'),
4434 ((None, [False, None]), False, False)),
4435@@ -2597,6 +2610,7 @@
4436 entries = list(merge_obj._entries_lca())
4437 root_id = wt.path2id('')
4438 self.assertEqual([('foo-id', True,
4439+ ((u'foo', [u'foo', u'foo']), u'foo', u'foo'),
4440 ((root_id, [root_id, root_id]), root_id, root_id),
4441 ((u'foo', [u'foo', u'foo']), u'foo', u'foo'),
4442 ((False, [False, False]), False, False)),
4443@@ -2720,10 +2734,12 @@
4444 entries = list(merge_obj._entries_lca())
4445 root_id = 'a-root-id'
4446 self.assertEqual([('a-id', False,
4447+ ((u'a', [u'c', u'c']), u'c', u'b'),
4448 ((root_id, [root_id, root_id]), root_id, root_id),
4449 ((u'a', [u'a', u'b']), u'c', u'b'),
4450 ((False, [False, False]), False, False)),
4451 ('foo-id', True,
4452+ ((u'foo', [u'foo', u'foo']), u'foo', u'foo'),
4453 ((root_id, [root_id, root_id]), root_id, root_id),
4454 ((u'foo', [u'foo', u'foo']), u'foo', u'foo'),
4455 ((False, [False, False]), False, False)),
4456@@ -2838,6 +2854,7 @@
4457 entries = list(merge_obj._entries_lca())
4458 root_id = 'a-root-id'
4459 self.assertEqual([('sub-tree-root', False,
4460+ ((u'sub', [u'alt_sub', u'alt_sub']), u'alt_sub', u'sub'),
4461 ((root_id, [root_id, root_id]), root_id, root_id),
4462 ((u'sub', [u'sub', u'sub']), u'alt_sub', u'sub'),
4463 ((False, [False, False]), False, False)),
4464@@ -2882,6 +2899,7 @@
4465 entries = list(merge_obj._entries_lca())
4466 root_id = 'a-root-id'
4467 self.assertEqual([('sub-tree-root', False,
4468+ ((u'sub', [u'alt_sub', u'alt_sub']), u'alt_sub', u'sub'),
4469 ((root_id, [root_id, root_id]), root_id, root_id),
4470 ((u'sub', [u'sub', u'sub']), u'alt_sub', u'sub'),
4471 ((False, [False, False]), False, False)),
4472
4473=== modified file 'breezy/tests/test_merge_core.py'
4474--- breezy/tests/test_merge_core.py 2018-03-09 19:52:32 +0000
4475+++ breezy/tests/test_merge_core.py 2018-03-24 17:11:56 +0000
4476@@ -77,8 +77,8 @@
4477 if option is True:
4478 new_file(tt)
4479
4480- def merge(self, merge_type=Merge3Merger, interesting_ids=None, **kwargs):
4481- merger = self.make_merger(merge_type, interesting_ids, **kwargs)
4482+ def merge(self, merge_type=Merge3Merger, interesting_files=None, **kwargs):
4483+ merger = self.make_merger(merge_type, interesting_files, **kwargs)
4484 merger.do_merge()
4485 return merger.cooked_conflicts
4486
4487@@ -86,7 +86,7 @@
4488 merger = self.make_merger(Merge3Merger, None, this_revision_tree=True)
4489 return merger.make_preview_transform()
4490
4491- def make_merger(self, merge_type, interesting_ids,
4492+ def make_merger(self, merge_type, interesting_files,
4493 this_revision_tree=False, **kwargs):
4494 self.base_tt.apply()
4495 self.base.commit('base commit')
4496@@ -110,7 +110,7 @@
4497 else:
4498 this_tree = self.this
4499 merger = merge_type(this_tree, self.this, self.base, other_basis,
4500- interesting_ids=interesting_ids, do_merge=False,
4501+ interesting_files=interesting_files, do_merge=False,
4502 this_branch=self.this.branch, **kwargs)
4503 return merger
4504
4505@@ -251,7 +251,7 @@
4506 builder.change_contents("1", other="text4")
4507 builder.add_file("2", builder.tree_root, "name2", "hello1", True)
4508 builder.change_contents("2", other="text4")
4509- builder.merge(interesting_ids=["1"])
4510+ builder.merge(interesting_files=["name1"])
4511 self.assertEqual(builder.this.get_file("name1").read(), "text4" )
4512 self.assertEqual(builder.this.get_file("name2").read(), "hello1" )
4513 builder.cleanup()
4514
4515=== modified file 'breezy/tests/test_revert.py'
4516--- breezy/tests/test_revert.py 2017-11-12 17:53:35 +0000
4517+++ breezy/tests/test_revert.py 2018-03-24 17:11:56 +0000
4518@@ -97,7 +97,7 @@
4519 def test_preserve_execute(self):
4520 tree = self.tree_with_executable()
4521 tt = transform.TreeTransform(tree)
4522- newfile = tt.trans_id_tree_file_id('newfile-id')
4523+ newfile = tt.trans_id_tree_path('newfile')
4524 tt.delete_contents(newfile)
4525 tt.create_file('Woooorld!', newfile)
4526 tt.apply()
4527@@ -112,7 +112,7 @@
4528 def test_revert_executable(self):
4529 tree = self.tree_with_executable()
4530 tt = transform.TreeTransform(tree)
4531- newfile = tt.trans_id_tree_file_id('newfile-id')
4532+ newfile = tt.trans_id_tree_path('newfile')
4533 tt.set_executability(False, newfile)
4534 tt.apply()
4535 tree.lock_write()
4536
4537=== modified file 'breezy/tests/test_shelf.py'
4538--- breezy/tests/test_shelf.py 2017-12-12 01:19:18 +0000
4539+++ breezy/tests/test_shelf.py 2018-03-24 17:11:56 +0000
4540@@ -206,7 +206,7 @@
4541
4542 def check_shelve_creation(self, creator, tree):
4543 self.assertRaises(StopIteration,
4544- next, tree.iter_entries_by_dir(['foo-id']))
4545+ next, tree.iter_entries_by_dir(specific_files=['foo']))
4546 s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
4547 self.assertEqual('foo-id',
4548 creator.shelf_transform.final_file_id(s_trans_id))
4549@@ -349,7 +349,7 @@
4550 creator.shelve_creation('foo-id')
4551 creator.transform()
4552 self.assertRaises(StopIteration,
4553- next, tree.iter_entries_by_dir(['foo-id']))
4554+ next, tree.iter_entries_by_dir(specific_files=['foo']))
4555 self.assertShelvedFileEqual('', creator, 'foo-id')
4556 s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
4557 self.assertEqual('foo-id',
4558
4559=== modified file 'breezy/tests/test_transform.py'
4560--- breezy/tests/test_transform.py 2018-03-09 19:52:32 +0000
4561+++ breezy/tests/test_transform.py 2018-03-24 17:11:56 +0000
4562@@ -453,7 +453,7 @@
4563 self.assertEqual(self.wt.path2id('name'), 'my_pretties')
4564 self.assertEqual('contents', file(self.wt.abspath('name')).read())
4565 transform2, root = self.get_transform()
4566- oz_id = transform2.trans_id_tree_file_id('oz-id')
4567+ oz_id = transform2.trans_id_tree_path('oz')
4568 newtip = transform2.new_file('tip', oz_id, 'other', 'tip-id')
4569 result = transform2.find_conflicts()
4570 fp = FinalPaths(transform2)
4571@@ -467,12 +467,12 @@
4572 transform2.finalize()
4573 transform3 = TreeTransform(self.wt)
4574 self.addCleanup(transform3.finalize)
4575- oz_id = transform3.trans_id_tree_file_id('oz-id')
4576+ oz_id = transform3.trans_id_tree_path('oz')
4577 transform3.delete_contents(oz_id)
4578 self.assertEqual(transform3.find_conflicts(),
4579 [('missing parent', oz_id)])
4580 root_id = transform3.root
4581- tip_id = transform3.trans_id_tree_file_id('tip-id')
4582+ tip_id = transform3.trans_id_tree_path('oz/tip')
4583 transform3.adjust_path('tip', root_id, tip_id)
4584 transform3.apply()
4585
4586@@ -601,7 +601,7 @@
4587 start.new_directory('a', root, 'a')
4588 start.apply()
4589 transform, root = self.get_transform()
4590- transform.delete_versioned(transform.trans_id_tree_file_id('a'))
4591+ transform.delete_versioned(transform.trans_id_tree_path('a'))
4592 transform.new_directory('a', root, 'a')
4593 transform.apply()
4594
4595@@ -616,7 +616,7 @@
4596 unversion.unversion_file(parent)
4597 self.assertEqual(unversion.find_conflicts(),
4598 [('unversioned parent', parent_id)])
4599- file_id = unversion.trans_id_tree_file_id('child-id')
4600+ file_id = unversion.trans_id_tree_path('parent/child')
4601 unversion.unversion_file(file_id)
4602 unversion.apply()
4603
4604@@ -635,23 +635,23 @@
4605 mangle_tree, root = self.get_transform()
4606 root = mangle_tree.root
4607 #swap names
4608- name1 = mangle_tree.trans_id_tree_file_id('name1')
4609- name2 = mangle_tree.trans_id_tree_file_id('name2')
4610+ name1 = mangle_tree.trans_id_tree_path('name1')
4611+ name2 = mangle_tree.trans_id_tree_path('name2')
4612 mangle_tree.adjust_path('name2', root, name1)
4613 mangle_tree.adjust_path('name1', root, name2)
4614
4615 #tests for deleting parent directories
4616- ddir = mangle_tree.trans_id_tree_file_id('ddir')
4617+ ddir = mangle_tree.trans_id_tree_path('dying_directory')
4618 mangle_tree.delete_contents(ddir)
4619- dfile = mangle_tree.trans_id_tree_file_id('dfile')
4620+ dfile = mangle_tree.trans_id_tree_path('dying_directory/dying_file')
4621 mangle_tree.delete_versioned(dfile)
4622 mangle_tree.unversion_file(dfile)
4623- mfile = mangle_tree.trans_id_tree_file_id('mfile')
4624+ mfile = mangle_tree.trans_id_tree_path('dying_directory/moving_file')
4625 mangle_tree.adjust_path('mfile', root, mfile)
4626
4627 #tests for adding parent directories
4628 newdir = mangle_tree.new_directory('new_directory', root, 'newdir')
4629- mfile2 = mangle_tree.trans_id_tree_file_id('mfile2')
4630+ mfile2 = mangle_tree.trans_id_tree_path('moving_file2')
4631 mangle_tree.adjust_path('mfile2', newdir, mfile2)
4632 mangle_tree.new_file('newfile', newdir, 'hello3', 'dfile')
4633 self.assertEqual(mangle_tree.final_file_id(mfile2), 'mfile2')
4634@@ -677,8 +677,8 @@
4635 create_tree.new_file('blackbox.py', newdir, 'hello1', 'blackbox-id')
4636 create_tree.apply()
4637 mangle_tree, root = self.get_transform()
4638- selftest = mangle_tree.trans_id_tree_file_id('selftest-id')
4639- blackbox = mangle_tree.trans_id_tree_file_id('blackbox-id')
4640+ selftest = mangle_tree.trans_id_tree_path('selftest')
4641+ blackbox = mangle_tree.trans_id_tree_path('selftest/blackbox.py')
4642 mangle_tree.adjust_path('test', root, selftest)
4643 mangle_tree.adjust_path('test_too_much', root, selftest)
4644 mangle_tree.set_executability(True, blackbox)
4645@@ -693,9 +693,9 @@
4646 'test_too_much-id')
4647 create_tree.apply()
4648 mangle_tree, root = self.get_transform()
4649- breezy = mangle_tree.trans_id_tree_file_id('breezy-id')
4650- tests = mangle_tree.trans_id_tree_file_id('tests-id')
4651- test_too_much = mangle_tree.trans_id_tree_file_id('test_too_much-id')
4652+ breezy = mangle_tree.trans_id_tree_path('breezy')
4653+ tests = mangle_tree.trans_id_tree_path('breezy/tests')
4654+ test_too_much = mangle_tree.trans_id_tree_path('breezy/tests/blackbox/test_too_much.py')
4655 mangle_tree.adjust_path('selftest', breezy, tests)
4656 mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
4657 mangle_tree.set_executability(True, test_too_much)
4658@@ -708,8 +708,8 @@
4659 'test_too_much-id')
4660 create_tree.apply()
4661 mangle_tree, root = self.get_transform()
4662- tests = mangle_tree.trans_id_tree_file_id('tests-id')
4663- test_too_much = mangle_tree.trans_id_tree_file_id('test_too_much-id')
4664+ tests = mangle_tree.trans_id_tree_path('tests')
4665+ test_too_much = mangle_tree.trans_id_tree_path('tests/test_too_much.py')
4666 mangle_tree.adjust_path('selftest', root, tests)
4667 mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
4668 mangle_tree.set_executability(True, test_too_much)
4669@@ -722,11 +722,11 @@
4670 create_tree.new_file('name1', root, 'hello1', 'name1')
4671 create_tree.apply()
4672 delete_contents, root = self.get_transform()
4673- file = delete_contents.trans_id_tree_file_id('name1')
4674+ file = delete_contents.trans_id_tree_path('name1')
4675 delete_contents.delete_contents(file)
4676 delete_contents.apply()
4677 move_id, root = self.get_transform()
4678- name1 = move_id.trans_id_tree_file_id('name1')
4679+ name1 = move_id.trans_id_tree_path('name1')
4680 newdir = move_id.new_directory('dir', root, 'newdir')
4681 move_id.adjust_path('name2', newdir, name1)
4682 move_id.apply()
4683@@ -739,7 +739,7 @@
4684 create_tree.apply()
4685 delete_contents = TreeTransform(self.wt)
4686 self.addCleanup(delete_contents.finalize)
4687- file = delete_contents.trans_id_tree_file_id('name1')
4688+ file = delete_contents.trans_id_tree_path('name1')
4689 delete_contents.delete_contents(file)
4690 delete_contents.apply()
4691 delete_contents.finalize()
4692@@ -747,7 +747,7 @@
4693 self.addCleanup(replace.finalize)
4694 name2 = replace.new_file('name2', root, 'hello2', 'name1')
4695 conflicts = replace.find_conflicts()
4696- name1 = replace.trans_id_tree_file_id('name1')
4697+ name1 = replace.trans_id_tree_path('name1')
4698 self.assertEqual(conflicts, [('duplicate id', name1, name2)])
4699 resolve_conflicts(replace)
4700 replace.apply()
4701@@ -819,11 +819,11 @@
4702 # set up duplicate entry, duplicate id
4703 new_dorothy = conflicts.new_file('dorothy', root, 'dorothy',
4704 'dorothy-id')
4705- old_dorothy = conflicts.trans_id_tree_file_id('dorothy-id')
4706- oz = conflicts.trans_id_tree_file_id('oz-id')
4707+ old_dorothy = conflicts.trans_id_tree_path('dorothy')
4708+ oz = conflicts.trans_id_tree_path('oz')
4709 # set up DeletedParent parent conflict
4710 conflicts.delete_versioned(oz)
4711- emerald = conflicts.trans_id_tree_file_id('emerald-id')
4712+ emerald = conflicts.trans_id_tree_path('oz/emeraldcity')
4713 # set up MissingParent conflict
4714 munchkincity = conflicts.trans_id_file_id('munchkincity-id')
4715 conflicts.adjust_path('munchkincity', root, munchkincity)
4716@@ -975,8 +975,8 @@
4717 create.new_directory('oz', root, 'oz-id')
4718 create.apply()
4719 cyclone, root = self.get_transform()
4720- oz = cyclone.trans_id_tree_file_id('oz-id')
4721- house = cyclone.trans_id_tree_file_id('house-id')
4722+ oz = cyclone.trans_id_tree_path('oz')
4723+ house = cyclone.trans_id_tree_path('house')
4724 cyclone.adjust_path('house', oz, house)
4725 cyclone.apply()
4726
4727@@ -1080,7 +1080,7 @@
4728 self.addCleanup(self.wt.unlock)
4729 self.assertTrue(self.wt.is_executable('file1'))
4730 transform, root = self.get_transform()
4731- file1_id = transform.trans_id_tree_file_id('file1-id')
4732+ file1_id = transform.trans_id_tree_path('file1')
4733 transform.delete_contents(file1_id)
4734 transform.create_file('contents2', file1_id)
4735 transform.apply()
4736@@ -1124,7 +1124,7 @@
4737 transform, root = self.get_transform()
4738 try:
4739 self.assertEqual([], list(transform.iter_changes()))
4740- old = transform.trans_id_tree_file_id('id-1')
4741+ old = transform.trans_id_tree_path('old')
4742 transform.unversion_file(old)
4743 self.assertEqual([('id-1', ('old', None), False, (True, False),
4744 ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
4745@@ -1162,7 +1162,7 @@
4746 transform, root = self.get_transform()
4747 try:
4748 old = transform.trans_id_tree_path('old')
4749- subdir = transform.trans_id_tree_file_id('subdir-id')
4750+ subdir = transform.trans_id_tree_path('subdir')
4751 new = transform.trans_id_tree_path('new')
4752 self.assertEqual([], list(transform.iter_changes()))
4753
4754@@ -1280,7 +1280,7 @@
4755 transform, root = self.get_transform()
4756 try:
4757 old = transform.trans_id_tree_path('old')
4758- subdir = transform.trans_id_tree_file_id('subdir-id')
4759+ subdir = transform.trans_id_tree_path('subdir')
4760 self.assertEqual([], list(transform.iter_changes()))
4761 transform.delete_contents(subdir)
4762 transform.create_directory(subdir)
4763@@ -1651,7 +1651,7 @@
4764 self.wt.set_root_id(root_id)
4765 self.b = self.wt.branch
4766 self.tt = TreeTransform(self.wt)
4767- self.root = self.tt.trans_id_tree_file_id(self.wt.get_root_id())
4768+ self.root = self.tt.trans_id_tree_path('')
4769
4770
4771 def conflict_text(tree, merge):
4772@@ -1675,7 +1675,7 @@
4773 with TransformPreview(tree) as tt:
4774 tt.unversion_file(tt.root)
4775 tt.version_file('new-id', tt.root)
4776- foo_trans_id = tt.trans_id_tree_file_id('foo-id')
4777+ foo_trans_id = tt.trans_id_tree_path('foo')
4778 foo_tuple = ('foo', foo_trans_id)
4779 root_tuple = ('', tt.root)
4780 self.assertEqual([root_tuple, foo_tuple], tt._inventory_altered())
4781@@ -1687,7 +1687,7 @@
4782 with TransformPreview(tree) as tt:
4783 tt.unversion_file(tt.root)
4784 tt.version_file(tree.get_root_id(), tt.root)
4785- foo_trans_id = tt.trans_id_tree_file_id('foo-id')
4786+ foo_trans_id = tt.trans_id_tree_path('foo')
4787 self.assertEqual([], tt._inventory_altered())
4788
4789
4790@@ -2160,7 +2160,7 @@
4791 self.requireFeature(HardlinkFeature)
4792 source = self.create_ab_tree()
4793 tt = TreeTransform(source)
4794- trans_id = tt.trans_id_tree_file_id('file1-id')
4795+ trans_id = tt.trans_id_tree_path('file1')
4796 tt.set_executability(True, trans_id)
4797 tt.apply()
4798 self.assertTrue(source.is_executable('file1'))
4799@@ -2669,7 +2669,7 @@
4800
4801 def test_resolve_create_parent_for_versioned_file(self):
4802 wt, tt = self.make_tt_with_versioned_dir()
4803- dir_tid = tt.trans_id_tree_file_id('dir-id')
4804+ dir_tid = tt.trans_id_tree_path('dir')
4805 file_tid = tt.new_file('file', dir_tid, 'Contents', file_id='file-id')
4806 tt.delete_contents(dir_tid)
4807 tt.unversion_file(dir_tid)
4808@@ -2680,7 +2680,7 @@
4809
4810 def test_non_versioned_file_create_conflict(self):
4811 wt, tt = self.make_tt_with_versioned_dir()
4812- dir_tid = tt.trans_id_tree_file_id('dir-id')
4813+ dir_tid = tt.trans_id_tree_path('dir')
4814 tt.new_file('file', dir_tid, 'Contents')
4815 tt.delete_contents(dir_tid)
4816 tt.unversion_file(dir_tid)
4817@@ -2837,7 +2837,7 @@
4818 work_tree.add('file', 'file-id')
4819 preview = TransformPreview(work_tree)
4820 self.addCleanup(preview.finalize)
4821- file_trans_id = preview.trans_id_tree_file_id('file-id')
4822+ file_trans_id = preview.trans_id_tree_path('file')
4823 preview.adjust_path('renamed', preview.root, file_trans_id)
4824 preview_tree = preview.get_preview_tree()
4825 preview_mtime = preview_tree.get_file_mtime('renamed', 'file-id')
4826@@ -2937,13 +2937,14 @@
4827 self.assertFalse(preview_tree.is_versioned('old_name/child'))
4828 self.assertEqual('child-id', preview_tree.path2id('new_name/child'))
4829
4830- def assertMatchingIterEntries(self, tt, specific_file_ids=None):
4831+ def assertMatchingIterEntries(self, tt, specific_files=None):
4832 preview_tree = tt.get_preview_tree()
4833 preview_result = list(preview_tree.iter_entries_by_dir(
4834- specific_file_ids))
4835+ specific_files=specific_files))
4836 tree = tt._tree
4837 tt.apply()
4838- actual_result = list(tree.iter_entries_by_dir(specific_file_ids))
4839+ actual_result = list(tree.iter_entries_by_dir(
4840+ specific_files=specific_files))
4841 self.assertEqual(actual_result, preview_result)
4842
4843 def test_iter_entries_by_dir_new(self):
4844@@ -2977,13 +2978,13 @@
4845 tt.trans_id_file_id('moved-id'))
4846 self.assertMatchingIterEntries(tt)
4847
4848- def test_iter_entries_by_dir_specific_file_ids(self):
4849+ def test_iter_entries_by_dir_specific_files(self):
4850 tree = self.make_branch_and_tree('tree')
4851 tree.set_root_id('tree-root-id')
4852 self.build_tree(['tree/parent/', 'tree/parent/child'])
4853 tree.add(['parent', 'parent/child'], ['parent-id', 'child-id'])
4854 tt = TreeTransform(tree)
4855- self.assertMatchingIterEntries(tt, ['tree-root-id', 'child-id'])
4856+ self.assertMatchingIterEntries(tt, ['', 'parent/child'])
4857
4858 def test_symlink_content_summary(self):
4859 self.requireFeature(SymlinkFeature)
4860@@ -3455,9 +3456,9 @@
4861
4862 def test_serialize_destruction(self):
4863 tt = self.make_destruction_preview()
4864- foo_trans_id = tt.trans_id_tree_file_id('foo-id')
4865+ foo_trans_id = tt.trans_id_tree_path(u'foo\u1234')
4866 tt.unversion_file(foo_trans_id)
4867- bar_trans_id = tt.trans_id_tree_file_id('bar-id')
4868+ bar_trans_id = tt.trans_id_tree_path('bar')
4869 tt.delete_contents(bar_trans_id)
4870 self.assertSerializesTo(self.destruction_records(), tt)
4871
4872@@ -3612,7 +3613,7 @@
4873 self.assertRaises(NotImplementedError, tt.new_orphan, 'foo', 'bar')
4874
4875 def _set_orphan_policy(self, wt, policy):
4876- wt.branch.get_config_stack().set('bzr.transform.orphan_policy',
4877+ wt.branch.get_config_stack().set('transform.orphan_policy',
4878 policy)
4879
4880 def _prepare_orphan(self, wt):
4881@@ -3741,7 +3742,7 @@
4882 self.parent_tree.lock_write()
4883 self.addCleanup(self.parent_tree.unlock)
4884 self.build_tree_contents([('parent/foo', 'bar')])
4885- self.parent_tree.add('foo', 'foo-id')
4886+ self.parent_tree.add('foo')
4887 self.parent_tree.commit('added foo')
4888 child_controldir = self.parent_tree.controldir.sprout('child')
4889 self.child_tree = child_controldir.open_workingtree()
4890@@ -3761,7 +3762,7 @@
4891 """If the file to be linked has modified execute bit, don't link."""
4892 tt = TreeTransform(self.child_tree)
4893 try:
4894- trans_id = tt.trans_id_tree_file_id('foo-id')
4895+ trans_id = tt.trans_id_tree_path('foo')
4896 tt.set_executability(True, trans_id)
4897 tt.apply()
4898 finally:
4899
4900=== modified file 'breezy/tests/test_workingtree.py'
4901--- breezy/tests/test_workingtree.py 2018-02-11 17:07:38 +0000
4902+++ breezy/tests/test_workingtree.py 2018-03-24 17:11:56 +0000
4903@@ -257,7 +257,8 @@
4904 subtree = self.make_branch_and_tree('tree/a/b')
4905 self.assertEqual([('tree-reference', 'b-id')],
4906 [(ie.kind, ie.file_id)
4907- for path, ie in tree.iter_entries_by_dir(['b-id'])])
4908+ for path, ie in tree.iter_entries_by_dir(
4909+ specific_files=['a/b'])])
4910
4911 def test_direct_subtree(self):
4912 tree = self.make_simple_tree()
4913
4914=== modified file 'breezy/transform.py'
4915--- breezy/transform.py 2018-03-12 05:18:13 +0000
4916+++ breezy/transform.py 2018-03-24 17:11:56 +0000
4917@@ -93,8 +93,7 @@
4918 class TreeTransformBase(object):
4919 """The base class for TreeTransform and its kin."""
4920
4921- def __init__(self, tree, pb=None,
4922- case_sensitive=True):
4923+ def __init__(self, tree, pb=None, case_sensitive=True):
4924 """Constructor.
4925
4926 :param tree: The tree that will be transformed, but not necessarily
4927@@ -135,7 +134,7 @@
4928 # The trans_id that will be used as the tree root
4929 root_id = tree.get_root_id()
4930 if root_id is not None:
4931- self._new_root = self.trans_id_tree_file_id(root_id)
4932+ self._new_root = self.trans_id_tree_path('')
4933 else:
4934 self._new_root = None
4935 # Indicator of whether the transform has been applied
4936@@ -219,7 +218,7 @@
4937 # the physical root needs a new transaction id
4938 self._tree_path_ids.pop("")
4939 self._tree_id_paths.pop(old_root)
4940- self._new_root = self.trans_id_tree_file_id(self._tree.get_root_id())
4941+ self._new_root = self.trans_id_tree_path('')
4942 if parent == old_root:
4943 parent = self._new_root
4944 self.adjust_path(name, parent, old_root)
4945@@ -288,17 +287,6 @@
4946 del self._new_parent[old_new_root]
4947 del self._new_name[old_new_root]
4948
4949- def trans_id_tree_file_id(self, inventory_id):
4950- """Determine the transaction id of a working tree file.
4951-
4952- This reflects only files that already exist, not ones that will be
4953- added by transactions.
4954- """
4955- if inventory_id is None:
4956- raise ValueError('None is not a valid file id')
4957- path = self._tree.id2path(inventory_id)
4958- return self.trans_id_tree_path(path)
4959-
4960 def trans_id_file_id(self, file_id):
4961 """Determine or set the transaction id associated with a file ID.
4962 A new id is only created for file_ids that were never present. If
4963@@ -311,8 +299,8 @@
4964 return self._r_new_id[file_id]
4965 else:
4966 try:
4967- next(self._tree.iter_entries_by_dir([file_id]))
4968- except StopIteration:
4969+ path = self._tree.id2path(file_id)
4970+ except errors.NoSuchId:
4971 if file_id in self._non_present_ids:
4972 return self._non_present_ids[file_id]
4973 else:
4974@@ -320,7 +308,7 @@
4975 self._non_present_ids[file_id] = trans_id
4976 return trans_id
4977 else:
4978- return self.trans_id_tree_file_id(file_id)
4979+ return self.trans_id_tree_path(path)
4980
4981 def trans_id_tree_path(self, path):
4982 """Determine (and maybe set) the transaction ID for a tree path."""
4983@@ -457,12 +445,14 @@
4984 else:
4985 return self.tree_kind(trans_id)
4986
4987+ def tree_path(self, trans_id):
4988+ """Determine the tree path associated with the trans_id."""
4989+ return self._tree_id_paths.get(trans_id)
4990+
4991 def tree_file_id(self, trans_id):
4992 """Determine the file id associated with the trans_id in the tree"""
4993- try:
4994- path = self._tree_id_paths[trans_id]
4995- except KeyError:
4996- # the file is a new, unversioned file, or invalid trans_id
4997+ path = self.tree_path(trans_id)
4998+ if path is None:
4999 return None
5000 # the file is old; the old id is still valid
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: