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/transform |
Merge into: | lp:brz/3.1 |
Diff against target: |
1696 lines (+770/-696) 8 files modified
breezy/git/tree.py (+8/-0) breezy/merge.py (+2/-8) breezy/tests/per_tree/__init__.py (+1/-0) breezy/tests/per_tree/test_transform.py (+719/-0) breezy/tests/per_workingtree/test_transform.py (+14/-6) breezy/tests/test_transform.py (+0/-665) breezy/tests/test_tree.py (+7/-0) breezy/transform.py (+19/-17) |
To merge this branch: | bzr merge lp:~jelmer/brz/transform |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jelmer Vernooij | Approve | ||
Review via email: mp+386857@code.launchpad.net |
Commit message
More work towards supporting file-id-independent Transform.
Description of the change
More work towards supporting file-id-independent Transform.
To post a comment you must log in.
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 : | # |
Running landing tests failed
https:/
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'breezy/git/tree.py' |
2 | --- breezy/git/tree.py 2020-07-04 00:38:37 +0000 |
3 | +++ breezy/git/tree.py 2020-07-05 00:45:38 +0000 |
4 | @@ -724,6 +724,10 @@ |
5 | file_id, mode_kind(mode))) |
6 | yield (path_decoded, parent_id), children |
7 | |
8 | + def preview_transform(self, pb=None): |
9 | + from ..transform import TransformPreview |
10 | + return TransformPreview(self, pb=pb) |
11 | + |
12 | |
13 | def tree_delta_from_git_changes(changes, mappings, |
14 | specific_files=None, |
15 | @@ -1634,6 +1638,10 @@ |
16 | from ..transform import TreeTransform |
17 | return TreeTransform(self, pb=pb) |
18 | |
19 | + def preview_transform(self, pb=None): |
20 | + from ..transform import TransformPreview |
21 | + return TransformPreview(self, pb=pb) |
22 | + |
23 | |
24 | |
25 | class InterToIndexGitTree(InterGitTrees): |
26 | |
27 | === modified file 'breezy/merge.py' |
28 | --- breezy/merge.py 2020-07-04 14:58:52 +0000 |
29 | +++ breezy/merge.py 2020-07-05 00:45:38 +0000 |
30 | @@ -1465,14 +1465,8 @@ |
31 | data.append(('BASE', self.base_tree, base_path, base_lines)) |
32 | |
33 | # We need to use the actual path in the working tree of the file here, |
34 | - # ignoring the conflict suffixes |
35 | - wt = self.this_tree |
36 | - if wt.supports_content_filtering(): |
37 | - try: |
38 | - filter_tree_path = wt.id2path(file_id) |
39 | - except errors.NoSuchId: |
40 | - # file has been deleted |
41 | - filter_tree_path = None |
42 | + if self.this_tree.supports_content_filtering(): |
43 | + filter_tree_path = this_path |
44 | else: |
45 | # Skip the id2path lookup for older formats |
46 | filter_tree_path = None |
47 | |
48 | === modified file 'breezy/tests/per_tree/__init__.py' |
49 | --- breezy/tests/per_tree/__init__.py 2020-07-04 01:15:59 +0000 |
50 | +++ breezy/tests/per_tree/__init__.py 2020-07-05 00:45:38 +0000 |
51 | @@ -354,6 +354,7 @@ |
52 | 'revision_tree', |
53 | 'symlinks', |
54 | 'test_trees', |
55 | + 'transform', |
56 | 'tree', |
57 | 'walkdirs', |
58 | ] |
59 | |
60 | === added file 'breezy/tests/per_tree/test_transform.py' |
61 | --- breezy/tests/per_tree/test_transform.py 1970-01-01 00:00:00 +0000 |
62 | +++ breezy/tests/per_tree/test_transform.py 2020-07-05 00:45:38 +0000 |
63 | @@ -0,0 +1,719 @@ |
64 | +# Copyright (C) 2006-2012, 2016 Canonical Ltd |
65 | +# |
66 | +# This program is free software; you can redistribute it and/or modify |
67 | +# it under the terms of the GNU General Public License as published by |
68 | +# the Free Software Foundation; either version 2 of the License, or |
69 | +# (at your option) any later version. |
70 | +# |
71 | +# This program is distributed in the hope that it will be useful, |
72 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
73 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
74 | +# GNU General Public License for more details. |
75 | +# |
76 | +# You should have received a copy of the GNU General Public License |
77 | +# along with this program; if not, write to the Free Software |
78 | +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
79 | + |
80 | +from io import BytesIO |
81 | +import os |
82 | + |
83 | +from ... import ( |
84 | + revision as _mod_revision, |
85 | + trace, |
86 | + ) |
87 | +from ...diff import show_diff_trees |
88 | +from ...merge import Merger, Merge3Merger |
89 | +from ...transform import ( |
90 | + ROOT_PARENT, |
91 | + resolve_conflicts, |
92 | + ) |
93 | +from ...tree import ( |
94 | + find_previous_path, |
95 | + ) |
96 | + |
97 | + |
98 | +from breezy.tests.per_tree import TestCaseWithTree |
99 | + |
100 | + |
101 | +from ..features import ( |
102 | + HardlinkFeature, |
103 | + SymlinkFeature, |
104 | + UnicodeFilenameFeature, |
105 | + ) |
106 | + |
107 | + |
108 | + |
109 | +A_ENTRY = (b'a-id', ('a', 'a'), True, (True, True), |
110 | + (b'TREE_ROOT', b'TREE_ROOT'), ('a', 'a'), ('file', 'file'), |
111 | + (False, False), False) |
112 | +ROOT_ENTRY = (b'TREE_ROOT', ('', ''), False, (True, True), (None, None), |
113 | + ('', ''), ('directory', 'directory'), (False, False), False) |
114 | + |
115 | + |
116 | +class TestTransformPreview(TestCaseWithTree): |
117 | + |
118 | + def setUp(self): |
119 | + super(TestTransformPreview, self).setUp() |
120 | + if not self.workingtree_format.supports_setting_file_ids: |
121 | + self.skipTest('test not compatible with non-file-id trees yet') |
122 | + |
123 | + def create_tree(self): |
124 | + tree = self.make_branch_and_tree('.') |
125 | + self.build_tree_contents([('a', b'content 1')]) |
126 | + tree.set_root_id(b'TREE_ROOT') |
127 | + tree.add('a', b'a-id') |
128 | + revid1 = tree.commit('rev1') |
129 | + return tree.branch.repository.revision_tree(revid1) |
130 | + |
131 | + def get_empty_preview(self): |
132 | + repository = self.make_repository('repo') |
133 | + tree = repository.revision_tree(_mod_revision.NULL_REVISION) |
134 | + preview = tree.preview_transform() |
135 | + self.addCleanup(preview.finalize) |
136 | + return preview |
137 | + |
138 | + def test_transform_preview(self): |
139 | + revision_tree = self.create_tree() |
140 | + preview = revision_tree.preview_transform() |
141 | + self.addCleanup(preview.finalize) |
142 | + |
143 | + def test_transform_preview_tree(self): |
144 | + revision_tree = self.create_tree() |
145 | + preview = revision_tree.preview_transform() |
146 | + self.addCleanup(preview.finalize) |
147 | + preview.get_preview_tree() |
148 | + |
149 | + def test_transform_new_file(self): |
150 | + revision_tree = self.create_tree() |
151 | + preview = revision_tree.preview_transform() |
152 | + self.addCleanup(preview.finalize) |
153 | + preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id') |
154 | + preview_tree = preview.get_preview_tree() |
155 | + self.assertEqual(preview_tree.kind('file2'), 'file') |
156 | + with preview_tree.get_file('file2') as f: |
157 | + self.assertEqual(f.read(), b'content B\n') |
158 | + |
159 | + def test_diff_preview_tree(self): |
160 | + revision_tree = self.create_tree() |
161 | + preview = revision_tree.preview_transform() |
162 | + self.addCleanup(preview.finalize) |
163 | + preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id') |
164 | + preview_tree = preview.get_preview_tree() |
165 | + out = BytesIO() |
166 | + show_diff_trees(revision_tree, preview_tree, out) |
167 | + lines = out.getvalue().splitlines() |
168 | + self.assertEqual(lines[0], b"=== added file 'file2'") |
169 | + # 3 lines of diff administrivia |
170 | + self.assertEqual(lines[4], b"+content B") |
171 | + |
172 | + def test_unsupported_symlink_diff(self): |
173 | + self.requireFeature(SymlinkFeature) |
174 | + tree = self.make_branch_and_tree('.') |
175 | + self.build_tree_contents([('a', 'content 1')]) |
176 | + tree.set_root_id(b'TREE_ROOT') |
177 | + tree.add('a') |
178 | + os.symlink('a', 'foo') |
179 | + tree.add('foo', b'foo-id') |
180 | + revid1 = tree.commit('rev1') |
181 | + revision_tree = tree.branch.repository.revision_tree(revid1) |
182 | + preview = revision_tree.preview_transform() |
183 | + self.addCleanup(preview.finalize) |
184 | + preview.delete_versioned(preview.trans_id_tree_path('foo')) |
185 | + preview_tree = preview.get_preview_tree() |
186 | + out = BytesIO() |
187 | + log = BytesIO() |
188 | + trace.push_log_file(log) |
189 | + os_symlink = getattr(os, 'symlink', None) |
190 | + os.symlink = None |
191 | + try: |
192 | + show_diff_trees(revision_tree, preview_tree, out) |
193 | + lines = out.getvalue().splitlines() |
194 | + finally: |
195 | + os.symlink = os_symlink |
196 | + self.assertContainsRe( |
197 | + log.getvalue(), |
198 | + b'Ignoring "foo" as symlinks are not supported on this filesystem') |
199 | + |
200 | + def test_transform_conflicts(self): |
201 | + revision_tree = self.create_tree() |
202 | + preview = revision_tree.preview_transform() |
203 | + self.addCleanup(preview.finalize) |
204 | + preview.new_file('a', preview.root, [b'content 2']) |
205 | + resolve_conflicts(preview) |
206 | + trans_id = preview.trans_id_file_id(b'a-id') |
207 | + self.assertEqual('a.moved', preview.final_name(trans_id)) |
208 | + |
209 | + def get_tree_and_preview_tree(self): |
210 | + revision_tree = self.create_tree() |
211 | + preview = revision_tree.preview_transform() |
212 | + self.addCleanup(preview.finalize) |
213 | + a_trans_id = preview.trans_id_file_id(b'a-id') |
214 | + preview.delete_contents(a_trans_id) |
215 | + preview.create_file([b'b content'], a_trans_id) |
216 | + preview_tree = preview.get_preview_tree() |
217 | + return revision_tree, preview_tree |
218 | + |
219 | + def test_iter_changes(self): |
220 | + revision_tree, preview_tree = self.get_tree_and_preview_tree() |
221 | + root = revision_tree.path2id('') |
222 | + self.assertEqual([(b'a-id', ('a', 'a'), True, (True, True), |
223 | + (root, root), ('a', 'a'), ('file', 'file'), |
224 | + (False, False), False)], |
225 | + list(preview_tree.iter_changes(revision_tree))) |
226 | + |
227 | + def test_include_unchanged_succeeds(self): |
228 | + revision_tree, preview_tree = self.get_tree_and_preview_tree() |
229 | + changes = preview_tree.iter_changes(revision_tree, |
230 | + include_unchanged=True) |
231 | + self.assertEqual([ROOT_ENTRY, A_ENTRY], list(changes)) |
232 | + |
233 | + def test_specific_files(self): |
234 | + revision_tree, preview_tree = self.get_tree_and_preview_tree() |
235 | + changes = preview_tree.iter_changes(revision_tree, |
236 | + specific_files=['']) |
237 | + self.assertEqual([A_ENTRY], list(changes)) |
238 | + |
239 | + def test_want_unversioned(self): |
240 | + revision_tree, preview_tree = self.get_tree_and_preview_tree() |
241 | + changes = preview_tree.iter_changes(revision_tree, |
242 | + want_unversioned=True) |
243 | + self.assertEqual([A_ENTRY], list(changes)) |
244 | + |
245 | + def test_ignore_extra_trees_no_specific_files(self): |
246 | + # extra_trees is harmless without specific_files, so we'll silently |
247 | + # accept it, even though we won't use it. |
248 | + revision_tree, preview_tree = self.get_tree_and_preview_tree() |
249 | + preview_tree.iter_changes(revision_tree, extra_trees=[preview_tree]) |
250 | + |
251 | + def test_ignore_require_versioned_no_specific_files(self): |
252 | + # require_versioned is meaningless without specific_files. |
253 | + revision_tree, preview_tree = self.get_tree_and_preview_tree() |
254 | + preview_tree.iter_changes(revision_tree, require_versioned=False) |
255 | + |
256 | + def test_ignore_pb(self): |
257 | + # pb could be supported, but TT.iter_changes doesn't support it. |
258 | + revision_tree, preview_tree = self.get_tree_and_preview_tree() |
259 | + preview_tree.iter_changes(revision_tree) |
260 | + |
261 | + def test_kind(self): |
262 | + revision_tree = self.create_tree() |
263 | + preview = revision_tree.preview_transform() |
264 | + self.addCleanup(preview.finalize) |
265 | + preview.new_file('file', preview.root, [b'contents'], b'file-id') |
266 | + preview.new_directory('directory', preview.root, b'dir-id') |
267 | + preview_tree = preview.get_preview_tree() |
268 | + self.assertEqual('file', preview_tree.kind('file')) |
269 | + self.assertEqual('directory', preview_tree.kind('directory')) |
270 | + |
271 | + def test_get_file_mtime(self): |
272 | + preview = self.get_empty_preview() |
273 | + file_trans_id = preview.new_file('file', preview.root, [b'contents'], |
274 | + b'file-id') |
275 | + limbo_path = preview._limbo_name(file_trans_id) |
276 | + preview_tree = preview.get_preview_tree() |
277 | + self.assertEqual(os.stat(limbo_path).st_mtime, |
278 | + preview_tree.get_file_mtime('file')) |
279 | + |
280 | + def test_get_file_mtime_renamed(self): |
281 | + work_tree = self.make_branch_and_tree('tree') |
282 | + self.build_tree(['tree/file']) |
283 | + work_tree.add('file', b'file-id') |
284 | + preview = work_tree.preview_transform() |
285 | + self.addCleanup(preview.finalize) |
286 | + file_trans_id = preview.trans_id_tree_path('file') |
287 | + preview.adjust_path('renamed', preview.root, file_trans_id) |
288 | + preview_tree = preview.get_preview_tree() |
289 | + preview_mtime = preview_tree.get_file_mtime('renamed') |
290 | + work_mtime = work_tree.get_file_mtime('file') |
291 | + |
292 | + def test_get_file_size(self): |
293 | + work_tree = self.make_branch_and_tree('tree') |
294 | + self.build_tree_contents([('tree/old', b'old')]) |
295 | + work_tree.add('old', b'old-id') |
296 | + preview = work_tree.preview_transform() |
297 | + self.addCleanup(preview.finalize) |
298 | + preview.new_file('name', preview.root, [b'contents'], b'new-id', |
299 | + 'executable') |
300 | + tree = preview.get_preview_tree() |
301 | + self.assertEqual(len('old'), tree.get_file_size('old')) |
302 | + self.assertEqual(len('contents'), tree.get_file_size('name')) |
303 | + |
304 | + def test_get_file(self): |
305 | + preview = self.get_empty_preview() |
306 | + preview.new_file('file', preview.root, [b'contents'], b'file-id') |
307 | + preview_tree = preview.get_preview_tree() |
308 | + with preview_tree.get_file('file') as tree_file: |
309 | + self.assertEqual(b'contents', tree_file.read()) |
310 | + |
311 | + def test_get_symlink_target(self): |
312 | + self.requireFeature(SymlinkFeature) |
313 | + preview = self.get_empty_preview() |
314 | + preview.new_symlink('symlink', preview.root, 'target', b'symlink-id') |
315 | + preview_tree = preview.get_preview_tree() |
316 | + self.assertEqual('target', |
317 | + preview_tree.get_symlink_target('symlink')) |
318 | + |
319 | + def test_all_file_ids(self): |
320 | + tree = self.make_branch_and_tree('tree') |
321 | + self.build_tree(['tree/a', 'tree/b', 'tree/c']) |
322 | + tree.add(['a', 'b', 'c'], [b'a-id', b'b-id', b'c-id']) |
323 | + preview = tree.preview_transform() |
324 | + self.addCleanup(preview.finalize) |
325 | + preview.unversion_file(preview.trans_id_file_id(b'b-id')) |
326 | + c_trans_id = preview.trans_id_file_id(b'c-id') |
327 | + preview.unversion_file(c_trans_id) |
328 | + preview.version_file(c_trans_id, file_id=b'c-id') |
329 | + preview_tree = preview.get_preview_tree() |
330 | + self.assertEqual({b'a-id', b'c-id', tree.path2id('')}, |
331 | + preview_tree.all_file_ids()) |
332 | + |
333 | + def test_path2id_deleted_unchanged(self): |
334 | + tree = self.make_branch_and_tree('tree') |
335 | + self.build_tree(['tree/unchanged', 'tree/deleted']) |
336 | + tree.add(['unchanged', 'deleted']) |
337 | + preview = tree.preview_transform() |
338 | + self.addCleanup(preview.finalize) |
339 | + preview.unversion_file(preview.trans_id_tree_path('deleted')) |
340 | + preview_tree = preview.get_preview_tree() |
341 | + self.assertEqual( |
342 | + 'unchanged', |
343 | + find_previous_path(preview_tree, tree, 'unchanged')) |
344 | + self.assertFalse(preview_tree.is_versioned('deleted')) |
345 | + |
346 | + def test_path2id_created(self): |
347 | + tree = self.make_branch_and_tree('tree') |
348 | + self.build_tree(['tree/unchanged']) |
349 | + tree.add(['unchanged']) |
350 | + preview = tree.preview_transform() |
351 | + self.addCleanup(preview.finalize) |
352 | + preview.new_file('new', preview.trans_id_tree_path('unchanged'), |
353 | + [b'contents'], b'new-id') |
354 | + preview_tree = preview.get_preview_tree() |
355 | + self.assertEqual(b'new-id', preview_tree.path2id('unchanged/new')) |
356 | + |
357 | + def test_path2id_moved(self): |
358 | + tree = self.make_branch_and_tree('tree') |
359 | + self.build_tree(['tree/old_parent/', 'tree/old_parent/child']) |
360 | + tree.add(['old_parent', 'old_parent/child'], |
361 | + [b'old_parent-id', b'child-id']) |
362 | + preview = tree.preview_transform() |
363 | + self.addCleanup(preview.finalize) |
364 | + new_parent = preview.new_directory('new_parent', preview.root, |
365 | + b'new_parent-id') |
366 | + preview.adjust_path('child', new_parent, |
367 | + preview.trans_id_file_id(b'child-id')) |
368 | + preview_tree = preview.get_preview_tree() |
369 | + self.assertFalse(preview_tree.is_versioned('old_parent/child')) |
370 | + self.assertEqual(b'child-id', preview_tree.path2id('new_parent/child')) |
371 | + |
372 | + def test_path2id_renamed_parent(self): |
373 | + tree = self.make_branch_and_tree('tree') |
374 | + self.build_tree(['tree/old_name/', 'tree/old_name/child']) |
375 | + tree.add(['old_name', 'old_name/child'], |
376 | + [b'parent-id', b'child-id']) |
377 | + preview = tree.preview_transform() |
378 | + self.addCleanup(preview.finalize) |
379 | + preview.adjust_path('new_name', preview.root, |
380 | + preview.trans_id_file_id(b'parent-id')) |
381 | + preview_tree = preview.get_preview_tree() |
382 | + self.assertFalse(preview_tree.is_versioned('old_name/child')) |
383 | + self.assertEqual(b'child-id', preview_tree.path2id('new_name/child')) |
384 | + |
385 | + def assertMatchingIterEntries(self, tt, specific_files=None): |
386 | + preview_tree = tt.get_preview_tree() |
387 | + preview_result = list(preview_tree.iter_entries_by_dir( |
388 | + specific_files=specific_files)) |
389 | + tree = tt._tree |
390 | + tt.apply() |
391 | + actual_result = list(tree.iter_entries_by_dir( |
392 | + specific_files=specific_files)) |
393 | + self.assertEqual(actual_result, preview_result) |
394 | + |
395 | + def test_iter_entries_by_dir_new(self): |
396 | + tree = self.make_branch_and_tree('tree') |
397 | + tt = tree.transform() |
398 | + tt.new_file('new', tt.root, [b'contents'], b'new-id') |
399 | + self.assertMatchingIterEntries(tt) |
400 | + |
401 | + def test_iter_entries_by_dir_deleted(self): |
402 | + tree = self.make_branch_and_tree('tree') |
403 | + self.build_tree(['tree/deleted']) |
404 | + tree.add('deleted', b'deleted-id') |
405 | + tt = tree.transform() |
406 | + tt.delete_contents(tt.trans_id_file_id(b'deleted-id')) |
407 | + self.assertMatchingIterEntries(tt) |
408 | + |
409 | + def test_iter_entries_by_dir_unversioned(self): |
410 | + tree = self.make_branch_and_tree('tree') |
411 | + self.build_tree(['tree/removed']) |
412 | + tree.add('removed', b'removed-id') |
413 | + tt = tree.transform() |
414 | + tt.unversion_file(tt.trans_id_file_id(b'removed-id')) |
415 | + self.assertMatchingIterEntries(tt) |
416 | + |
417 | + def test_iter_entries_by_dir_moved(self): |
418 | + tree = self.make_branch_and_tree('tree') |
419 | + self.build_tree(['tree/moved', 'tree/new_parent/']) |
420 | + tree.add(['moved', 'new_parent'], [b'moved-id', b'new_parent-id']) |
421 | + tt = tree.transform() |
422 | + tt.adjust_path('moved', tt.trans_id_file_id(b'new_parent-id'), |
423 | + tt.trans_id_file_id(b'moved-id')) |
424 | + self.assertMatchingIterEntries(tt) |
425 | + |
426 | + def test_iter_entries_by_dir_specific_files(self): |
427 | + tree = self.make_branch_and_tree('tree') |
428 | + tree.set_root_id(b'tree-root-id') |
429 | + self.build_tree(['tree/parent/', 'tree/parent/child']) |
430 | + tree.add(['parent', 'parent/child'], [b'parent-id', b'child-id']) |
431 | + tt = tree.transform() |
432 | + self.assertMatchingIterEntries(tt, ['', 'parent/child']) |
433 | + |
434 | + def test_symlink_content_summary(self): |
435 | + self.requireFeature(SymlinkFeature) |
436 | + preview = self.get_empty_preview() |
437 | + preview.new_symlink('path', preview.root, 'target', b'path-id') |
438 | + summary = preview.get_preview_tree().path_content_summary('path') |
439 | + self.assertEqual(('symlink', None, None, 'target'), summary) |
440 | + |
441 | + def test_missing_content_summary(self): |
442 | + preview = self.get_empty_preview() |
443 | + summary = preview.get_preview_tree().path_content_summary('path') |
444 | + self.assertEqual(('missing', None, None, None), summary) |
445 | + |
446 | + def test_deleted_content_summary(self): |
447 | + tree = self.make_branch_and_tree('tree') |
448 | + self.build_tree(['tree/path/']) |
449 | + tree.add('path') |
450 | + preview = tree.preview_transform() |
451 | + self.addCleanup(preview.finalize) |
452 | + preview.delete_contents(preview.trans_id_tree_path('path')) |
453 | + summary = preview.get_preview_tree().path_content_summary('path') |
454 | + self.assertEqual(('missing', None, None, None), summary) |
455 | + |
456 | + def test_file_content_summary_executable(self): |
457 | + preview = self.get_empty_preview() |
458 | + path_id = preview.new_file('path', preview.root, [ |
459 | + b'contents'], b'path-id') |
460 | + preview.set_executability(True, path_id) |
461 | + summary = preview.get_preview_tree().path_content_summary('path') |
462 | + self.assertEqual(4, len(summary)) |
463 | + self.assertEqual('file', summary[0]) |
464 | + # size must be known |
465 | + self.assertEqual(len('contents'), summary[1]) |
466 | + # executable |
467 | + self.assertEqual(True, summary[2]) |
468 | + # will not have hash (not cheap to determine) |
469 | + self.assertIs(None, summary[3]) |
470 | + |
471 | + def test_change_executability(self): |
472 | + tree = self.make_branch_and_tree('tree') |
473 | + self.build_tree(['tree/path']) |
474 | + tree.add('path') |
475 | + preview = tree.preview_transform() |
476 | + self.addCleanup(preview.finalize) |
477 | + path_id = preview.trans_id_tree_path('path') |
478 | + preview.set_executability(True, path_id) |
479 | + summary = preview.get_preview_tree().path_content_summary('path') |
480 | + self.assertEqual(True, summary[2]) |
481 | + |
482 | + def test_file_content_summary_non_exec(self): |
483 | + preview = self.get_empty_preview() |
484 | + preview.new_file('path', preview.root, [b'contents'], b'path-id') |
485 | + summary = preview.get_preview_tree().path_content_summary('path') |
486 | + self.assertEqual(4, len(summary)) |
487 | + self.assertEqual('file', summary[0]) |
488 | + # size must be known |
489 | + self.assertEqual(len('contents'), summary[1]) |
490 | + # not executable |
491 | + self.assertEqual(False, summary[2]) |
492 | + # will not have hash (not cheap to determine) |
493 | + self.assertIs(None, summary[3]) |
494 | + |
495 | + def test_dir_content_summary(self): |
496 | + preview = self.get_empty_preview() |
497 | + preview.new_directory('path', preview.root, b'path-id') |
498 | + summary = preview.get_preview_tree().path_content_summary('path') |
499 | + self.assertEqual(('directory', None, None, None), summary) |
500 | + |
501 | + def test_tree_content_summary(self): |
502 | + preview = self.get_empty_preview() |
503 | + path = preview.new_directory('path', preview.root, b'path-id') |
504 | + preview.set_tree_reference(b'rev-1', path) |
505 | + summary = preview.get_preview_tree().path_content_summary('path') |
506 | + self.assertEqual(4, len(summary)) |
507 | + self.assertEqual('tree-reference', summary[0]) |
508 | + |
509 | + def test_annotate(self): |
510 | + tree = self.make_branch_and_tree('tree') |
511 | + self.build_tree_contents([('tree/file', b'a\n')]) |
512 | + tree.add('file', b'file-id') |
513 | + revid1 = tree.commit('a') |
514 | + self.build_tree_contents([('tree/file', b'a\nb\n')]) |
515 | + preview = tree.preview_transform() |
516 | + self.addCleanup(preview.finalize) |
517 | + file_trans_id = preview.trans_id_file_id(b'file-id') |
518 | + preview.delete_contents(file_trans_id) |
519 | + preview.create_file([b'a\nb\nc\n'], file_trans_id) |
520 | + preview_tree = preview.get_preview_tree() |
521 | + expected = [ |
522 | + (revid1, b'a\n'), |
523 | + (b'me:', b'b\n'), |
524 | + (b'me:', b'c\n'), |
525 | + ] |
526 | + annotation = preview_tree.annotate_iter( |
527 | + 'file', default_revision=b'me:') |
528 | + self.assertEqual(expected, annotation) |
529 | + |
530 | + def test_annotate_missing(self): |
531 | + preview = self.get_empty_preview() |
532 | + preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id') |
533 | + preview_tree = preview.get_preview_tree() |
534 | + expected = [ |
535 | + (b'me:', b'a\n'), |
536 | + (b'me:', b'b\n'), |
537 | + (b'me:', b'c\n'), |
538 | + ] |
539 | + annotation = preview_tree.annotate_iter( |
540 | + 'file', default_revision=b'me:') |
541 | + self.assertEqual(expected, annotation) |
542 | + |
543 | + def test_annotate_rename(self): |
544 | + tree = self.make_branch_and_tree('tree') |
545 | + self.build_tree_contents([('tree/file', b'a\n')]) |
546 | + tree.add('file') |
547 | + revid1 = tree.commit('a') |
548 | + preview = tree.preview_transform() |
549 | + self.addCleanup(preview.finalize) |
550 | + file_trans_id = preview.trans_id_tree_path('file') |
551 | + preview.adjust_path('newname', preview.root, file_trans_id) |
552 | + preview_tree = preview.get_preview_tree() |
553 | + expected = [ |
554 | + (revid1, b'a\n'), |
555 | + ] |
556 | + annotation = preview_tree.annotate_iter( |
557 | + 'file', default_revision=b'me:') |
558 | + self.assertEqual(expected, annotation) |
559 | + |
560 | + def test_annotate_deleted(self): |
561 | + tree = self.make_branch_and_tree('tree') |
562 | + self.build_tree_contents([('tree/file', b'a\n')]) |
563 | + tree.add('file') |
564 | + tree.commit('a') |
565 | + self.build_tree_contents([('tree/file', b'a\nb\n')]) |
566 | + preview = tree.preview_transform() |
567 | + self.addCleanup(preview.finalize) |
568 | + file_trans_id = preview.trans_id_tree_path('file') |
569 | + preview.delete_contents(file_trans_id) |
570 | + preview_tree = preview.get_preview_tree() |
571 | + annotation = preview_tree.annotate_iter( |
572 | + 'file', default_revision=b'me:') |
573 | + self.assertIs(None, annotation) |
574 | + |
575 | + def test_stored_kind(self): |
576 | + preview = self.get_empty_preview() |
577 | + preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id') |
578 | + preview_tree = preview.get_preview_tree() |
579 | + self.assertEqual('file', preview_tree.stored_kind('file')) |
580 | + |
581 | + def test_is_executable(self): |
582 | + preview = self.get_empty_preview() |
583 | + preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id') |
584 | + preview.set_executability(True, preview.trans_id_file_id(b'file-id')) |
585 | + preview_tree = preview.get_preview_tree() |
586 | + self.assertEqual(True, preview_tree.is_executable('file')) |
587 | + |
588 | + def test_get_set_parent_ids(self): |
589 | + revision_tree, preview_tree = self.get_tree_and_preview_tree() |
590 | + self.assertEqual([], preview_tree.get_parent_ids()) |
591 | + preview_tree.set_parent_ids([revision_tree.get_revision_id()]) |
592 | + self.assertEqual( |
593 | + [revision_tree.get_revision_id()], |
594 | + preview_tree.get_parent_ids()) |
595 | + |
596 | + def test_plan_file_merge(self): |
597 | + work_a = self.make_branch_and_tree('wta') |
598 | + self.build_tree_contents([('wta/file', b'a\nb\nc\nd\n')]) |
599 | + work_a.add('file') |
600 | + base_id = work_a.commit('base version') |
601 | + tree_b = work_a.controldir.sprout('wtb').open_workingtree() |
602 | + preview = work_a.preview_transform() |
603 | + self.addCleanup(preview.finalize) |
604 | + trans_id = preview.trans_id_tree_path('file') |
605 | + preview.delete_contents(trans_id) |
606 | + preview.create_file([b'b\nc\nd\ne\n'], trans_id) |
607 | + self.build_tree_contents([('wtb/file', b'a\nc\nd\nf\n')]) |
608 | + tree_a = preview.get_preview_tree() |
609 | + tree_a.set_parent_ids([base_id]) |
610 | + self.addCleanup(tree_b.lock_read().unlock) |
611 | + self.assertEqual([ |
612 | + ('killed-a', b'a\n'), |
613 | + ('killed-b', b'b\n'), |
614 | + ('unchanged', b'c\n'), |
615 | + ('unchanged', b'd\n'), |
616 | + ('new-a', b'e\n'), |
617 | + ('new-b', b'f\n'), |
618 | + ], list(tree_a.plan_file_merge('file', tree_b))) |
619 | + |
620 | + def test_plan_file_merge_revision_tree(self): |
621 | + work_a = self.make_branch_and_tree('wta') |
622 | + self.build_tree_contents([('wta/file', b'a\nb\nc\nd\n')]) |
623 | + work_a.add('file') |
624 | + base_id = work_a.commit('base version') |
625 | + tree_b = work_a.controldir.sprout('wtb').open_workingtree() |
626 | + preview = work_a.basis_tree().preview_transform() |
627 | + self.addCleanup(preview.finalize) |
628 | + trans_id = preview.trans_id_tree_path('file') |
629 | + preview.delete_contents(trans_id) |
630 | + preview.create_file([b'b\nc\nd\ne\n'], trans_id) |
631 | + self.build_tree_contents([('wtb/file', b'a\nc\nd\nf\n')]) |
632 | + tree_a = preview.get_preview_tree() |
633 | + tree_a.set_parent_ids([base_id]) |
634 | + self.addCleanup(tree_b.lock_read().unlock) |
635 | + self.assertEqual([ |
636 | + ('killed-a', b'a\n'), |
637 | + ('killed-b', b'b\n'), |
638 | + ('unchanged', b'c\n'), |
639 | + ('unchanged', b'd\n'), |
640 | + ('new-a', b'e\n'), |
641 | + ('new-b', b'f\n'), |
642 | + ], list(tree_a.plan_file_merge('file', tree_b))) |
643 | + |
644 | + def test_walkdirs(self): |
645 | + preview = self.get_empty_preview() |
646 | + preview.new_directory('', ROOT_PARENT, b'tree-root') |
647 | + # FIXME: new_directory should mark root. |
648 | + preview.fixup_new_roots() |
649 | + preview_tree = preview.get_preview_tree() |
650 | + preview.new_file('a', preview.root, [b'contents'], b'a-id') |
651 | + expected = [(('', b'tree-root'), |
652 | + [('a', 'a', 'file', None, b'a-id', 'file')])] |
653 | + self.assertEqual(expected, list(preview_tree.walkdirs())) |
654 | + |
655 | + def test_extras(self): |
656 | + work_tree = self.make_branch_and_tree('tree') |
657 | + self.build_tree(['tree/removed-file', 'tree/existing-file', |
658 | + 'tree/not-removed-file']) |
659 | + work_tree.add(['removed-file', 'not-removed-file']) |
660 | + preview = work_tree.preview_transform() |
661 | + self.addCleanup(preview.finalize) |
662 | + preview.new_file('new-file', preview.root, [b'contents']) |
663 | + preview.new_file('new-versioned-file', preview.root, [b'contents'], |
664 | + b'new-versioned-id') |
665 | + tree = preview.get_preview_tree() |
666 | + preview.unversion_file(preview.trans_id_tree_path('removed-file')) |
667 | + self.assertEqual({'new-file', 'removed-file', 'existing-file'}, |
668 | + set(tree.extras())) |
669 | + |
670 | + def test_merge_into_preview(self): |
671 | + work_tree = self.make_branch_and_tree('tree') |
672 | + self.build_tree_contents([('tree/file', b'b\n')]) |
673 | + work_tree.add('file') |
674 | + work_tree.commit('first commit') |
675 | + child_tree = work_tree.controldir.sprout('child').open_workingtree() |
676 | + self.build_tree_contents([('child/file', b'b\nc\n')]) |
677 | + child_tree.commit('child commit') |
678 | + child_tree.lock_write() |
679 | + self.addCleanup(child_tree.unlock) |
680 | + work_tree.lock_write() |
681 | + self.addCleanup(work_tree.unlock) |
682 | + preview = work_tree.preview_transform() |
683 | + self.addCleanup(preview.finalize) |
684 | + file_trans_id = preview.trans_id_tree_path('file') |
685 | + preview.delete_contents(file_trans_id) |
686 | + preview.create_file([b'a\nb\n'], file_trans_id) |
687 | + preview_tree = preview.get_preview_tree() |
688 | + merger = Merger.from_revision_ids(preview_tree, |
689 | + child_tree.branch.last_revision(), |
690 | + other_branch=child_tree.branch, |
691 | + tree_branch=work_tree.branch) |
692 | + merger.merge_type = Merge3Merger |
693 | + tt = merger.make_merger().make_preview_transform() |
694 | + self.addCleanup(tt.finalize) |
695 | + final_tree = tt.get_preview_tree() |
696 | + self.assertEqual( |
697 | + b'a\nb\nc\n', |
698 | + final_tree.get_file_text('file')) |
699 | + |
700 | + def test_merge_preview_into_workingtree(self): |
701 | + tree = self.make_branch_and_tree('tree') |
702 | + tree.set_root_id(b'TREE_ROOT') |
703 | + tt = tree.preview_transform() |
704 | + self.addCleanup(tt.finalize) |
705 | + tt.new_file('name', tt.root, [b'content'], b'file-id') |
706 | + tree2 = self.make_branch_and_tree('tree2') |
707 | + tree2.set_root_id(b'TREE_ROOT') |
708 | + merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(), |
709 | + tree.basis_tree()) |
710 | + merger.merge_type = Merge3Merger |
711 | + merger.do_merge() |
712 | + |
713 | + def test_merge_preview_into_workingtree_handles_conflicts(self): |
714 | + tree = self.make_branch_and_tree('tree') |
715 | + self.build_tree_contents([('tree/foo', b'bar')]) |
716 | + tree.add('foo', b'foo-id') |
717 | + tree.commit('foo') |
718 | + tt = tree.preview_transform() |
719 | + self.addCleanup(tt.finalize) |
720 | + trans_id = tt.trans_id_file_id(b'foo-id') |
721 | + tt.delete_contents(trans_id) |
722 | + tt.create_file([b'baz'], trans_id) |
723 | + tree2 = tree.controldir.sprout('tree2').open_workingtree() |
724 | + self.build_tree_contents([('tree2/foo', b'qux')]) |
725 | + merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(), |
726 | + tree.basis_tree()) |
727 | + merger.merge_type = Merge3Merger |
728 | + merger.do_merge() |
729 | + |
730 | + def test_has_filename(self): |
731 | + wt = self.make_branch_and_tree('tree') |
732 | + self.build_tree(['tree/unmodified', 'tree/removed', 'tree/modified']) |
733 | + tt = wt.preview_transform() |
734 | + removed_id = tt.trans_id_tree_path('removed') |
735 | + tt.delete_contents(removed_id) |
736 | + tt.new_file('new', tt.root, [b'contents']) |
737 | + modified_id = tt.trans_id_tree_path('modified') |
738 | + tt.delete_contents(modified_id) |
739 | + tt.create_file([b'modified-contents'], modified_id) |
740 | + self.addCleanup(tt.finalize) |
741 | + tree = tt.get_preview_tree() |
742 | + self.assertTrue(tree.has_filename('unmodified')) |
743 | + self.assertFalse(tree.has_filename('not-present')) |
744 | + self.assertFalse(tree.has_filename('removed')) |
745 | + self.assertTrue(tree.has_filename('new')) |
746 | + self.assertTrue(tree.has_filename('modified')) |
747 | + |
748 | + def test_is_executable(self): |
749 | + tree = self.make_branch_and_tree('tree') |
750 | + preview = tree.preview_transform() |
751 | + self.addCleanup(preview.finalize) |
752 | + preview.new_file('foo', preview.root, [b'bar'], b'baz-id') |
753 | + preview_tree = preview.get_preview_tree() |
754 | + self.assertEqual(False, preview_tree.is_executable('tree/foo')) |
755 | + |
756 | + def test_commit_preview_tree(self): |
757 | + tree = self.make_branch_and_tree('tree') |
758 | + rev_id = tree.commit('rev1') |
759 | + tree.branch.lock_write() |
760 | + self.addCleanup(tree.branch.unlock) |
761 | + tt = tree.preview_transform() |
762 | + tt.new_file('file', tt.root, [b'contents'], b'file_id') |
763 | + self.addCleanup(tt.finalize) |
764 | + preview = tt.get_preview_tree() |
765 | + preview.set_parent_ids([rev_id]) |
766 | + builder = tree.branch.get_commit_builder([rev_id]) |
767 | + list(builder.record_iter_changes(preview, rev_id, tt.iter_changes())) |
768 | + builder.finish_inventory() |
769 | + rev2_id = builder.commit('rev2') |
770 | + rev2_tree = tree.branch.repository.revision_tree(rev2_id) |
771 | + self.assertEqual(b'contents', rev2_tree.get_file_text('file')) |
772 | + |
773 | + def test_ascii_limbo_paths(self): |
774 | + self.requireFeature(UnicodeFilenameFeature) |
775 | + branch = self.make_branch('any') |
776 | + tree = branch.repository.revision_tree(_mod_revision.NULL_REVISION) |
777 | + tt = tree.preview_transform() |
778 | + self.addCleanup(tt.finalize) |
779 | + foo_id = tt.new_directory('', ROOT_PARENT) |
780 | + bar_id = tt.new_file(u'\u1234bar', foo_id, [b'contents']) |
781 | + limbo_path = tt._limbo_name(bar_id) |
782 | + self.assertEqual(limbo_path, limbo_path) |
783 | |
784 | === modified file 'breezy/tests/per_workingtree/test_transform.py' |
785 | --- breezy/tests/per_workingtree/test_transform.py 2020-07-04 14:58:52 +0000 |
786 | +++ breezy/tests/per_workingtree/test_transform.py 2020-07-05 00:45:38 +0000 |
787 | @@ -72,12 +72,16 @@ |
788 | ReusingTransform, |
789 | ) |
790 | |
791 | - |
792 | - |
793 | -class TestTreeTransform(tests.TestCaseWithTransport): |
794 | +from breezy.tests.per_workingtree import TestCaseWithWorkingTree |
795 | + |
796 | + |
797 | + |
798 | +class TestTreeTransform(TestCaseWithWorkingTree): |
799 | |
800 | def setUp(self): |
801 | super(TestTreeTransform, self).setUp() |
802 | + if not self.workingtree_format.supports_setting_file_ids: |
803 | + self.skipTest('test not compatible with non-file-id trees yet') |
804 | self.wt = self.make_branch_and_tree('wt') |
805 | |
806 | def transform(self): |
807 | @@ -385,6 +389,10 @@ |
808 | def test_tree_reference(self): |
809 | transform, root = self.transform() |
810 | tree = transform._tree |
811 | + if not tree.supports_tree_reference(): |
812 | + raise tests.TestNotApplicable( |
813 | + 'Tree format does not support references') |
814 | + |
815 | trans_id = transform.new_directory('reference', root, b'subtree-id') |
816 | transform.set_tree_reference(b'subtree-revision', trans_id) |
817 | transform.apply() |
818 | @@ -1643,7 +1651,7 @@ |
819 | def test_create_from_tree(self): |
820 | tree1 = self.make_branch_and_tree('tree1') |
821 | self.build_tree_contents([('tree1/foo/',), ('tree1/bar', b'baz')]) |
822 | - tree1.add(['foo', 'bar'], [b'foo-id', b'bar-id']) |
823 | + tree1.add(['foo', 'bar']) |
824 | tree2 = self.make_branch_and_tree('tree2') |
825 | tt = tree2.transform() |
826 | foo_trans_id = tt.create_path('foo', tt.root) |
827 | @@ -1658,7 +1666,7 @@ |
828 | """Provided lines are used instead of tree content.""" |
829 | tree1 = self.make_branch_and_tree('tree1') |
830 | self.build_tree_contents([('tree1/foo', b'bar'), ]) |
831 | - tree1.add('foo', b'foo-id') |
832 | + tree1.add('foo') |
833 | tree2 = self.make_branch_and_tree('tree2') |
834 | tt = tree2.transform() |
835 | foo_trans_id = tt.create_path('foo', tt.root) |
836 | @@ -1670,7 +1678,7 @@ |
837 | self.requireFeature(SymlinkFeature) |
838 | tree1 = self.make_branch_and_tree('tree1') |
839 | os.symlink('bar', 'tree1/foo') |
840 | - tree1.add('foo', b'foo-id') |
841 | + tree1.add('foo') |
842 | tt = self.make_branch_and_tree('tree2').transform() |
843 | foo_trans_id = tt.create_path('foo', tt.root) |
844 | create_from_tree(tt, foo_trans_id, tree1, 'foo') |
845 | |
846 | === modified file 'breezy/tests/test_transform.py' |
847 | --- breezy/tests/test_transform.py 2020-07-04 13:53:04 +0000 |
848 | +++ breezy/tests/test_transform.py 2020-07-05 00:45:38 +0000 |
849 | @@ -1160,671 +1160,6 @@ |
850 | conflicts.pop()) |
851 | |
852 | |
853 | -A_ENTRY = (b'a-id', ('a', 'a'), True, (True, True), |
854 | - (b'TREE_ROOT', b'TREE_ROOT'), ('a', 'a'), ('file', 'file'), |
855 | - (False, False), False) |
856 | -ROOT_ENTRY = (b'TREE_ROOT', ('', ''), False, (True, True), (None, None), |
857 | - ('', ''), ('directory', 'directory'), (False, False), False) |
858 | - |
859 | - |
860 | -class TestTransformPreview(tests.TestCaseWithTransport): |
861 | - |
862 | - def create_tree(self): |
863 | - tree = self.make_branch_and_tree('.') |
864 | - self.build_tree_contents([('a', b'content 1')]) |
865 | - tree.set_root_id(b'TREE_ROOT') |
866 | - tree.add('a', b'a-id') |
867 | - tree.commit('rev1', rev_id=b'rev1') |
868 | - return tree.branch.repository.revision_tree(b'rev1') |
869 | - |
870 | - def get_empty_preview(self): |
871 | - repository = self.make_repository('repo') |
872 | - tree = repository.revision_tree(_mod_revision.NULL_REVISION) |
873 | - preview = tree.preview_transform() |
874 | - self.addCleanup(preview.finalize) |
875 | - return preview |
876 | - |
877 | - def test_transform_preview(self): |
878 | - revision_tree = self.create_tree() |
879 | - preview = revision_tree.preview_transform() |
880 | - self.addCleanup(preview.finalize) |
881 | - |
882 | - def test_transform_preview_tree(self): |
883 | - revision_tree = self.create_tree() |
884 | - preview = revision_tree.preview_transform() |
885 | - self.addCleanup(preview.finalize) |
886 | - preview.get_preview_tree() |
887 | - |
888 | - def test_transform_new_file(self): |
889 | - revision_tree = self.create_tree() |
890 | - preview = revision_tree.preview_transform() |
891 | - self.addCleanup(preview.finalize) |
892 | - preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id') |
893 | - preview_tree = preview.get_preview_tree() |
894 | - self.assertEqual(preview_tree.kind('file2'), 'file') |
895 | - with preview_tree.get_file('file2') as f: |
896 | - self.assertEqual(f.read(), b'content B\n') |
897 | - |
898 | - def test_diff_preview_tree(self): |
899 | - revision_tree = self.create_tree() |
900 | - preview = revision_tree.preview_transform() |
901 | - self.addCleanup(preview.finalize) |
902 | - preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id') |
903 | - preview_tree = preview.get_preview_tree() |
904 | - out = BytesIO() |
905 | - show_diff_trees(revision_tree, preview_tree, out) |
906 | - lines = out.getvalue().splitlines() |
907 | - self.assertEqual(lines[0], b"=== added file 'file2'") |
908 | - # 3 lines of diff administrivia |
909 | - self.assertEqual(lines[4], b"+content B") |
910 | - |
911 | - def test_unsupported_symlink_diff(self): |
912 | - self.requireFeature(SymlinkFeature) |
913 | - tree = self.make_branch_and_tree('.') |
914 | - self.build_tree_contents([('a', 'content 1')]) |
915 | - tree.set_root_id(b'TREE_ROOT') |
916 | - tree.add('a', b'a-id') |
917 | - os.symlink('a', 'foo') |
918 | - tree.add('foo', b'foo-id') |
919 | - tree.commit('rev1', rev_id=b'rev1') |
920 | - revision_tree = tree.branch.repository.revision_tree(b'rev1') |
921 | - preview = revision_tree.preview_transform() |
922 | - self.addCleanup(preview.finalize) |
923 | - preview.delete_versioned(preview.trans_id_tree_path('foo')) |
924 | - preview_tree = preview.get_preview_tree() |
925 | - out = BytesIO() |
926 | - log = BytesIO() |
927 | - trace.push_log_file(log) |
928 | - os_symlink = getattr(os, 'symlink', None) |
929 | - os.symlink = None |
930 | - try: |
931 | - show_diff_trees(revision_tree, preview_tree, out) |
932 | - lines = out.getvalue().splitlines() |
933 | - finally: |
934 | - os.symlink = os_symlink |
935 | - self.assertContainsRe( |
936 | - log.getvalue(), |
937 | - b'Ignoring "foo" as symlinks are not supported on this filesystem') |
938 | - |
939 | - def test_transform_conflicts(self): |
940 | - revision_tree = self.create_tree() |
941 | - preview = revision_tree.preview_transform() |
942 | - self.addCleanup(preview.finalize) |
943 | - preview.new_file('a', preview.root, [b'content 2']) |
944 | - resolve_conflicts(preview) |
945 | - trans_id = preview.trans_id_file_id(b'a-id') |
946 | - self.assertEqual('a.moved', preview.final_name(trans_id)) |
947 | - |
948 | - def get_tree_and_preview_tree(self): |
949 | - revision_tree = self.create_tree() |
950 | - preview = revision_tree.preview_transform() |
951 | - self.addCleanup(preview.finalize) |
952 | - a_trans_id = preview.trans_id_file_id(b'a-id') |
953 | - preview.delete_contents(a_trans_id) |
954 | - preview.create_file([b'b content'], a_trans_id) |
955 | - preview_tree = preview.get_preview_tree() |
956 | - return revision_tree, preview_tree |
957 | - |
958 | - def test_iter_changes(self): |
959 | - revision_tree, preview_tree = self.get_tree_and_preview_tree() |
960 | - root = revision_tree.path2id('') |
961 | - self.assertEqual([(b'a-id', ('a', 'a'), True, (True, True), |
962 | - (root, root), ('a', 'a'), ('file', 'file'), |
963 | - (False, False), False)], |
964 | - list(preview_tree.iter_changes(revision_tree))) |
965 | - |
966 | - def test_include_unchanged_succeeds(self): |
967 | - revision_tree, preview_tree = self.get_tree_and_preview_tree() |
968 | - changes = preview_tree.iter_changes(revision_tree, |
969 | - include_unchanged=True) |
970 | - self.assertEqual([ROOT_ENTRY, A_ENTRY], list(changes)) |
971 | - |
972 | - def test_specific_files(self): |
973 | - revision_tree, preview_tree = self.get_tree_and_preview_tree() |
974 | - changes = preview_tree.iter_changes(revision_tree, |
975 | - specific_files=['']) |
976 | - self.assertEqual([A_ENTRY], list(changes)) |
977 | - |
978 | - def test_want_unversioned(self): |
979 | - revision_tree, preview_tree = self.get_tree_and_preview_tree() |
980 | - changes = preview_tree.iter_changes(revision_tree, |
981 | - want_unversioned=True) |
982 | - self.assertEqual([A_ENTRY], list(changes)) |
983 | - |
984 | - def test_ignore_extra_trees_no_specific_files(self): |
985 | - # extra_trees is harmless without specific_files, so we'll silently |
986 | - # accept it, even though we won't use it. |
987 | - revision_tree, preview_tree = self.get_tree_and_preview_tree() |
988 | - preview_tree.iter_changes(revision_tree, extra_trees=[preview_tree]) |
989 | - |
990 | - def test_ignore_require_versioned_no_specific_files(self): |
991 | - # require_versioned is meaningless without specific_files. |
992 | - revision_tree, preview_tree = self.get_tree_and_preview_tree() |
993 | - preview_tree.iter_changes(revision_tree, require_versioned=False) |
994 | - |
995 | - def test_ignore_pb(self): |
996 | - # pb could be supported, but TT.iter_changes doesn't support it. |
997 | - revision_tree, preview_tree = self.get_tree_and_preview_tree() |
998 | - preview_tree.iter_changes(revision_tree) |
999 | - |
1000 | - def test_kind(self): |
1001 | - revision_tree = self.create_tree() |
1002 | - preview = revision_tree.preview_transform() |
1003 | - self.addCleanup(preview.finalize) |
1004 | - preview.new_file('file', preview.root, [b'contents'], b'file-id') |
1005 | - preview.new_directory('directory', preview.root, b'dir-id') |
1006 | - preview_tree = preview.get_preview_tree() |
1007 | - self.assertEqual('file', preview_tree.kind('file')) |
1008 | - self.assertEqual('directory', preview_tree.kind('directory')) |
1009 | - |
1010 | - def test_get_file_mtime(self): |
1011 | - preview = self.get_empty_preview() |
1012 | - file_trans_id = preview.new_file('file', preview.root, [b'contents'], |
1013 | - b'file-id') |
1014 | - limbo_path = preview._limbo_name(file_trans_id) |
1015 | - preview_tree = preview.get_preview_tree() |
1016 | - self.assertEqual(os.stat(limbo_path).st_mtime, |
1017 | - preview_tree.get_file_mtime('file')) |
1018 | - |
1019 | - def test_get_file_mtime_renamed(self): |
1020 | - work_tree = self.make_branch_and_tree('tree') |
1021 | - self.build_tree(['tree/file']) |
1022 | - work_tree.add('file', b'file-id') |
1023 | - preview = work_tree.preview_transform() |
1024 | - self.addCleanup(preview.finalize) |
1025 | - file_trans_id = preview.trans_id_tree_path('file') |
1026 | - preview.adjust_path('renamed', preview.root, file_trans_id) |
1027 | - preview_tree = preview.get_preview_tree() |
1028 | - preview_mtime = preview_tree.get_file_mtime('renamed') |
1029 | - work_mtime = work_tree.get_file_mtime('file') |
1030 | - |
1031 | - def test_get_file_size(self): |
1032 | - work_tree = self.make_branch_and_tree('tree') |
1033 | - self.build_tree_contents([('tree/old', b'old')]) |
1034 | - work_tree.add('old', b'old-id') |
1035 | - preview = work_tree.preview_transform() |
1036 | - self.addCleanup(preview.finalize) |
1037 | - preview.new_file('name', preview.root, [b'contents'], b'new-id', |
1038 | - 'executable') |
1039 | - tree = preview.get_preview_tree() |
1040 | - self.assertEqual(len('old'), tree.get_file_size('old')) |
1041 | - self.assertEqual(len('contents'), tree.get_file_size('name')) |
1042 | - |
1043 | - def test_get_file(self): |
1044 | - preview = self.get_empty_preview() |
1045 | - preview.new_file('file', preview.root, [b'contents'], b'file-id') |
1046 | - preview_tree = preview.get_preview_tree() |
1047 | - with preview_tree.get_file('file') as tree_file: |
1048 | - self.assertEqual(b'contents', tree_file.read()) |
1049 | - |
1050 | - def test_get_symlink_target(self): |
1051 | - self.requireFeature(SymlinkFeature) |
1052 | - preview = self.get_empty_preview() |
1053 | - preview.new_symlink('symlink', preview.root, 'target', b'symlink-id') |
1054 | - preview_tree = preview.get_preview_tree() |
1055 | - self.assertEqual('target', |
1056 | - preview_tree.get_symlink_target('symlink')) |
1057 | - |
1058 | - def test_all_file_ids(self): |
1059 | - tree = self.make_branch_and_tree('tree') |
1060 | - self.build_tree(['tree/a', 'tree/b', 'tree/c']) |
1061 | - tree.add(['a', 'b', 'c'], [b'a-id', b'b-id', b'c-id']) |
1062 | - preview = tree.preview_transform() |
1063 | - self.addCleanup(preview.finalize) |
1064 | - preview.unversion_file(preview.trans_id_file_id(b'b-id')) |
1065 | - c_trans_id = preview.trans_id_file_id(b'c-id') |
1066 | - preview.unversion_file(c_trans_id) |
1067 | - preview.version_file(c_trans_id, file_id=b'c-id') |
1068 | - preview_tree = preview.get_preview_tree() |
1069 | - self.assertEqual({b'a-id', b'c-id', tree.path2id('')}, |
1070 | - preview_tree.all_file_ids()) |
1071 | - |
1072 | - def test_path2id_deleted_unchanged(self): |
1073 | - tree = self.make_branch_and_tree('tree') |
1074 | - self.build_tree(['tree/unchanged', 'tree/deleted']) |
1075 | - tree.add(['unchanged', 'deleted'], [b'unchanged-id', b'deleted-id']) |
1076 | - preview = tree.preview_transform() |
1077 | - self.addCleanup(preview.finalize) |
1078 | - preview.unversion_file(preview.trans_id_file_id(b'deleted-id')) |
1079 | - preview_tree = preview.get_preview_tree() |
1080 | - self.assertEqual(b'unchanged-id', preview_tree.path2id('unchanged')) |
1081 | - self.assertFalse(preview_tree.is_versioned('deleted')) |
1082 | - |
1083 | - def test_path2id_created(self): |
1084 | - tree = self.make_branch_and_tree('tree') |
1085 | - self.build_tree(['tree/unchanged']) |
1086 | - tree.add(['unchanged'], [b'unchanged-id']) |
1087 | - preview = tree.preview_transform() |
1088 | - self.addCleanup(preview.finalize) |
1089 | - preview.new_file('new', preview.trans_id_file_id(b'unchanged-id'), |
1090 | - [b'contents'], b'new-id') |
1091 | - preview_tree = preview.get_preview_tree() |
1092 | - self.assertEqual(b'new-id', preview_tree.path2id('unchanged/new')) |
1093 | - |
1094 | - def test_path2id_moved(self): |
1095 | - tree = self.make_branch_and_tree('tree') |
1096 | - self.build_tree(['tree/old_parent/', 'tree/old_parent/child']) |
1097 | - tree.add(['old_parent', 'old_parent/child'], |
1098 | - [b'old_parent-id', b'child-id']) |
1099 | - preview = tree.preview_transform() |
1100 | - self.addCleanup(preview.finalize) |
1101 | - new_parent = preview.new_directory('new_parent', preview.root, |
1102 | - b'new_parent-id') |
1103 | - preview.adjust_path('child', new_parent, |
1104 | - preview.trans_id_file_id(b'child-id')) |
1105 | - preview_tree = preview.get_preview_tree() |
1106 | - self.assertFalse(preview_tree.is_versioned('old_parent/child')) |
1107 | - self.assertEqual(b'child-id', preview_tree.path2id('new_parent/child')) |
1108 | - |
1109 | - def test_path2id_renamed_parent(self): |
1110 | - tree = self.make_branch_and_tree('tree') |
1111 | - self.build_tree(['tree/old_name/', 'tree/old_name/child']) |
1112 | - tree.add(['old_name', 'old_name/child'], |
1113 | - [b'parent-id', b'child-id']) |
1114 | - preview = tree.preview_transform() |
1115 | - self.addCleanup(preview.finalize) |
1116 | - preview.adjust_path('new_name', preview.root, |
1117 | - preview.trans_id_file_id(b'parent-id')) |
1118 | - preview_tree = preview.get_preview_tree() |
1119 | - self.assertFalse(preview_tree.is_versioned('old_name/child')) |
1120 | - self.assertEqual(b'child-id', preview_tree.path2id('new_name/child')) |
1121 | - |
1122 | - def assertMatchingIterEntries(self, tt, specific_files=None): |
1123 | - preview_tree = tt.get_preview_tree() |
1124 | - preview_result = list(preview_tree.iter_entries_by_dir( |
1125 | - specific_files=specific_files)) |
1126 | - tree = tt._tree |
1127 | - tt.apply() |
1128 | - actual_result = list(tree.iter_entries_by_dir( |
1129 | - specific_files=specific_files)) |
1130 | - self.assertEqual(actual_result, preview_result) |
1131 | - |
1132 | - def test_iter_entries_by_dir_new(self): |
1133 | - tree = self.make_branch_and_tree('tree') |
1134 | - tt = tree.transform() |
1135 | - tt.new_file('new', tt.root, [b'contents'], b'new-id') |
1136 | - self.assertMatchingIterEntries(tt) |
1137 | - |
1138 | - def test_iter_entries_by_dir_deleted(self): |
1139 | - tree = self.make_branch_and_tree('tree') |
1140 | - self.build_tree(['tree/deleted']) |
1141 | - tree.add('deleted', b'deleted-id') |
1142 | - tt = tree.transform() |
1143 | - tt.delete_contents(tt.trans_id_file_id(b'deleted-id')) |
1144 | - self.assertMatchingIterEntries(tt) |
1145 | - |
1146 | - def test_iter_entries_by_dir_unversioned(self): |
1147 | - tree = self.make_branch_and_tree('tree') |
1148 | - self.build_tree(['tree/removed']) |
1149 | - tree.add('removed', b'removed-id') |
1150 | - tt = tree.transform() |
1151 | - tt.unversion_file(tt.trans_id_file_id(b'removed-id')) |
1152 | - self.assertMatchingIterEntries(tt) |
1153 | - |
1154 | - def test_iter_entries_by_dir_moved(self): |
1155 | - tree = self.make_branch_and_tree('tree') |
1156 | - self.build_tree(['tree/moved', 'tree/new_parent/']) |
1157 | - tree.add(['moved', 'new_parent'], [b'moved-id', b'new_parent-id']) |
1158 | - tt = tree.transform() |
1159 | - tt.adjust_path('moved', tt.trans_id_file_id(b'new_parent-id'), |
1160 | - tt.trans_id_file_id(b'moved-id')) |
1161 | - self.assertMatchingIterEntries(tt) |
1162 | - |
1163 | - def test_iter_entries_by_dir_specific_files(self): |
1164 | - tree = self.make_branch_and_tree('tree') |
1165 | - tree.set_root_id(b'tree-root-id') |
1166 | - self.build_tree(['tree/parent/', 'tree/parent/child']) |
1167 | - tree.add(['parent', 'parent/child'], [b'parent-id', b'child-id']) |
1168 | - tt = tree.transform() |
1169 | - self.assertMatchingIterEntries(tt, ['', 'parent/child']) |
1170 | - |
1171 | - def test_symlink_content_summary(self): |
1172 | - self.requireFeature(SymlinkFeature) |
1173 | - preview = self.get_empty_preview() |
1174 | - preview.new_symlink('path', preview.root, 'target', b'path-id') |
1175 | - summary = preview.get_preview_tree().path_content_summary('path') |
1176 | - self.assertEqual(('symlink', None, None, 'target'), summary) |
1177 | - |
1178 | - def test_missing_content_summary(self): |
1179 | - preview = self.get_empty_preview() |
1180 | - summary = preview.get_preview_tree().path_content_summary('path') |
1181 | - self.assertEqual(('missing', None, None, None), summary) |
1182 | - |
1183 | - def test_deleted_content_summary(self): |
1184 | - tree = self.make_branch_and_tree('tree') |
1185 | - self.build_tree(['tree/path/']) |
1186 | - tree.add('path') |
1187 | - preview = tree.preview_transform() |
1188 | - self.addCleanup(preview.finalize) |
1189 | - preview.delete_contents(preview.trans_id_tree_path('path')) |
1190 | - summary = preview.get_preview_tree().path_content_summary('path') |
1191 | - self.assertEqual(('missing', None, None, None), summary) |
1192 | - |
1193 | - def test_file_content_summary_executable(self): |
1194 | - preview = self.get_empty_preview() |
1195 | - path_id = preview.new_file('path', preview.root, [ |
1196 | - b'contents'], b'path-id') |
1197 | - preview.set_executability(True, path_id) |
1198 | - summary = preview.get_preview_tree().path_content_summary('path') |
1199 | - self.assertEqual(4, len(summary)) |
1200 | - self.assertEqual('file', summary[0]) |
1201 | - # size must be known |
1202 | - self.assertEqual(len('contents'), summary[1]) |
1203 | - # executable |
1204 | - self.assertEqual(True, summary[2]) |
1205 | - # will not have hash (not cheap to determine) |
1206 | - self.assertIs(None, summary[3]) |
1207 | - |
1208 | - def test_change_executability(self): |
1209 | - tree = self.make_branch_and_tree('tree') |
1210 | - self.build_tree(['tree/path']) |
1211 | - tree.add('path') |
1212 | - preview = tree.preview_transform() |
1213 | - self.addCleanup(preview.finalize) |
1214 | - path_id = preview.trans_id_tree_path('path') |
1215 | - preview.set_executability(True, path_id) |
1216 | - summary = preview.get_preview_tree().path_content_summary('path') |
1217 | - self.assertEqual(True, summary[2]) |
1218 | - |
1219 | - def test_file_content_summary_non_exec(self): |
1220 | - preview = self.get_empty_preview() |
1221 | - preview.new_file('path', preview.root, [b'contents'], b'path-id') |
1222 | - summary = preview.get_preview_tree().path_content_summary('path') |
1223 | - self.assertEqual(4, len(summary)) |
1224 | - self.assertEqual('file', summary[0]) |
1225 | - # size must be known |
1226 | - self.assertEqual(len('contents'), summary[1]) |
1227 | - # not executable |
1228 | - self.assertEqual(False, summary[2]) |
1229 | - # will not have hash (not cheap to determine) |
1230 | - self.assertIs(None, summary[3]) |
1231 | - |
1232 | - def test_dir_content_summary(self): |
1233 | - preview = self.get_empty_preview() |
1234 | - preview.new_directory('path', preview.root, b'path-id') |
1235 | - summary = preview.get_preview_tree().path_content_summary('path') |
1236 | - self.assertEqual(('directory', None, None, None), summary) |
1237 | - |
1238 | - def test_tree_content_summary(self): |
1239 | - preview = self.get_empty_preview() |
1240 | - path = preview.new_directory('path', preview.root, b'path-id') |
1241 | - preview.set_tree_reference(b'rev-1', path) |
1242 | - summary = preview.get_preview_tree().path_content_summary('path') |
1243 | - self.assertEqual(4, len(summary)) |
1244 | - self.assertEqual('tree-reference', summary[0]) |
1245 | - |
1246 | - def test_annotate(self): |
1247 | - tree = self.make_branch_and_tree('tree') |
1248 | - self.build_tree_contents([('tree/file', b'a\n')]) |
1249 | - tree.add('file', b'file-id') |
1250 | - tree.commit('a', rev_id=b'one') |
1251 | - self.build_tree_contents([('tree/file', b'a\nb\n')]) |
1252 | - preview = tree.preview_transform() |
1253 | - self.addCleanup(preview.finalize) |
1254 | - file_trans_id = preview.trans_id_file_id(b'file-id') |
1255 | - preview.delete_contents(file_trans_id) |
1256 | - preview.create_file([b'a\nb\nc\n'], file_trans_id) |
1257 | - preview_tree = preview.get_preview_tree() |
1258 | - expected = [ |
1259 | - (b'one', b'a\n'), |
1260 | - (b'me:', b'b\n'), |
1261 | - (b'me:', b'c\n'), |
1262 | - ] |
1263 | - annotation = preview_tree.annotate_iter( |
1264 | - 'file', default_revision=b'me:') |
1265 | - self.assertEqual(expected, annotation) |
1266 | - |
1267 | - def test_annotate_missing(self): |
1268 | - preview = self.get_empty_preview() |
1269 | - preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id') |
1270 | - preview_tree = preview.get_preview_tree() |
1271 | - expected = [ |
1272 | - (b'me:', b'a\n'), |
1273 | - (b'me:', b'b\n'), |
1274 | - (b'me:', b'c\n'), |
1275 | - ] |
1276 | - annotation = preview_tree.annotate_iter( |
1277 | - 'file', default_revision=b'me:') |
1278 | - self.assertEqual(expected, annotation) |
1279 | - |
1280 | - def test_annotate_rename(self): |
1281 | - tree = self.make_branch_and_tree('tree') |
1282 | - self.build_tree_contents([('tree/file', b'a\n')]) |
1283 | - tree.add('file', b'file-id') |
1284 | - tree.commit('a', rev_id=b'one') |
1285 | - preview = tree.preview_transform() |
1286 | - self.addCleanup(preview.finalize) |
1287 | - file_trans_id = preview.trans_id_file_id(b'file-id') |
1288 | - preview.adjust_path('newname', preview.root, file_trans_id) |
1289 | - preview_tree = preview.get_preview_tree() |
1290 | - expected = [ |
1291 | - (b'one', b'a\n'), |
1292 | - ] |
1293 | - annotation = preview_tree.annotate_iter( |
1294 | - 'file', default_revision=b'me:') |
1295 | - self.assertEqual(expected, annotation) |
1296 | - |
1297 | - def test_annotate_deleted(self): |
1298 | - tree = self.make_branch_and_tree('tree') |
1299 | - self.build_tree_contents([('tree/file', b'a\n')]) |
1300 | - tree.add('file', b'file-id') |
1301 | - tree.commit('a', rev_id=b'one') |
1302 | - self.build_tree_contents([('tree/file', b'a\nb\n')]) |
1303 | - preview = tree.preview_transform() |
1304 | - self.addCleanup(preview.finalize) |
1305 | - file_trans_id = preview.trans_id_file_id(b'file-id') |
1306 | - preview.delete_contents(file_trans_id) |
1307 | - preview_tree = preview.get_preview_tree() |
1308 | - annotation = preview_tree.annotate_iter( |
1309 | - 'file', default_revision=b'me:') |
1310 | - self.assertIs(None, annotation) |
1311 | - |
1312 | - def test_stored_kind(self): |
1313 | - preview = self.get_empty_preview() |
1314 | - preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id') |
1315 | - preview_tree = preview.get_preview_tree() |
1316 | - self.assertEqual('file', preview_tree.stored_kind('file')) |
1317 | - |
1318 | - def test_is_executable(self): |
1319 | - preview = self.get_empty_preview() |
1320 | - preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id') |
1321 | - preview.set_executability(True, preview.trans_id_file_id(b'file-id')) |
1322 | - preview_tree = preview.get_preview_tree() |
1323 | - self.assertEqual(True, preview_tree.is_executable('file')) |
1324 | - |
1325 | - def test_get_set_parent_ids(self): |
1326 | - revision_tree, preview_tree = self.get_tree_and_preview_tree() |
1327 | - self.assertEqual([], preview_tree.get_parent_ids()) |
1328 | - preview_tree.set_parent_ids([b'rev-1']) |
1329 | - self.assertEqual([b'rev-1'], preview_tree.get_parent_ids()) |
1330 | - |
1331 | - def test_plan_file_merge(self): |
1332 | - work_a = self.make_branch_and_tree('wta') |
1333 | - self.build_tree_contents([('wta/file', b'a\nb\nc\nd\n')]) |
1334 | - work_a.add('file', b'file-id') |
1335 | - base_id = work_a.commit('base version') |
1336 | - tree_b = work_a.controldir.sprout('wtb').open_workingtree() |
1337 | - preview = work_a.preview_transform() |
1338 | - self.addCleanup(preview.finalize) |
1339 | - trans_id = preview.trans_id_file_id(b'file-id') |
1340 | - preview.delete_contents(trans_id) |
1341 | - preview.create_file([b'b\nc\nd\ne\n'], trans_id) |
1342 | - self.build_tree_contents([('wtb/file', b'a\nc\nd\nf\n')]) |
1343 | - tree_a = preview.get_preview_tree() |
1344 | - tree_a.set_parent_ids([base_id]) |
1345 | - self.assertEqual([ |
1346 | - ('killed-a', b'a\n'), |
1347 | - ('killed-b', b'b\n'), |
1348 | - ('unchanged', b'c\n'), |
1349 | - ('unchanged', b'd\n'), |
1350 | - ('new-a', b'e\n'), |
1351 | - ('new-b', b'f\n'), |
1352 | - ], list(tree_a.plan_file_merge('file', tree_b))) |
1353 | - |
1354 | - def test_plan_file_merge_revision_tree(self): |
1355 | - work_a = self.make_branch_and_tree('wta') |
1356 | - self.build_tree_contents([('wta/file', b'a\nb\nc\nd\n')]) |
1357 | - work_a.add('file', b'file-id') |
1358 | - base_id = work_a.commit('base version') |
1359 | - tree_b = work_a.controldir.sprout('wtb').open_workingtree() |
1360 | - preview = work_a.basis_tree().preview_transform() |
1361 | - self.addCleanup(preview.finalize) |
1362 | - trans_id = preview.trans_id_file_id(b'file-id') |
1363 | - preview.delete_contents(trans_id) |
1364 | - preview.create_file([b'b\nc\nd\ne\n'], trans_id) |
1365 | - self.build_tree_contents([('wtb/file', b'a\nc\nd\nf\n')]) |
1366 | - tree_a = preview.get_preview_tree() |
1367 | - tree_a.set_parent_ids([base_id]) |
1368 | - self.assertEqual([ |
1369 | - ('killed-a', b'a\n'), |
1370 | - ('killed-b', b'b\n'), |
1371 | - ('unchanged', b'c\n'), |
1372 | - ('unchanged', b'd\n'), |
1373 | - ('new-a', b'e\n'), |
1374 | - ('new-b', b'f\n'), |
1375 | - ], list(tree_a.plan_file_merge('file', tree_b))) |
1376 | - |
1377 | - def test_walkdirs(self): |
1378 | - preview = self.get_empty_preview() |
1379 | - preview.new_directory('', ROOT_PARENT, b'tree-root') |
1380 | - # FIXME: new_directory should mark root. |
1381 | - preview.fixup_new_roots() |
1382 | - preview_tree = preview.get_preview_tree() |
1383 | - preview.new_file('a', preview.root, [b'contents'], b'a-id') |
1384 | - expected = [(('', b'tree-root'), |
1385 | - [('a', 'a', 'file', None, b'a-id', 'file')])] |
1386 | - self.assertEqual(expected, list(preview_tree.walkdirs())) |
1387 | - |
1388 | - def test_extras(self): |
1389 | - work_tree = self.make_branch_and_tree('tree') |
1390 | - self.build_tree(['tree/removed-file', 'tree/existing-file', |
1391 | - 'tree/not-removed-file']) |
1392 | - work_tree.add(['removed-file', 'not-removed-file']) |
1393 | - preview = work_tree.preview_transform() |
1394 | - self.addCleanup(preview.finalize) |
1395 | - preview.new_file('new-file', preview.root, [b'contents']) |
1396 | - preview.new_file('new-versioned-file', preview.root, [b'contents'], |
1397 | - b'new-versioned-id') |
1398 | - tree = preview.get_preview_tree() |
1399 | - preview.unversion_file(preview.trans_id_tree_path('removed-file')) |
1400 | - self.assertEqual({'new-file', 'removed-file', 'existing-file'}, |
1401 | - set(tree.extras())) |
1402 | - |
1403 | - def test_merge_into_preview(self): |
1404 | - work_tree = self.make_branch_and_tree('tree') |
1405 | - self.build_tree_contents([('tree/file', b'b\n')]) |
1406 | - work_tree.add('file', b'file-id') |
1407 | - work_tree.commit('first commit') |
1408 | - child_tree = work_tree.controldir.sprout('child').open_workingtree() |
1409 | - self.build_tree_contents([('child/file', b'b\nc\n')]) |
1410 | - child_tree.commit('child commit') |
1411 | - child_tree.lock_write() |
1412 | - self.addCleanup(child_tree.unlock) |
1413 | - work_tree.lock_write() |
1414 | - self.addCleanup(work_tree.unlock) |
1415 | - preview = work_tree.preview_transform() |
1416 | - self.addCleanup(preview.finalize) |
1417 | - file_trans_id = preview.trans_id_file_id(b'file-id') |
1418 | - preview.delete_contents(file_trans_id) |
1419 | - preview.create_file([b'a\nb\n'], file_trans_id) |
1420 | - preview_tree = preview.get_preview_tree() |
1421 | - merger = Merger.from_revision_ids(preview_tree, |
1422 | - child_tree.branch.last_revision(), |
1423 | - other_branch=child_tree.branch, |
1424 | - tree_branch=work_tree.branch) |
1425 | - merger.merge_type = Merge3Merger |
1426 | - tt = merger.make_merger().make_preview_transform() |
1427 | - self.addCleanup(tt.finalize) |
1428 | - final_tree = tt.get_preview_tree() |
1429 | - self.assertEqual( |
1430 | - b'a\nb\nc\n', |
1431 | - final_tree.get_file_text(final_tree.id2path(b'file-id'))) |
1432 | - |
1433 | - def test_merge_preview_into_workingtree(self): |
1434 | - tree = self.make_branch_and_tree('tree') |
1435 | - tree.set_root_id(b'TREE_ROOT') |
1436 | - tt = tree.preview_transform() |
1437 | - self.addCleanup(tt.finalize) |
1438 | - tt.new_file('name', tt.root, [b'content'], b'file-id') |
1439 | - tree2 = self.make_branch_and_tree('tree2') |
1440 | - tree2.set_root_id(b'TREE_ROOT') |
1441 | - merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(), |
1442 | - tree.basis_tree()) |
1443 | - merger.merge_type = Merge3Merger |
1444 | - merger.do_merge() |
1445 | - |
1446 | - def test_merge_preview_into_workingtree_handles_conflicts(self): |
1447 | - tree = self.make_branch_and_tree('tree') |
1448 | - self.build_tree_contents([('tree/foo', b'bar')]) |
1449 | - tree.add('foo', b'foo-id') |
1450 | - tree.commit('foo') |
1451 | - tt = tree.preview_transform() |
1452 | - self.addCleanup(tt.finalize) |
1453 | - trans_id = tt.trans_id_file_id(b'foo-id') |
1454 | - tt.delete_contents(trans_id) |
1455 | - tt.create_file([b'baz'], trans_id) |
1456 | - tree2 = tree.controldir.sprout('tree2').open_workingtree() |
1457 | - self.build_tree_contents([('tree2/foo', b'qux')]) |
1458 | - merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(), |
1459 | - tree.basis_tree()) |
1460 | - merger.merge_type = Merge3Merger |
1461 | - merger.do_merge() |
1462 | - |
1463 | - def test_has_filename(self): |
1464 | - wt = self.make_branch_and_tree('tree') |
1465 | - self.build_tree(['tree/unmodified', 'tree/removed', 'tree/modified']) |
1466 | - tt = wt.preview_transform() |
1467 | - removed_id = tt.trans_id_tree_path('removed') |
1468 | - tt.delete_contents(removed_id) |
1469 | - tt.new_file('new', tt.root, [b'contents']) |
1470 | - modified_id = tt.trans_id_tree_path('modified') |
1471 | - tt.delete_contents(modified_id) |
1472 | - tt.create_file([b'modified-contents'], modified_id) |
1473 | - self.addCleanup(tt.finalize) |
1474 | - tree = tt.get_preview_tree() |
1475 | - self.assertTrue(tree.has_filename('unmodified')) |
1476 | - self.assertFalse(tree.has_filename('not-present')) |
1477 | - self.assertFalse(tree.has_filename('removed')) |
1478 | - self.assertTrue(tree.has_filename('new')) |
1479 | - self.assertTrue(tree.has_filename('modified')) |
1480 | - |
1481 | - def test_is_executable(self): |
1482 | - tree = self.make_branch_and_tree('tree') |
1483 | - preview = tree.preview_transform() |
1484 | - self.addCleanup(preview.finalize) |
1485 | - preview.new_file('foo', preview.root, [b'bar'], b'baz-id') |
1486 | - preview_tree = preview.get_preview_tree() |
1487 | - self.assertEqual(False, preview_tree.is_executable('tree/foo')) |
1488 | - |
1489 | - def test_commit_preview_tree(self): |
1490 | - tree = self.make_branch_and_tree('tree') |
1491 | - rev_id = tree.commit('rev1') |
1492 | - tree.branch.lock_write() |
1493 | - self.addCleanup(tree.branch.unlock) |
1494 | - tt = tree.preview_transform() |
1495 | - tt.new_file('file', tt.root, [b'contents'], b'file_id') |
1496 | - self.addCleanup(tt.finalize) |
1497 | - preview = tt.get_preview_tree() |
1498 | - preview.set_parent_ids([rev_id]) |
1499 | - builder = tree.branch.get_commit_builder([rev_id]) |
1500 | - list(builder.record_iter_changes(preview, rev_id, tt.iter_changes())) |
1501 | - builder.finish_inventory() |
1502 | - rev2_id = builder.commit('rev2') |
1503 | - rev2_tree = tree.branch.repository.revision_tree(rev2_id) |
1504 | - self.assertEqual(b'contents', rev2_tree.get_file_text('file')) |
1505 | - |
1506 | - def test_ascii_limbo_paths(self): |
1507 | - self.requireFeature(features.UnicodeFilenameFeature) |
1508 | - branch = self.make_branch('any') |
1509 | - tree = branch.repository.revision_tree(_mod_revision.NULL_REVISION) |
1510 | - tt = tree.preview_transform() |
1511 | - self.addCleanup(tt.finalize) |
1512 | - foo_id = tt.new_directory('', ROOT_PARENT) |
1513 | - bar_id = tt.new_file(u'\u1234bar', foo_id, [b'contents']) |
1514 | - limbo_path = tt._limbo_name(bar_id) |
1515 | - self.assertEqual(limbo_path, limbo_path) |
1516 | - |
1517 | - |
1518 | class FakeSerializer(object): |
1519 | """Serializer implementation that simply returns the input. |
1520 | |
1521 | |
1522 | === modified file 'breezy/tests/test_tree.py' |
1523 | --- breezy/tests/test_tree.py 2019-06-29 19:50:18 +0000 |
1524 | +++ breezy/tests/test_tree.py 2020-07-05 00:45:38 +0000 |
1525 | @@ -91,6 +91,10 @@ |
1526 | include_root, want_unversioned) |
1527 | ) |
1528 | |
1529 | + def find_source_path(self, target_path, recurse='none'): |
1530 | + self.calls.append( |
1531 | + ('find_source_path', self.source, self.target, target_path, recurse)) |
1532 | + |
1533 | @classmethod |
1534 | def is_compatible(klass, source, target): |
1535 | return True |
1536 | @@ -106,6 +110,7 @@ |
1537 | RecordingOptimiser.calls = [] |
1538 | InterTree.register_optimiser(RecordingOptimiser) |
1539 | tree = self.make_branch_and_tree('1') |
1540 | + null_tree = tree.basis_tree() |
1541 | tree2 = self.make_branch_and_tree('2') |
1542 | # do a series of calls: |
1543 | # trivial usage |
1544 | @@ -126,6 +131,8 @@ |
1545 | InterTree._optimisers = old_optimisers |
1546 | self.assertEqual( |
1547 | [ |
1548 | + ('find_source_path', null_tree, tree, '', 'none'), |
1549 | + ('find_source_path', null_tree, tree2, '', 'none'), |
1550 | ('compare', tree2, tree, False, None, None, False, False, |
1551 | False), |
1552 | ('compare', tree2, tree, 'unchanged', 'specific', 'extra', |
1553 | |
1554 | === modified file 'breezy/transform.py' |
1555 | --- breezy/transform.py 2020-07-04 14:58:52 +0000 |
1556 | +++ breezy/transform.py 2020-07-05 00:45:38 +0000 |
1557 | @@ -72,6 +72,7 @@ |
1558 | from .tree import ( |
1559 | InterTree, |
1560 | TreeChange, |
1561 | + find_previous_path, |
1562 | ) |
1563 | |
1564 | |
1565 | @@ -508,6 +509,9 @@ |
1566 | return self._tree.path2id('') |
1567 | return self._tree.path2id(path) |
1568 | |
1569 | + def final_is_versioned(self, trans_id): |
1570 | + return self.final_file_id(trans_id) is not None |
1571 | + |
1572 | def final_file_id(self, trans_id): |
1573 | """Determine the file id after any changes are applied, or None. |
1574 | |
1575 | @@ -687,10 +691,10 @@ |
1576 | for parent_id, children in viewitems(by_parent): |
1577 | if parent_id == ROOT_PARENT: |
1578 | continue |
1579 | - if self.final_file_id(parent_id) is not None: |
1580 | + if self.final_is_versioned(parent_id): |
1581 | continue |
1582 | for child_id in children: |
1583 | - if self.final_file_id(child_id) is not None: |
1584 | + if self.final_is_versioned(child_id): |
1585 | conflicts.append(('unversioned parent', parent_id)) |
1586 | break |
1587 | return conflicts |
1588 | @@ -723,7 +727,7 @@ |
1589 | """ |
1590 | conflicts = [] |
1591 | for trans_id in self._new_executability: |
1592 | - if self.final_file_id(trans_id) is None: |
1593 | + if not self.final_is_versioned(trans_id): |
1594 | conflicts.append(('unversioned executability', trans_id)) |
1595 | else: |
1596 | if self.final_kind(trans_id) != "file": |
1597 | @@ -760,8 +764,7 @@ |
1598 | last_trans_id = None |
1599 | for name, trans_id in name_ids: |
1600 | kind = self.final_kind(trans_id) |
1601 | - file_id = self.final_file_id(trans_id) |
1602 | - if kind is None and file_id is None: |
1603 | + if kind is None and not self.final_is_versioned(trans_id): |
1604 | continue |
1605 | if name == last_name: |
1606 | conflicts.append(('duplicate', last_trans_id, trans_id, |
1607 | @@ -913,7 +916,7 @@ |
1608 | # The child is removed as part of the transform. Since it was |
1609 | # versioned before, it's not an orphan |
1610 | continue |
1611 | - if self.final_file_id(child_tid) is None: |
1612 | + if not self.final_is_versioned(child_tid): |
1613 | # The child is not versioned |
1614 | orphans.append(child_tid) |
1615 | else: |
1616 | @@ -1101,7 +1104,7 @@ |
1617 | if strict: |
1618 | unversioned = set(self._new_contents).difference(set(self._new_id)) |
1619 | for trans_id in unversioned: |
1620 | - if self.final_file_id(trans_id) is None: |
1621 | + if not self.final_is_versioned(trans_id): |
1622 | raise errors.StrictCommitFailed() |
1623 | |
1624 | revno, last_rev_id = branch.last_revision_info() |
1625 | @@ -1859,7 +1862,7 @@ |
1626 | raise |
1627 | else: |
1628 | mover.apply_deletions() |
1629 | - if self.final_file_id(self.root) is None: |
1630 | + if not self.final_is_versioned(self.root): |
1631 | inventory_delta = [e for e in inventory_delta if e[0] != ''] |
1632 | self._tree.apply_inventory_delta(inventory_delta) |
1633 | self._apply_observed_sha1s() |
1634 | @@ -2138,7 +2141,6 @@ |
1635 | kind = None |
1636 | executable = False |
1637 | else: |
1638 | - file_id = self._transform.final_file_id(self._path2trans_id(path)) |
1639 | executable = self.is_executable(path) |
1640 | return kind, executable, None |
1641 | |
1642 | @@ -2230,7 +2232,7 @@ |
1643 | possible_extras.update(self._transform._new_contents) |
1644 | possible_extras.update(self._transform._removed_id) |
1645 | for trans_id in possible_extras: |
1646 | - if self._transform.final_file_id(trans_id) is None: |
1647 | + if not self._transform.final_is_versioned(trans_id): |
1648 | yield self._final_paths._determine_path(trans_id) |
1649 | |
1650 | def _make_inv_entries(self, ordered_entries, specific_files=None): |
1651 | @@ -2677,7 +2679,7 @@ |
1652 | divert = set() |
1653 | try: |
1654 | pp.next_phase() |
1655 | - file_trans_id[wt.path2id('')] = tt.trans_id_tree_path('') |
1656 | + file_trans_id[find_previous_path(wt, tree, '')] = tt.trans_id_tree_path('') |
1657 | with ui.ui_factory.nested_progress_bar() as pb: |
1658 | deferred_contents = [] |
1659 | num = 0 |
1660 | @@ -2714,19 +2716,19 @@ |
1661 | except errors.NotBranchError: |
1662 | pass |
1663 | else: |
1664 | - divert.add(file_id) |
1665 | - if (file_id not in divert |
1666 | + divert.add(tree_path) |
1667 | + if (tree_path not in divert |
1668 | and _content_match( |
1669 | tree, entry, tree_path, kind, target_path)): |
1670 | tt.delete_contents(tt.trans_id_tree_path(tree_path)) |
1671 | if kind == 'directory': |
1672 | reparent = True |
1673 | - parent_id = file_trans_id[entry.parent_id] |
1674 | + parent_id = file_trans_id[osutils.dirname(tree_path)] |
1675 | if entry.kind == 'file': |
1676 | # We *almost* replicate new_by_entry, so that we can defer |
1677 | # getting the file text, and get them all at once. |
1678 | trans_id = tt.create_path(entry.name, parent_id) |
1679 | - file_trans_id[file_id] = trans_id |
1680 | + file_trans_id[tree_path] = trans_id |
1681 | tt.version_file(trans_id, file_id=file_id) |
1682 | executable = tree.is_executable(tree_path) |
1683 | if executable: |
1684 | @@ -2734,10 +2736,10 @@ |
1685 | trans_data = (trans_id, tree_path, entry.text_sha1) |
1686 | deferred_contents.append((tree_path, trans_data)) |
1687 | else: |
1688 | - file_trans_id[file_id] = new_by_entry( |
1689 | + file_trans_id[tree_path] = new_by_entry( |
1690 | tree_path, tt, entry, parent_id, tree) |
1691 | if reparent: |
1692 | - new_trans_id = file_trans_id[file_id] |
1693 | + new_trans_id = file_trans_id[tree_path] |
1694 | old_parent = tt.trans_id_tree_path(tree_path) |
1695 | _reparent_children(tt, old_parent, new_trans_id) |
1696 | offset = num + 1 - len(deferred_contents) |
Running landing tests failed /ci.breezy- vcs.org/ job/brz- 3.1/job/ brz-3.1- land/193/
https:/