Merge lp:~jelmer/brz/follow-tree-references-iter-entries-by-dir into lp:brz

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merge reported by: The Breezy Bot
Merged at revision: not available
Proposed branch: lp:~jelmer/brz/follow-tree-references-iter-entries-by-dir
Merge into: lp:brz
Prerequisite: lp:~jelmer/brz/follow-tree-references-list-files
Diff against target: 307 lines (+104/-27)
10 files modified
breezy/bzr/inventorytree.py (+12/-7)
breezy/bzr/workingtree.py (+20/-5)
breezy/bzr/workingtree_4.py (+0/-4)
breezy/filter_tree.py (+2/-2)
breezy/git/tree.py (+10/-3)
breezy/tests/blackbox/test_join.py (+2/-1)
breezy/tests/per_tree/test_test_trees.py (+40/-0)
breezy/tests/test_dirstate.py (+2/-2)
breezy/transform.py (+11/-2)
breezy/tree.py (+5/-1)
To merge this branch: bzr merge lp:~jelmer/brz/follow-tree-references-iter-entries-by-dir
Reviewer Review Type Date Requested Status
Jelmer Vernooij Approve
Review via email: mp+374108@code.launchpad.net

Commit message

Add recurse_nested argument to Tree.iter_entries_by_dir.

Description of the change

Add follow_tree_references argument to Tree.iter_entries_by_dir.

This is another step towards nested tree support.

To post a comment you must log in.
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :
Revision history for this message
Jelmer Vernooij (jelmer) :
review: Approve
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'breezy/bzr/inventorytree.py'
2--- breezy/bzr/inventorytree.py 2020-01-11 02:39:34 +0000
3+++ breezy/bzr/inventorytree.py 2020-01-11 02:39:34 +0000
4@@ -213,7 +213,8 @@
5 def all_versioned_paths(self):
6 return {path for path, entry in self.iter_entries_by_dir()}
7
8- def iter_entries_by_dir(self, specific_files=None):
9+ def iter_entries_by_dir(self, specific_files=None,
10+ recurse_nested=False):
11 """Walk the tree in 'by_dir' order.
12
13 This will yield each entry in the tree as a (path, entry) tuple.
14@@ -226,17 +227,21 @@
15 inventory_file_ids = []
16 for path in specific_files:
17 inventory, inv_file_id = self._path2inv_file_id(path)
18- if inv_file_id is None:
19- continue
20- if inventory is not self.root_inventory: # for now
21+ if inventory and inventory is not self.root_inventory:
22 raise AssertionError("%r != %r" % (
23 inventory, self.root_inventory))
24 inventory_file_ids.append(inv_file_id)
25 else:
26 inventory_file_ids = None
27- # FIXME: Handle nested trees
28- return self.root_inventory.iter_entries_by_dir(
29- specific_file_ids=inventory_file_ids)
30+ def iter_entries(inv):
31+ for p, e in inv.iter_entries_by_dir(specific_file_ids=inventory_file_ids):
32+ if e.kind == 'tree-reference' and recurse_nested:
33+ subinv = self._get_nested_tree(p, e.file_id, e.reference_revision).root_inventory
34+ for subp, e in iter_entries(subinv):
35+ yield (osutils.pathjoin(p, subp) if subp else p), e
36+ else:
37+ yield p, e
38+ return iter_entries(self.root_inventory)
39
40 def iter_child_entries(self, path):
41 with self.lock_read():
42
43=== modified file 'breezy/bzr/workingtree.py'
44--- breezy/bzr/workingtree.py 2020-01-11 02:39:34 +0000
45+++ breezy/bzr/workingtree.py 2020-01-11 02:39:34 +0000
46@@ -1728,7 +1728,7 @@
47 self.control_transport.put_bytes(
48 'format', self._format.as_string())
49
50- def _check_for_tree_references(self, iterator):
51+ def _check_for_tree_references(self, iterator, recurse_nested, specific_files=None):
52 """See if directories have become tree-references."""
53 blocked_parent_ids = set()
54 for path, ie in iterator:
55@@ -1740,12 +1740,25 @@
56 continue
57 if (ie.kind == 'directory' and
58 self._directory_is_tree_reference(path)):
59+
60 # This InventoryDirectory needs to be a TreeReference
61 ie = inventory.TreeReference(ie.file_id, ie.name, ie.parent_id)
62 blocked_parent_ids.add(ie.file_id)
63- yield path, ie
64-
65- def iter_entries_by_dir(self, specific_files=None):
66+
67+ if ie.kind == 'tree-reference' and recurse_nested:
68+ subtree = self.get_nested_tree(path)
69+ for subpath, ie in subtree.iter_entries_by_dir(
70+ recurse_nested=recurse_nested,
71+ specific_files=specific_files):
72+ if subpath:
73+ full_subpath = osutils.pathjoin(path, subpath)
74+ else:
75+ full_subpath = path
76+ yield full_subpath, ie
77+ else:
78+ yield path, ie
79+
80+ def iter_entries_by_dir(self, specific_files=None, recurse_nested=False):
81 """See Tree.iter_entries_by_dir()"""
82 # The only trick here is that if we supports_tree_reference then we
83 # need to detect if a directory becomes a tree-reference.
84@@ -1754,7 +1767,9 @@
85 if not self.supports_tree_reference():
86 return iterator
87 else:
88- return self._check_for_tree_references(iterator)
89+ return self._check_for_tree_references(
90+ iterator, recurse_nested=recurse_nested,
91+ specific_files=specific_files)
92
93 def get_canonical_paths(self, paths):
94 """Look up canonical paths for multiple items.
95
96=== modified file 'breezy/bzr/workingtree_4.py'
97--- breezy/bzr/workingtree_4.py 2020-01-11 02:39:34 +0000
98+++ breezy/bzr/workingtree_4.py 2020-01-11 02:39:34 +0000
99@@ -374,10 +374,6 @@
100 # add this entry to the parent map.
101 parent_ies[(dirname + b'/' + name).strip(b'/')] = inv_entry
102 elif kind == 'tree-reference':
103- if not self._repo_supports_tree_reference:
104- raise errors.UnsupportedOperation(
105- self._generate_inventory,
106- self.branch.repository)
107 inv_entry.reference_revision = link_or_sha1 or None
108 elif kind != 'symlink':
109 raise AssertionError("unknown kind %r" % kind)
110
111=== modified file 'breezy/filter_tree.py'
112--- breezy/filter_tree.py 2018-11-16 18:33:17 +0000
113+++ breezy/filter_tree.py 2020-01-11 02:39:34 +0000
114@@ -63,14 +63,14 @@
115 def is_executable(self, path):
116 return self.backing_tree.is_executable(path)
117
118- def iter_entries_by_dir(self, specific_files=None):
119+ def iter_entries_by_dir(self, specific_files=None, recurse_nested=False):
120 # NB: This simply returns the parent tree's entries; the length may be
121 # wrong but it can't easily be calculated without filtering the whole
122 # text. Currently all callers cope with this; perhaps they should be
123 # updated to a narrower interface that only provides things guaranteed
124 # cheaply available across all trees. -- mbp 20110705
125 return self.backing_tree.iter_entries_by_dir(
126- specific_files=specific_files)
127+ specific_files=specific_files, recurse_nested=recurse_nested)
128
129 def lock_read(self):
130 return self.backing_tree.lock_read()
131
132=== modified file 'breezy/git/tree.py'
133--- breezy/git/tree.py 2020-01-11 02:39:34 +0000
134+++ breezy/git/tree.py 2020-01-11 02:39:34 +0000
135@@ -526,7 +526,8 @@
136 yield self._get_file_ie(store, child_path, name, mode, hexsha,
137 file_id)
138
139- def iter_entries_by_dir(self, specific_files=None):
140+ def iter_entries_by_dir(self, specific_files=None,
141+ recurse_nested=False):
142 if self.tree is None:
143 return
144 if specific_files is not None:
145@@ -547,6 +548,10 @@
146 continue
147 child_path = posixpath.join(path, name)
148 child_path_decoded = child_path.decode('utf-8')
149+ if recurse_nested and S_ISGITLINK(mode):
150+ mode = stat.S_IFDIR
151+ store = self._get_submodule_store(child_path)
152+ hexsha = store[hexsha].tree
153 if stat.S_ISDIR(mode):
154 if (specific_files is None or
155 any([p for p in specific_files if p.startswith(
156@@ -1217,7 +1222,8 @@
157 else:
158 yield (posixpath.join(basepath, path), value)
159
160- def iter_entries_by_dir(self, specific_files=None):
161+ def iter_entries_by_dir(self, specific_files=None,
162+ recurse_nested=False):
163 with self.lock_read():
164 if specific_files is not None:
165 specific_files = set(specific_files)
166@@ -1228,7 +1234,8 @@
167 if specific_files is None or u"" in specific_files:
168 ret[(u"", u"")] = root_ie
169 dir_ids = {u"": root_ie.file_id}
170- for path, value in self._recurse_index_entries():
171+ for path, value in self._recurse_index_entries(
172+ recurse_nested=recurse_nested):
173 if self.mapping.is_special_file(path):
174 continue
175 path = path.decode("utf-8")
176
177=== modified file 'breezy/tests/blackbox/test_join.py'
178--- breezy/tests/blackbox/test_join.py 2020-01-11 02:39:34 +0000
179+++ breezy/tests/blackbox/test_join.py 2020-01-11 02:39:34 +0000
180@@ -76,7 +76,8 @@
181 self.assertEqual('file1', sub_tree.id2path(b'file1-id'))
182 self.assertEqual(subtree_root_id, sub_tree.path2id(''))
183 self.assertEqual('', sub_tree.id2path(subtree_root_id))
184- self.assertEqual(b'file1-id', base_tree.path2id('subtree/file1'))
185+ self.assertEqual(
186+ sub_tree.path2id('file1'), base_tree.path2id('subtree/file1'))
187
188 base_tree.lock_read()
189 self.addCleanup(base_tree.unlock)
190
191=== modified file 'breezy/tests/per_tree/test_test_trees.py'
192--- breezy/tests/per_tree/test_test_trees.py 2019-10-13 14:28:07 +0000
193+++ breezy/tests/per_tree/test_test_trees.py 2020-01-11 02:39:34 +0000
194@@ -410,3 +410,43 @@
195 last_revision = getattr(tree, 'last_revision', None)
196 if last_revision is not None:
197 self.assertIsInstance(last_revision(), bytes)
198+
199+ def skip_if_no_reference(self, tree):
200+ if not getattr(tree, 'supports_tree_reference', lambda: False)():
201+ raise TestNotApplicable('Tree references not supported')
202+
203+ def create_nested(self):
204+ work_tree = self.make_branch_and_tree('wt')
205+ with work_tree.lock_write():
206+ self.skip_if_no_reference(work_tree)
207+ subtree = self.make_branch_and_tree('wt/subtree')
208+ self.build_tree(['wt/subtree/a'])
209+ subtree.add(['a'])
210+ subtree.commit('foo')
211+ work_tree.add_reference(subtree)
212+ tree = self._convert_tree(work_tree)
213+ self.skip_if_no_reference(tree)
214+ return tree, subtree
215+
216+ def test_iter_entries_with_unfollowed_reference(self):
217+ tree, subtree = self.create_nested()
218+ expected = [
219+ ('', 'directory'),
220+ ('subtree', 'tree-reference')]
221+ with tree.lock_read():
222+ path_entries = list(tree.iter_entries_by_dir(recurse_nested=False))
223+ actual = [(path, ie.kind)
224+ for path, ie in path_entries]
225+ self.assertEqual(expected, actual)
226+
227+ def test_iter_entries_with_followed_reference(self):
228+ tree, subtree = self.create_nested()
229+ expected = [
230+ ('', 'directory'),
231+ ('subtree', 'directory'),
232+ ('subtree/a', 'file')]
233+ with tree.lock_read():
234+ path_entries = list(tree.iter_entries_by_dir(recurse_nested=True))
235+ actual = [(path, ie.kind)
236+ for path, ie in path_entries]
237+ self.assertEqual(expected, actual)
238
239=== modified file 'breezy/tests/test_dirstate.py'
240--- breezy/tests/test_dirstate.py 2020-01-11 02:39:34 +0000
241+++ breezy/tests/test_dirstate.py 2020-01-11 02:39:34 +0000
242@@ -2564,8 +2564,8 @@
243 basis_tree.root_inventory)
244 state.update_basis_by_delta(delta, b'target')
245 state._validate()
246- dirstate_tree = workingtree_4.DirStateRevisionTree(state,
247- b'target', _Repo(), None)
248+ dirstate_tree = workingtree_4.DirStateRevisionTree(
249+ state, b'target', _Repo(), None)
250 # The target now that delta has been applied should match the
251 # RevisionTree
252 self.assertEqual([], list(dirstate_tree.iter_changes(target_tree)))
253
254=== modified file 'breezy/transform.py'
255--- breezy/transform.py 2019-09-29 12:45:26 +0000
256+++ breezy/transform.py 2020-01-11 02:39:34 +0000
257@@ -2218,7 +2218,11 @@
258 for entry, trans_id in self._make_inv_entries(todo):
259 yield entry
260
261- def iter_entries_by_dir(self, specific_files=None):
262+ def iter_entries_by_dir(self, specific_files=None, recurse_nested=False):
263+ if recurse_nested:
264+ raise NotImplementedError(
265+ 'follow tree references not yet supported')
266+
267 # This may not be a maximally efficient implementation, but it is
268 # reasonably straightforward. An implementation that grafts the
269 # TreeTransform changes onto the tree's iter_entries_by_dir results
270@@ -2242,8 +2246,13 @@
271 path_entries.sort()
272 return path_entries
273
274- def list_files(self, include_root=False, from_dir=None, recursive=True):
275+ def list_files(self, include_root=False, from_dir=None, recursive=True,
276+ recurse_nested=False):
277 """See WorkingTree.list_files."""
278+ if recurse_nested:
279+ raise NotImplementedError(
280+ 'follow tree references not yet supported')
281+
282 # XXX This should behave like WorkingTree.list_files, but is really
283 # more like RevisionTree.list_files.
284 if from_dir == '.':
285
286=== modified file 'breezy/tree.py'
287--- breezy/tree.py 2020-01-11 02:39:34 +0000
288+++ breezy/tree.py 2020-01-11 02:39:34 +0000
289@@ -317,7 +317,7 @@
290 """
291 raise NotImplementedError(self.id2path)
292
293- def iter_entries_by_dir(self, specific_files=None):
294+ def iter_entries_by_dir(self, specific_files=None, recurse_nested=False):
295 """Walk the tree in 'by_dir' order.
296
297 This will yield each entry in the tree as a (path, entry) tuple.
298@@ -341,6 +341,10 @@
299 The yield order (ignoring root) would be::
300
301 a, f, a/b, a/d, a/b/c, a/d/e, f/g
302+
303+ If recurse_nested is enabled then nested trees are included as if
304+ they were a part of the tree. If is disabled then TreeReference
305+ objects (without any children) are yielded.
306 """
307 raise NotImplementedError(self.iter_entries_by_dir)
308

Subscribers

People subscribed via source and target branches