Merge lp:~jelmer/brz/has-path-relations into lp:brz
- has-path-relations
- Merge into trunk
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/has-path-relations |
Merge into: | lp:brz |
Diff against target: |
326 lines (+77/-114) 3 files modified
breezy/tests/matchers.py (+9/-11) breezy/tests/per_workingtree/test_commit.py (+25/-42) breezy/tests/per_workingtree/test_unversion.py (+43/-61) |
To merge this branch: | bzr merge lp:~jelmer/brz/has-path-relations |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Packman | Approve | ||
Review via email: mp+342034@code.launchpad.net |
Commit message
Description of the change
Use HasPathRelations in a few more places.
Simplify the actual HasPathRelations implementation to always take tuples with
current and previous path. The mode in which only the current path is specified
is not useful; the HasLayout matcher can already be used for that.
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 'breezy/tests/matchers.py' | |||
2 | --- breezy/tests/matchers.py 2018-03-18 14:48:55 +0000 | |||
3 | +++ breezy/tests/matchers.py 2018-03-24 13:52:34 +0000 | |||
4 | @@ -222,22 +222,20 @@ | |||
5 | 222 | 222 | ||
6 | 223 | :param entries: List of path strings or (path, previous_path) tuples to process | 223 | :param entries: List of path strings or (path, previous_path) tuples to process |
7 | 224 | """ | 224 | """ |
8 | 225 | directory_used = set() | ||
9 | 225 | directories = [] | 226 | directories = [] |
15 | 226 | for entry in entries: | 227 | for (path, previous_path) in entries: |
11 | 227 | if isinstance(entry, (str, text_type)): | ||
12 | 228 | path = entry | ||
13 | 229 | else: | ||
14 | 230 | path = entry[0] | ||
16 | 231 | if not path or path[-1] == "/": | 228 | if not path or path[-1] == "/": |
17 | 232 | # directory | 229 | # directory |
19 | 233 | directories.append((path, entry)) | 230 | directories.append((path, previous_path)) |
20 | 234 | else: | 231 | else: |
21 | 235 | # Yield the referenced parent directories | 232 | # Yield the referenced parent directories |
27 | 236 | for dirpath, direntry in directories: | 233 | for direntry in directories: |
28 | 237 | if osutils.is_inside(dirpath, path): | 234 | if osutils.is_inside(direntry[0], path): |
29 | 238 | yield direntry | 235 | directory_used.add(direntry[0]) |
30 | 239 | directories = [] | 236 | for (path, previous_path) in entries: |
31 | 240 | yield entry | 237 | if (not path.endswith("/")) or path in directory_used: |
32 | 238 | yield (path, previous_path) | ||
33 | 241 | 239 | ||
34 | 242 | def __str__(self): | 240 | def __str__(self): |
35 | 243 | return 'HasPathRelations(%r, %r)' % (self.previous_tree, self.previous_entries) | 241 | return 'HasPathRelations(%r, %r)' % (self.previous_tree, self.previous_entries) |
36 | 244 | 242 | ||
37 | === modified file 'breezy/tests/per_workingtree/test_commit.py' | |||
38 | --- breezy/tests/per_workingtree/test_commit.py 2018-03-10 14:20:40 +0000 | |||
39 | +++ breezy/tests/per_workingtree/test_commit.py 2018-03-24 13:52:34 +0000 | |||
40 | @@ -33,6 +33,7 @@ | |||
41 | 33 | CannotCommitSelectedFileMerge, | 33 | CannotCommitSelectedFileMerge, |
42 | 34 | PointlessCommit, | 34 | PointlessCommit, |
43 | 35 | ) | 35 | ) |
44 | 36 | from breezy.tests.matchers import HasPathRelations | ||
45 | 36 | from breezy.tests.per_workingtree import TestCaseWithWorkingTree | 37 | from breezy.tests.per_workingtree import TestCaseWithWorkingTree |
46 | 37 | from breezy.tests.testui import ProgressRecordingUIFactory | 38 | from breezy.tests.testui import ProgressRecordingUIFactory |
47 | 38 | 39 | ||
48 | @@ -66,51 +67,37 @@ | |||
49 | 66 | tree_a = self.make_branch_and_tree('a') | 67 | tree_a = self.make_branch_and_tree('a') |
50 | 67 | self.build_tree(['a/dir/', 'a/dir/f1', 'a/dir/f2', 'a/dir2/']) | 68 | self.build_tree(['a/dir/', 'a/dir/f1', 'a/dir/f2', 'a/dir2/']) |
51 | 68 | tree_a.add(['dir', 'dir/f1', 'dir/f2', 'dir2']) | 69 | tree_a.add(['dir', 'dir/f1', 'dir/f2', 'dir2']) |
52 | 69 | dir2_id = tree_a.path2id('dir2') | ||
53 | 70 | f1_id = tree_a.path2id('dir/f1') | ||
54 | 71 | rev_id1 = tree_a.commit('init') | 70 | rev_id1 = tree_a.commit('init') |
55 | 71 | revtree = tree_a.branch.repository.revision_tree(rev_id1) | ||
56 | 72 | # Rename one entry out of this directory | 72 | # Rename one entry out of this directory |
57 | 73 | tree_a.rename_one('dir/f1', 'dir2/a') | 73 | tree_a.rename_one('dir/f1', 'dir2/a') |
58 | 74 | osutils.rmtree('a/dir') | 74 | osutils.rmtree('a/dir') |
59 | 75 | tree_a.commit('autoremoved') | 75 | tree_a.commit('autoremoved') |
60 | 76 | 76 | ||
61 | 77 | with tree_a.lock_read(): | ||
62 | 78 | root_id = tree_a.get_root_id() | ||
63 | 79 | paths = [(path, ie.file_id) | ||
64 | 80 | for path, ie in tree_a.iter_entries_by_dir()] | ||
65 | 81 | # The only paths left should be the root | 77 | # The only paths left should be the root |
70 | 82 | self.assertEqual([('', root_id), | 78 | self.assertThat( |
71 | 83 | ('dir2', dir2_id), | 79 | tree_a, HasPathRelations( |
72 | 84 | ('dir2/a', f1_id), | 80 | revtree, |
73 | 85 | ], paths) | 81 | [('', ''), ('dir2/', 'dir2/'), ('dir2/a', 'dir/f1')])) |
74 | 86 | 82 | ||
75 | 87 | def test_no_autodelete_alternate_renamed(self): | 83 | def test_no_autodelete_alternate_renamed(self): |
76 | 88 | # Test for bug #114615 | 84 | # Test for bug #114615 |
77 | 89 | tree_a = self.make_branch_and_tree('A') | 85 | tree_a = self.make_branch_and_tree('A') |
78 | 90 | self.build_tree(['A/a/', 'A/a/m', 'A/a/n']) | 86 | self.build_tree(['A/a/', 'A/a/m', 'A/a/n']) |
79 | 91 | tree_a.add(['a', 'a/m', 'a/n']) | 87 | tree_a.add(['a', 'a/m', 'a/n']) |
80 | 92 | a_id = tree_a.path2id('a') | ||
81 | 93 | m_id = tree_a.path2id('a/m') | ||
82 | 94 | n_id = tree_a.path2id('a/n') | ||
83 | 95 | tree_a.commit('init') | 88 | tree_a.commit('init') |
84 | 96 | 89 | ||
85 | 97 | with tree_a.lock_read(): | ||
86 | 98 | root_id = tree_a.get_root_id() | ||
87 | 99 | |||
88 | 100 | tree_b = tree_a.controldir.sprout('B').open_workingtree() | 90 | tree_b = tree_a.controldir.sprout('B').open_workingtree() |
89 | 101 | self.build_tree(['B/xyz/']) | 91 | self.build_tree(['B/xyz/']) |
90 | 102 | tree_b.add(['xyz']) | 92 | tree_b.add(['xyz']) |
91 | 103 | xyz_id = tree_b.path2id('xyz') | ||
92 | 104 | tree_b.rename_one('a/m', 'xyz/m') | 93 | tree_b.rename_one('a/m', 'xyz/m') |
93 | 105 | osutils.rmtree('B/a') | 94 | osutils.rmtree('B/a') |
94 | 106 | tree_b.commit('delete in B') | 95 | tree_b.commit('delete in B') |
95 | 107 | 96 | ||
102 | 108 | paths = [(path, ie.file_id) | 97 | self.assertThat( |
103 | 109 | for path, ie in tree_b.iter_entries_by_dir()] | 98 | tree_b, |
104 | 110 | self.assertEqual([('', root_id), | 99 | HasPathRelations( |
105 | 111 | ('xyz', xyz_id), | 100 | tree_a, [('', ''), ('xyz/', None), ('xyz/m', 'a/m')])) |
100 | 112 | ('xyz/m', m_id), | ||
101 | 113 | ], paths) | ||
106 | 114 | 101 | ||
107 | 115 | self.build_tree_contents([('A/a/n', 'new contents for n\n')]) | 102 | self.build_tree_contents([('A/a/n', 'new contents for n\n')]) |
108 | 116 | tree_a.commit('change n in A') | 103 | tree_a.commit('change n in A') |
109 | @@ -119,14 +106,13 @@ | |||
110 | 119 | # (in A) and removed (in B), so 'a' needs to be restored. | 106 | # (in A) and removed (in B), so 'a' needs to be restored. |
111 | 120 | num_conflicts = tree_b.merge_from_branch(tree_a.branch) | 107 | num_conflicts = tree_b.merge_from_branch(tree_a.branch) |
112 | 121 | self.assertEqual(3, num_conflicts) | 108 | self.assertEqual(3, num_conflicts) |
121 | 122 | paths = [(path, ie.file_id) | 109 | |
122 | 123 | for path, ie in tree_b.iter_entries_by_dir()] | 110 | self.assertThat( |
123 | 124 | self.assertEqual([('', root_id), | 111 | tree_b, HasPathRelations( |
124 | 125 | ('a', a_id), | 112 | tree_a, |
125 | 126 | ('xyz', xyz_id), | 113 | [('', ''), ('a/', 'a/'), ('xyz/', None), |
126 | 127 | ('a/n.OTHER', n_id), | 114 | ('a/n.OTHER', 'a/n'), ('xyz/m', 'a/m')])) |
127 | 128 | ('xyz/m', m_id), | 115 | |
120 | 129 | ], paths) | ||
128 | 130 | osutils.rmtree('B/a') | 116 | osutils.rmtree('B/a') |
129 | 131 | try: | 117 | try: |
130 | 132 | # bzr resolve --all | 118 | # bzr resolve --all |
131 | @@ -136,12 +122,11 @@ | |||
132 | 136 | # effect. | 122 | # effect. |
133 | 137 | pass | 123 | pass |
134 | 138 | tree_b.commit('autoremove a, without touching xyz/m') | 124 | tree_b.commit('autoremove a, without touching xyz/m') |
141 | 139 | paths = [(path, ie.file_id) | 125 | |
142 | 140 | for path, ie in tree_b.iter_entries_by_dir()] | 126 | self.assertThat( |
143 | 141 | self.assertEqual([('', root_id), | 127 | tree_b, HasPathRelations( |
144 | 142 | ('xyz', xyz_id), | 128 | tree_a, |
145 | 143 | ('xyz/m', m_id), | 129 | [('', ''), ('xyz/', None), ('xyz/m', 'a/m')])) |
140 | 144 | ], paths) | ||
146 | 145 | 130 | ||
147 | 146 | def test_commit_exclude_pending_merge_fails(self): | 131 | def test_commit_exclude_pending_merge_fails(self): |
148 | 147 | """Excludes are a form of partial commit.""" | 132 | """Excludes are a form of partial commit.""" |
149 | @@ -173,15 +158,13 @@ | |||
150 | 173 | tree.lock_read() | 158 | tree.lock_read() |
151 | 174 | self.addCleanup(tree.unlock) | 159 | self.addCleanup(tree.unlock) |
152 | 175 | changes = list(tree.iter_changes(tree.basis_tree())) | 160 | changes = list(tree.iter_changes(tree.basis_tree())) |
156 | 176 | self.assertEqual(2, len(changes)) | 161 | self.assertEqual([(None, 'b'), (None, 'c')], [c[1] for c in changes]) |
154 | 177 | self.assertEqual((None, 'b'), changes[0][1]) | ||
155 | 178 | self.assertEqual((None, 'c'), changes[1][1]) | ||
157 | 179 | 162 | ||
158 | 180 | def test_commit_exclude_subtree_of_selected(self): | 163 | def test_commit_exclude_subtree_of_selected(self): |
159 | 181 | tree = self.make_branch_and_tree('.') | 164 | tree = self.make_branch_and_tree('.') |
161 | 182 | self.build_tree(['a/', 'a/b']) | 165 | self.build_tree(['a/', 'a/b', 'a/c']) |
162 | 183 | tree.smart_add(['.']) | 166 | tree.smart_add(['.']) |
164 | 184 | tree.commit('test', specific_files=['a'], exclude=['a/b']) | 167 | tree.commit('test', specific_files=['a', 'a/c'], exclude=['a/b']) |
165 | 185 | # If a/b was excluded it will still be 'added' in status. | 168 | # If a/b was excluded it will still be 'added' in status. |
166 | 186 | tree.lock_read() | 169 | tree.lock_read() |
167 | 187 | self.addCleanup(tree.unlock) | 170 | self.addCleanup(tree.unlock) |
168 | 188 | 171 | ||
169 | === modified file 'breezy/tests/per_workingtree/test_unversion.py' | |||
170 | --- breezy/tests/per_workingtree/test_unversion.py 2018-03-10 14:20:40 +0000 | |||
171 | +++ breezy/tests/per_workingtree/test_unversion.py 2018-03-24 13:52:34 +0000 | |||
172 | @@ -19,6 +19,7 @@ | |||
173 | 19 | from breezy import ( | 19 | from breezy import ( |
174 | 20 | errors, | 20 | errors, |
175 | 21 | ) | 21 | ) |
176 | 22 | from breezy.tests.matchers import HasPathRelations | ||
177 | 22 | from breezy.tests.per_workingtree import TestCaseWithWorkingTree | 23 | from breezy.tests.per_workingtree import TestCaseWithWorkingTree |
178 | 23 | 24 | ||
179 | 24 | 25 | ||
180 | @@ -44,12 +45,19 @@ | |||
181 | 44 | tree = self.make_branch_and_tree('.') | 45 | tree = self.make_branch_and_tree('.') |
182 | 45 | self.build_tree(['del/', 'del/sub/', 'del/sub/b']) | 46 | self.build_tree(['del/', 'del/sub/', 'del/sub/b']) |
183 | 46 | tree.add(['del', 'del/sub', 'del/sub/b']) | 47 | tree.add(['del', 'del/sub', 'del/sub/b']) |
186 | 47 | b_id = tree.path2id('del/sub/b') | 48 | revid = tree.commit('setup') |
187 | 48 | tree.commit('setup') | 49 | revtree = tree.branch.repository.revision_tree(revid) |
188 | 49 | tree.rename_one('del/sub', 'sub') | 50 | tree.rename_one('del/sub', 'sub') |
192 | 50 | self.assertEqual('sub/b', tree.id2path(b_id)) | 51 | self.assertThat( |
193 | 51 | tree.unversion(['del', 'sub/b']) | 52 | tree, |
194 | 52 | self.assertRaises(errors.NoSuchId, tree.id2path, b_id) | 53 | HasPathRelations(revtree, [('', ''), ('del/', 'del/'), ('sub/', 'del/sub/'), ('sub/b', 'del/sub/b')])) |
195 | 54 | if tree.has_versioned_directories(): | ||
196 | 55 | tree.unversion(['del', 'sub/b']) | ||
197 | 56 | else: | ||
198 | 57 | tree.unversion(['sub/b']) | ||
199 | 58 | self.assertThat( | ||
200 | 59 | tree, | ||
201 | 60 | HasPathRelations(revtree, [('', ''), ('sub/', 'del/sub/')])) | ||
202 | 53 | 61 | ||
203 | 54 | def test_unversion_several_files(self): | 62 | def test_unversion_several_files(self): |
204 | 55 | """After unversioning several files, they should not be versioned.""" | 63 | """After unversioning several files, they should not be versioned.""" |
205 | @@ -119,72 +127,47 @@ | |||
206 | 119 | self.build_tree(['a/dir/', 'a/dir/f1', 'a/dir/f2', 'a/dir/f3', | 127 | self.build_tree(['a/dir/', 'a/dir/f1', 'a/dir/f2', 'a/dir/f3', |
207 | 120 | 'a/dir2/']) | 128 | 'a/dir2/']) |
208 | 121 | tree.add(['dir', 'dir/f1', 'dir/f2', 'dir/f3', 'dir2']) | 129 | tree.add(['dir', 'dir/f1', 'dir/f2', 'dir/f3', 'dir2']) |
209 | 122 | dir_id = tree.path2id('dir') | ||
210 | 123 | dir2_id = tree.path2id('dir2') | ||
211 | 124 | f1_id = tree.path2id('dir/f1') | ||
212 | 125 | f2_id = tree.path2id('dir/f2') | ||
213 | 126 | f3_id = tree.path2id('dir/f3') | ||
214 | 127 | rev_id1 = tree.commit('init') | 130 | rev_id1 = tree.commit('init') |
215 | 131 | revtree = tree.branch.repository.revision_tree(rev_id1) | ||
216 | 128 | # Start off by renaming entries, and then unversion a bunch of entries | 132 | # Start off by renaming entries, and then unversion a bunch of entries |
217 | 129 | # https://bugs.launchpad.net/bzr/+bug/114615 | 133 | # https://bugs.launchpad.net/bzr/+bug/114615 |
218 | 130 | tree.rename_one('dir/f1', 'dir/a') | 134 | tree.rename_one('dir/f1', 'dir/a') |
219 | 131 | tree.rename_one('dir/f2', 'dir/z') | 135 | tree.rename_one('dir/f2', 'dir/z') |
220 | 132 | tree.move(['dir/f3'], 'dir2') | 136 | tree.move(['dir/f3'], 'dir2') |
221 | 133 | 137 | ||
236 | 134 | tree.lock_read() | 138 | self.assertThat( |
237 | 135 | try: | 139 | tree, HasPathRelations( |
238 | 136 | root_id = tree.get_root_id() | 140 | revtree, |
239 | 137 | paths = [(path, ie.file_id) | 141 | [('', ''), ('dir/', 'dir/'), ('dir2/', 'dir2/'), |
240 | 138 | for path, ie in tree.iter_entries_by_dir()] | 142 | ('dir/a', 'dir/f1'), ('dir/z', 'dir/f2'), |
241 | 139 | finally: | 143 | ('dir2/f3', 'dir/f3')])) |
228 | 140 | tree.unlock() | ||
229 | 141 | self.assertEqual([('', root_id), | ||
230 | 142 | ('dir', dir_id), | ||
231 | 143 | ('dir2', dir2_id), | ||
232 | 144 | ('dir/a', f1_id), | ||
233 | 145 | ('dir/z', f2_id), | ||
234 | 146 | ('dir2/f3', f3_id), | ||
235 | 147 | ], paths) | ||
242 | 148 | 144 | ||
243 | 149 | tree.unversion({'dir'}) | 145 | tree.unversion({'dir'}) |
251 | 150 | paths = [(path, ie.file_id) | 146 | self.assertThat( |
252 | 151 | for path, ie in tree.iter_entries_by_dir()] | 147 | tree, |
253 | 152 | 148 | HasPathRelations( | |
254 | 153 | self.assertEqual([('', root_id), | 149 | revtree, |
255 | 154 | ('dir2', dir2_id), | 150 | [('', ''), ('dir2/', 'dir2/'), ('dir2/f3', 'dir/f3')])) |
249 | 155 | ('dir2/f3', f3_id), | ||
250 | 156 | ], paths) | ||
256 | 157 | 151 | ||
257 | 158 | def test_unversion_after_conflicted_merge(self): | 152 | def test_unversion_after_conflicted_merge(self): |
258 | 159 | # Test for bug #114615 | 153 | # Test for bug #114615 |
259 | 160 | tree_a = self.make_branch_and_tree('A') | 154 | tree_a = self.make_branch_and_tree('A') |
260 | 161 | self.build_tree(['A/a/', 'A/a/m', 'A/a/n']) | 155 | self.build_tree(['A/a/', 'A/a/m', 'A/a/n']) |
261 | 162 | tree_a.add(['a', 'a/m', 'a/n']) | 156 | tree_a.add(['a', 'a/m', 'a/n']) |
262 | 163 | a_id = tree_a.path2id('a') | ||
263 | 164 | m_id = tree_a.path2id('a/m') | ||
264 | 165 | n_id = tree_a.path2id('a/n') | ||
265 | 166 | tree_a.commit('init') | 157 | tree_a.commit('init') |
266 | 167 | 158 | ||
267 | 168 | tree_a.lock_read() | ||
268 | 169 | try: | ||
269 | 170 | root_id = tree_a.get_root_id() | ||
270 | 171 | finally: | ||
271 | 172 | tree_a.unlock() | ||
272 | 173 | |||
273 | 174 | tree_b = tree_a.controldir.sprout('B').open_workingtree() | 159 | tree_b = tree_a.controldir.sprout('B').open_workingtree() |
274 | 175 | self.build_tree(['B/xyz/']) | 160 | self.build_tree(['B/xyz/']) |
275 | 176 | tree_b.add(['xyz']) | 161 | tree_b.add(['xyz']) |
276 | 177 | xyz_id = tree_b.path2id('xyz') | ||
277 | 178 | tree_b.rename_one('a/m', 'xyz/m') | 162 | tree_b.rename_one('a/m', 'xyz/m') |
278 | 179 | tree_b.unversion(['a']) | 163 | tree_b.unversion(['a']) |
279 | 180 | tree_b.commit('delete in B') | 164 | tree_b.commit('delete in B') |
280 | 181 | 165 | ||
287 | 182 | paths = [(path, ie.file_id) | 166 | self.assertThat( |
288 | 183 | for path, ie in tree_b.iter_entries_by_dir()] | 167 | tree_b, |
289 | 184 | self.assertEqual([('', root_id), | 168 | HasPathRelations( |
290 | 185 | ('xyz', xyz_id), | 169 | tree_a, |
291 | 186 | ('xyz/m', m_id), | 170 | [('', ''), ('xyz/', None), ('xyz/m', 'a/m')])) |
286 | 187 | ], paths) | ||
292 | 188 | 171 | ||
293 | 189 | self.build_tree_contents([('A/a/n', 'new contents for n\n')]) | 172 | self.build_tree_contents([('A/a/n', 'new contents for n\n')]) |
294 | 190 | tree_a.commit('change n in A') | 173 | tree_a.commit('change n in A') |
295 | @@ -194,18 +177,17 @@ | |||
296 | 194 | # because 'a' is still an existing directory | 177 | # because 'a' is still an existing directory |
297 | 195 | num_conflicts = tree_b.merge_from_branch(tree_a.branch) | 178 | num_conflicts = tree_b.merge_from_branch(tree_a.branch) |
298 | 196 | self.assertEqual(4, num_conflicts) | 179 | self.assertEqual(4, num_conflicts) |
307 | 197 | paths = [(path, ie.file_id) | 180 | |
308 | 198 | for path, ie in tree_b.iter_entries_by_dir()] | 181 | self.assertThat( |
309 | 199 | self.assertEqual([('', root_id), | 182 | tree_b, |
310 | 200 | ('a', a_id), | 183 | HasPathRelations( |
311 | 201 | ('xyz', xyz_id), | 184 | tree_a, |
312 | 202 | ('a/n.OTHER', n_id), | 185 | [('', ''), ('a/', 'a/'), ('xyz/', None), |
313 | 203 | ('xyz/m', m_id), | 186 | ('a/n.OTHER', 'a/n'), ('xyz/m', 'a/m')])) |
314 | 204 | ], paths) | 187 | |
315 | 205 | tree_b.unversion(['a']) | 188 | tree_b.unversion(['a']) |
322 | 206 | paths = [(path, ie.file_id) | 189 | self.assertThat( |
323 | 207 | for path, ie in tree_b.iter_entries_by_dir()] | 190 | tree_b, |
324 | 208 | self.assertEqual([('', root_id), | 191 | HasPathRelations( |
325 | 209 | ('xyz', xyz_id), | 192 | tree_a, |
326 | 210 | ('xyz/m', m_id), | 193 | [('', ''), ('xyz/', None), ('xyz/m', 'a/m')])) |
321 | 211 | ], paths) |
Looks good, thanks.