Merge lp:~jelmer/brz/objects-1 into lp:brz

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merge reported by: The Breezy Bot
Merged at revision: not available
Proposed branch: lp:~jelmer/brz/objects-1
Merge into: lp:brz
Prerequisite: lp:~jelmer/brz/objects
Diff against target: 1612 lines (+440/-407)
28 files modified
breezy/builtins.py (+8/-8)
breezy/bzr/_dirstate_helpers_pyx.pyx (+6/-3)
breezy/bzr/dirstate.py (+9/-9)
breezy/bzr/inventory.py (+3/-2)
breezy/bzr/inventorytree.py (+4/-5)
breezy/bzr/vf_repository.py (+30/-28)
breezy/bzr/workingtree.py (+9/-10)
breezy/commit.py (+16/-19)
breezy/delta.py (+31/-31)
breezy/diff.py (+13/-12)
breezy/git/commit.py (+29/-29)
breezy/git/object_store.py (+21/-22)
breezy/git/workingtree.py (+11/-12)
breezy/merge.py (+11/-11)
breezy/mutabletree.py (+1/-1)
breezy/plugins/fastimport/revision_store.py (+41/-36)
breezy/plugins/launchpad/lp_propose.py (+2/-3)
breezy/plugins/propose/launchpad.py (+2/-3)
breezy/rename_map.py (+13/-13)
breezy/shelf.py (+22/-23)
breezy/tests/per_intertree/test_compare.py (+76/-61)
breezy/tests/per_repository/test_check.py (+4/-2)
breezy/tests/per_repository/test_commit_builder.py (+6/-4)
breezy/tests/test__dirstate_helpers.py (+3/-6)
breezy/tests/test_commit.py (+17/-12)
breezy/tests/test_transform.py (+2/-3)
breezy/transform.py (+35/-34)
breezy/tree.py (+15/-5)
To merge this branch: bzr merge lp:~jelmer/brz/objects-1
Reviewer Review Type Date Requested Status
Martin Packman Approve
Review via email: mp+368859@code.launchpad.net

Commit message

Use the new attributes on TreeChange rather than indexing.

Description of the change

Use the new attributes on TreeChange rather than indexing.

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote :

Thanks! As discussed, probably makes sense to flatten this a bit more in future, but this is much more readable as is.

review: Approve
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'breezy/builtins.py'
2--- breezy/builtins.py 2019-06-02 03:11:13 +0000
3+++ breezy/builtins.py 2019-06-15 17:35:57 +0000
4@@ -1701,12 +1701,12 @@
5 self.add_cleanup(old_tree.lock_read().unlock)
6 renames = []
7 iterator = tree.iter_changes(old_tree, include_unchanged=True)
8- for f, paths, c, v, p, n, k, e in iterator:
9- if paths[0] == paths[1]:
10- continue
11- if None in (paths):
12- continue
13- renames.append(paths)
14+ for change in iterator:
15+ if change.path[0] == change.path[1]:
16+ continue
17+ if None in change.path:
18+ continue
19+ renames.append(change.path)
20 renames.sort()
21 for old_name, new_name in renames:
22 self.outf.write("%s => %s\n" % (old_name, new_name))
23@@ -1916,8 +1916,8 @@
24 missing = []
25 for change in tree.iter_changes(tree.basis_tree()):
26 # Find paths in the working tree that have no kind:
27- if change[1][1] is not None and change[6][1] is None:
28- missing.append(change[1][1])
29+ if change.path[1] is not None and change.kind[1] is None:
30+ missing.append(change.path[1])
31 file_list = sorted(missing, reverse=True)
32 file_deletion_strategy = 'keep'
33 tree.remove(file_list, verbose=verbose, to_file=self.outf,
34
35=== modified file 'breezy/bzr/_dirstate_helpers_pyx.pyx'
36--- breezy/bzr/_dirstate_helpers_pyx.pyx 2019-06-15 01:02:49 +0000
37+++ breezy/bzr/_dirstate_helpers_pyx.pyx 2019-06-15 17:35:57 +0000
38@@ -1553,7 +1553,8 @@
39 new_executable = bool(
40 stat.S_ISREG(self.root_dir_info[3].st_mode)
41 and stat.S_IEXEC & self.root_dir_info[3].st_mode)
42- return (None,
43+ return TreeChange(
44+ None,
45 (None, self.current_root_unicode),
46 True,
47 (False, False),
48@@ -1664,7 +1665,8 @@
49 new_executable = bool(
50 stat.S_ISREG(current_path_info[3].st_mode)
51 and stat.S_IEXEC & current_path_info[3].st_mode)
52- return (None,
53+ return TreeChange(
54+ None,
55 (None, self.utf8_decode(current_path_info[0])[0]),
56 True,
57 (False, False),
58@@ -1833,7 +1835,8 @@
59 if changed is not None:
60 raise AssertionError(
61 "result is not None: %r" % result)
62- result = (None,
63+ result = TreeChange(
64+ None,
65 (None, relpath_unicode),
66 True,
67 (False, False),
68
69=== modified file 'breezy/bzr/dirstate.py'
70--- breezy/bzr/dirstate.py 2019-06-15 01:02:49 +0000
71+++ breezy/bzr/dirstate.py 2019-06-15 17:35:57 +0000
72@@ -4190,15 +4190,15 @@
73 except UnicodeDecodeError:
74 raise errors.BadFilenameEncoding(
75 current_path_info[0], osutils._fs_enc)
76- yield (None,
77- (None, relpath_unicode),
78- True,
79- (False, False),
80- (None, None),
81- (None, utf8_decode(
82- current_path_info[1])[0]),
83- (None, current_path_info[2]),
84- (None, new_executable))
85+ yield TreeChange(
86+ None,
87+ (None, relpath_unicode),
88+ True,
89+ (False, False),
90+ (None, None),
91+ (None, utf8_decode(current_path_info[1])[0]),
92+ (None, current_path_info[2]),
93+ (None, new_executable))
94 # dont descend into this unversioned path if it is
95 # a dir
96 if current_path_info[2] in ('directory'):
97
98=== modified file 'breezy/bzr/inventory.py'
99--- breezy/bzr/inventory.py 2019-06-15 13:33:16 +0000
100+++ breezy/bzr/inventory.py 2019-06-15 17:35:57 +0000
101@@ -2104,8 +2104,9 @@
102 # Could happen when only the revision changed for a directory
103 # for instance.
104 continue
105- yield (file_id, (path_in_source, path_in_target), changed_content,
106- versioned, parent, name, kind, executable)
107+ yield (
108+ file_id, (path_in_source, path_in_target), changed_content,
109+ versioned, parent, name, kind, executable)
110
111 def __len__(self):
112 """Return the number of entries in the inventory."""
113
114=== modified file 'breezy/bzr/inventorytree.py'
115--- breezy/bzr/inventorytree.py 2019-06-15 01:02:49 +0000
116+++ breezy/bzr/inventorytree.py 2019-06-15 17:35:57 +0000
117@@ -893,16 +893,15 @@
118 # FIXME: nested tree support
119 for result in self.target.root_inventory.iter_changes(
120 self.source.root_inventory):
121+ result = TreeChange(*result)
122 if specific_file_ids is not None:
123- file_id = result[0]
124- if file_id not in specific_file_ids:
125+ if result.file_id not in specific_file_ids:
126 # A change from the whole tree that we don't want to show yet.
127 # We may find that we need to show it for delta consistency, so
128 # stash it.
129- discarded_changes[result[0]] = result
130+ discarded_changes[result.file_id] = result
131 continue
132- new_parent_id = result[4][1]
133- precise_file_ids.add(new_parent_id)
134+ precise_file_ids.add(result.parent_id[1])
135 yield result
136 changed_file_ids.add(result[0])
137 if specific_file_ids is not None:
138
139=== modified file 'breezy/bzr/vf_repository.py'
140--- breezy/bzr/vf_repository.py 2019-05-29 03:22:34 +0000
141+++ breezy/bzr/vf_repository.py 2019-06-15 17:35:57 +0000
142@@ -85,6 +85,7 @@
143 from ..trace import (
144 mutter
145 )
146+from ..tree import TreeChange
147
148
149 class VersionedFileRepositoryFormat(RepositoryFormat):
150@@ -374,12 +375,12 @@
151 changes = {}
152 for change in iter_changes:
153 # This probably looks up in basis_inv way to much.
154- if change[1][0] is not None:
155- head_candidate = [basis_inv.get_entry(change[0]).revision]
156+ if change.path[0] is not None:
157+ head_candidate = [basis_inv.get_entry(change.file_id).revision]
158 else:
159 head_candidate = []
160- changes[change[0]] = change, merged_ids.get(change[0],
161- head_candidate)
162+ changes[change.file_id] = change, merged_ids.get(
163+ change.file_id, head_candidate)
164 unchanged_merged = set(merged_ids) - set(changes)
165 # Extend the changes dict with synthetic changes to record merges of
166 # texts.
167@@ -403,13 +404,14 @@
168 # by the user. So we discard this change.
169 pass
170 else:
171- change = (file_id,
172- (basis_inv.id2path(file_id), tree.id2path(file_id)),
173- False, (True, True),
174- (basis_entry.parent_id, basis_entry.parent_id),
175- (basis_entry.name, basis_entry.name),
176- (basis_entry.kind, basis_entry.kind),
177- (basis_entry.executable, basis_entry.executable))
178+ change = TreeChange(
179+ file_id,
180+ (basis_inv.id2path(file_id), tree.id2path(file_id)),
181+ False, (True, True),
182+ (basis_entry.parent_id, basis_entry.parent_id),
183+ (basis_entry.name, basis_entry.name),
184+ (basis_entry.kind, basis_entry.kind),
185+ (basis_entry.executable, basis_entry.executable))
186 changes[file_id] = (change, merged_ids[file_id])
187 # changes contains tuples with the change and a set of inventory
188 # candidates for the file.
189@@ -419,7 +421,7 @@
190 inv_delta = self._basis_delta
191 modified_rev = self._new_revision_id
192 for change, head_candidates in viewvalues(changes):
193- if change[3][1]: # versioned in target.
194+ if change.versioned[1]: # versioned in target.
195 # Several things may be happening here:
196 # We may have a fork in the per-file graph
197 # - record a change with the content from tree
198@@ -427,11 +429,11 @@
199 # - carry over the tree that hasn't changed
200 # We may have a change against all trees
201 # - record the change with the content from tree
202- kind = change[6][1]
203- file_id = change[0]
204- entry = _entry_factory[kind](file_id, change[5][1],
205- change[4][1])
206- head_set = self._heads(change[0], set(head_candidates))
207+ kind = change.kind[1]
208+ file_id = change.file_id
209+ entry = _entry_factory[kind](file_id, change.name[1],
210+ change.parent_id[1])
211+ head_set = self._heads(change.file_id, set(head_candidates))
212 heads = []
213 # Preserve ordering.
214 for head_candidate in head_candidates:
215@@ -478,7 +480,7 @@
216 # other process reverts it while commit is running (with
217 # the revert happening after iter_changes did its
218 # examination).
219- if change[7][1]:
220+ if change.executable[1]:
221 entry.executable = True
222 else:
223 entry.executable = False
224@@ -489,11 +491,11 @@
225 nostore_sha = parent_entry.text_sha1
226 else:
227 nostore_sha = None
228- file_obj, stat_value = tree.get_file_with_stat(change[1][1])
229+ file_obj, stat_value = tree.get_file_with_stat(change.path[1])
230 try:
231 entry.text_sha1, entry.text_size = self._add_file_to_weave(
232 file_id, file_obj, heads, nostore_sha)
233- yield change[1][1], (entry.text_sha1, stat_value)
234+ yield change.path[1], (entry.text_sha1, stat_value)
235 except errors.ExistingContent:
236 # No content change against a carry_over parent
237 # Perhaps this should also yield a fs hash update?
238@@ -505,23 +507,23 @@
239 elif kind == 'symlink':
240 # Wants a path hint?
241 entry.symlink_target = tree.get_symlink_target(
242- change[1][1])
243+ change.path[1])
244 if (carry_over_possible and
245 parent_entry.symlink_target ==
246 entry.symlink_target):
247 carried_over = True
248 else:
249 self._add_file_to_weave(
250- change[0], BytesIO(), heads, None)
251+ change.file_id, BytesIO(), heads, None)
252 elif kind == 'directory':
253 if carry_over_possible:
254 carried_over = True
255 else:
256 # Nothing to set on the entry.
257 # XXX: split into the Root and nonRoot versions.
258- if change[1][1] != '' or self.repository.supports_rich_root():
259+ if change.path[1] != '' or self.repository.supports_rich_root():
260 self._add_file_to_weave(
261- change[0], BytesIO(), heads, None)
262+ change.file_id, BytesIO(), heads, None)
263 elif kind == 'tree-reference':
264 if not self.repository._format.supports_tree_reference:
265 # This isn't quite sane as an error, but we shouldn't
266@@ -531,7 +533,7 @@
267 raise errors.UnsupportedOperation(
268 tree.add_reference, self.repository)
269 reference_revision = tree.get_reference_revision(
270- change[1][1])
271+ change.path[1])
272 entry.reference_revision = reference_revision
273 if (carry_over_possible
274 and parent_entry.reference_revision ==
275@@ -539,7 +541,7 @@
276 carried_over = True
277 else:
278 self._add_file_to_weave(
279- change[0], BytesIO(), heads, None)
280+ change.file_id, BytesIO(), heads, None)
281 else:
282 raise AssertionError('unknown kind %r' % kind)
283 if not carried_over:
284@@ -548,8 +550,8 @@
285 entry.revision = parent_entry.revision
286 else:
287 entry = None
288- new_path = change[1][1]
289- inv_delta.append((change[1][0], new_path, change[0], entry))
290+ new_path = change.path[1]
291+ inv_delta.append((change.path[0], new_path, change.file_id, entry))
292 if new_path == '':
293 seen_root = True
294 # The initial commit adds a root directory, but this in itself is not
295
296=== modified file 'breezy/bzr/workingtree.py'
297--- breezy/bzr/workingtree.py 2019-06-04 00:08:59 +0000
298+++ breezy/bzr/workingtree.py 2019-06-15 17:35:57 +0000
299@@ -426,19 +426,18 @@
300
301 # Bail out if we are going to delete files we shouldn't
302 if not keep_files and not force:
303- for (file_id, path, content_change, versioned, parent_id, name,
304- kind, executable) in self.iter_changes(
305- self.basis_tree(), include_unchanged=True,
306- require_versioned=False, want_unversioned=True,
307- specific_files=files):
308- if versioned[0] is False:
309+ for change in self.iter_changes(
310+ self.basis_tree(), include_unchanged=True,
311+ require_versioned=False, want_unversioned=True,
312+ specific_files=files):
313+ if change.versioned[0] is False:
314 # The record is unknown or newly added
315- files_to_backup.append(path[1])
316- elif (content_change and (kind[1] is not None)
317- and osutils.is_inside_any(files, path[1])):
318+ files_to_backup.append(change.path[1])
319+ elif (change.changed_content and (change.kind[1] is not None)
320+ and osutils.is_inside_any(files, change.path[1])):
321 # Versioned and changed, but not deleted, and still
322 # in one of the dirs to be deleted.
323- files_to_backup.append(path[1])
324+ files_to_backup.append(change.path[1])
325
326 def backup(file_to_backup):
327 backup_name = self.controldir._available_backup_name(
328
329=== modified file 'breezy/commit.py'
330--- breezy/commit.py 2019-03-04 01:44:35 +0000
331+++ breezy/commit.py 2019-06-15 17:35:57 +0000
332@@ -69,6 +69,7 @@
333 minimum_path_selection,
334 )
335 from .trace import mutter, note, is_quiet
336+from .tree import TreeChange
337 from .urlutils import unescape_for_display
338 from .i18n import gettext
339
340@@ -96,14 +97,11 @@
341 :return: iter_changes function
342 """
343 for change in iter_changes:
344- old_path = change[1][0]
345- new_path = change[1][1]
346-
347- new_excluded = (new_path is not None and
348- is_inside_any(exclude, new_path))
349-
350- old_excluded = (old_path is not None and
351- is_inside_any(exclude, old_path))
352+ new_excluded = (change.path[1] is not None and
353+ is_inside_any(exclude, change.path[1]))
354+
355+ old_excluded = (change.path[0] is not None and
356+ is_inside_any(exclude, change.path[0]))
357
358 if old_excluded and new_excluded:
359 continue
360@@ -701,29 +699,28 @@
361 deleted_paths = []
362 for change in iter_changes:
363 if report_changes:
364- old_path = change[1][0]
365- new_path = change[1][1]
366- versioned = change[3][1]
367- kind = change[6][1]
368- versioned = change[3][1]
369+ old_path = change.path[0]
370+ new_path = change.path[1]
371+ versioned = change.versioned[1]
372+ kind = change.kind[1]
373+ versioned = change.versioned[1]
374 if kind is None and versioned:
375 # 'missing' path
376 if report_changes:
377 reporter.missing(new_path)
378- if change[6][0] == 'symlink' and not self.work_tree.supports_symlinks():
379+ if change.kind[0] == 'symlink' and not self.work_tree.supports_symlinks():
380 trace.warning('Ignoring "%s" as symlinks are not '
381- 'supported on this filesystem.' % (change[1][0],))
382+ 'supported on this filesystem.' % (change.path[0],))
383 continue
384 deleted_paths.append(change[1][1])
385 # Reset the new path (None) and new versioned flag (False)
386- change = (change[0], (change[1][0], None), change[2],
387- (change[3][0], False)) + change[4:]
388- new_path = change[1][1]
389+ change = change.discard_new()
390+ new_path = change.path[1]
391 versioned = False
392 elif kind == 'tree-reference':
393 if self.recursive == 'down':
394 self._commit_nested_tree(change[1][1])
395- if change[3][0] or change[3][1]:
396+ if change.versioned[0] or change.versioned[1]:
397 yield change
398 if report_changes:
399 if new_path is None:
400
401=== modified file 'breezy/delta.py'
402--- breezy/delta.py 2019-06-03 21:25:01 +0000
403+++ breezy/delta.py 2019-06-15 17:35:57 +0000
404@@ -125,48 +125,48 @@
405 delta = TreeDelta()
406 # mutter('start compare_trees')
407
408- for (file_id, path, content_change, versioned, parent_id, name, kind,
409- executable) in new_tree.iter_changes(old_tree, want_unchanged,
410- specific_files, extra_trees=extra_trees,
411- require_versioned=require_versioned,
412- want_unversioned=want_unversioned):
413- if versioned == (False, False):
414- delta.unversioned.append((path[1], None, kind[1]))
415- continue
416- if not include_root and (None, None) == parent_id:
417- continue
418- fully_present = tuple((versioned[x] and kind[x] is not None) for
419- x in range(2))
420+ for change in new_tree.iter_changes(
421+ old_tree, want_unchanged, specific_files, extra_trees=extra_trees,
422+ require_versioned=require_versioned,
423+ want_unversioned=want_unversioned):
424+ if change.versioned == (False, False):
425+ delta.unversioned.append((change.path[1], None, change.kind[1]))
426+ continue
427+ if not include_root and (None, None) == change.parent_id:
428+ continue
429+ fully_present = tuple(
430+ (change.versioned[x] and change.kind[x] is not None)
431+ for x in range(2))
432 if fully_present[0] != fully_present[1]:
433 if fully_present[1] is True:
434- delta.added.append((path[1], file_id, kind[1]))
435+ delta.added.append((change.path[1], change.file_id, change.kind[1]))
436 else:
437- if kind[0] == 'symlink' and not new_tree.supports_symlinks():
438+ if change.kind[0] == 'symlink' and not new_tree.supports_symlinks():
439 trace.warning(
440 'Ignoring "%s" as symlinks '
441- 'are not supported on this filesystem.' % (path[0],))
442+ 'are not supported on this filesystem.' % (change.path[0],))
443 else:
444- delta.removed.append((path[0], file_id, kind[0]))
445+ delta.removed.append(
446+ (change.path[0], change.file_id, change.kind[0]))
447 elif fully_present[0] is False:
448- delta.missing.append((path[1], file_id, kind[1]))
449- elif name[0] != name[1] or parent_id[0] != parent_id[1]:
450+ delta.missing.append((change.path[1], change.file_id, change.kind[1]))
451+ elif change.name[0] != change.name[1] or change.parent_id[0] != change.parent_id[1]:
452 # If the name changes, or the parent_id changes, we have a rename
453 # (if we move a parent, that doesn't count as a rename for the
454 # file)
455- delta.renamed.append((path[0],
456- path[1],
457- file_id,
458- kind[1],
459- content_change,
460- (executable[0] != executable[1])))
461- elif kind[0] != kind[1]:
462- delta.kind_changed.append((path[1], file_id, kind[0], kind[1]))
463- elif content_change or executable[0] != executable[1]:
464- delta.modified.append((path[1], file_id, kind[1],
465- content_change,
466- (executable[0] != executable[1])))
467+ delta.renamed.append(
468+ (change.path[0], change.path[1], change.file_id,
469+ change.kind[1], change.changed_content,
470+ (change.executable[0] != change.executable[1])))
471+ elif change.kind[0] != change.kind[1]:
472+ delta.kind_changed.append(
473+ (change.path[1], change.file_id, change.kind[0], change.kind[1]))
474+ elif change.changed_content or change.executable[0] != change.executable[1]:
475+ delta.modified.append((change.path[1], change.file_id, change.kind[1],
476+ change.changed_content,
477+ (change.executable[0] != change.executable[1])))
478 else:
479- delta.unchanged.append((path[1], file_id, kind[1]))
480+ delta.unchanged.append((change.path[1], change.file_id, change.kind[1]))
481
482 delta.removed.sort()
483 delta.added.sort()
484
485=== modified file 'breezy/diff.py'
486--- breezy/diff.py 2019-06-15 14:43:05 +0000
487+++ breezy/diff.py 2019-06-15 17:35:57 +0000
488@@ -1060,23 +1060,24 @@
489 def get_encoded_path(path):
490 if path is not None:
491 return path.encode(self.path_encoding, "replace")
492- for (file_id, paths, changed_content, versioned, parent, name, kind,
493- executable) in sorted(iterator, key=changes_key):
494+ for change in sorted(iterator, key=changes_key):
495 # The root does not get diffed, and items with no known kind (that
496 # is, missing) in both trees are skipped as well.
497- if parent == (None, None) or kind == (None, None):
498+ if change.parent_id == (None, None) or change.kind == (None, None):
499 continue
500- if kind[0] == 'symlink' and not self.new_tree.supports_symlinks():
501+ if change.kind[0] == 'symlink' and not self.new_tree.supports_symlinks():
502 warning(
503 'Ignoring "%s" as symlinks are not '
504- 'supported on this filesystem.' % (paths[0],))
505+ 'supported on this filesystem.' % (change.path[0],))
506 continue
507- oldpath, newpath = paths
508- oldpath_encoded = get_encoded_path(paths[0])
509- newpath_encoded = get_encoded_path(paths[1])
510- old_present = (kind[0] is not None and versioned[0])
511- new_present = (kind[1] is not None and versioned[1])
512- renamed = (parent[0], name[0]) != (parent[1], name[1])
513+ oldpath, newpath = change.path
514+ oldpath_encoded = get_encoded_path(change.path[0])
515+ newpath_encoded = get_encoded_path(change.path[1])
516+ old_present = (change.kind[0] is not None and change.versioned[0])
517+ new_present = (change.kind[1] is not None and change.versioned[1])
518+ executable = change.executable
519+ kind = change.kind
520+ renamed = (change.parent_id[0], change.name[0]) != (change.parent_id[1], change.name[1])
521
522 properties_changed = []
523 properties_changed.extend(
524@@ -1104,7 +1105,7 @@
525 # modified *somehow*, either content or execute bit.
526 self.to_file.write(b"=== modified %s '%s'%s\n" % (kind[0].encode('ascii'),
527 newpath_encoded, prop_str))
528- if changed_content:
529+ if change.changed_content:
530 self._diff(oldpath, newpath, kind[0], kind[1])
531 has_changes = 1
532 if renamed:
533
534=== modified file 'breezy/git/commit.py'
535--- breezy/git/commit.py 2019-06-15 13:38:17 +0000
536+++ breezy/git/commit.py 2019-06-15 17:35:57 +0000
537@@ -88,32 +88,32 @@
538
539 def record_iter_changes(self, workingtree, basis_revid, iter_changes):
540 seen_root = False
541- for (file_id, path, changed_content, versioned, parent, name, kind,
542- executable) in iter_changes:
543- if kind[1] in ("directory",):
544+ for change in iter_changes:
545+ if change.kind[1] in ("directory",):
546 self._inv_delta.append(
547- (path[0], path[1], file_id, entry_factory[kind[1]](
548- file_id, name[1], parent[1])))
549- if kind[0] in ("file", "symlink"):
550- self._blobs[path[0].encode("utf-8")] = None
551+ (change.path[0], change.path[1], change.file_id,
552+ entry_factory[change.kind[1]](
553+ change.file_id, change.name[1], change.parent_id[1])))
554+ if change.kind[0] in ("file", "symlink"):
555+ self._blobs[change.path[0].encode("utf-8")] = None
556 self._any_changes = True
557- if path[1] == "":
558+ if change.path[1] == "":
559 seen_root = True
560 continue
561 self._any_changes = True
562- if path[1] is None:
563- self._inv_delta.append((path[0], path[1], file_id, None))
564- self._blobs[path[0].encode("utf-8")] = None
565+ if change.path[1] is None:
566+ self._inv_delta.append((change.path[0], change.path[1], change.file_id, None))
567+ self._blobs[change.path[0].encode("utf-8")] = None
568 continue
569 try:
570- entry_kls = entry_factory[kind[1]]
571+ entry_kls = entry_factory[change.kind[1]]
572 except KeyError:
573- raise KeyError("unknown kind %s" % kind[1])
574- entry = entry_kls(file_id, name[1], parent[1])
575- if kind[1] == "file":
576- entry.executable = executable[1]
577+ raise KeyError("unknown kind %s" % change.kind[1])
578+ entry = entry_kls(change.file_id, change.name[1], change.parent_id[1])
579+ if change.kind[1] == "file":
580+ entry.executable = change.executable[1]
581 blob = Blob()
582- f, st = workingtree.get_file_with_stat(path[1])
583+ f, st = workingtree.get_file_with_stat(change.path[1])
584 try:
585 blob.data = f.read()
586 finally:
587@@ -122,29 +122,29 @@
588 entry.text_sha1 = osutils.sha_string(blob.data)
589 self.store.add_object(blob)
590 sha = blob.id
591- elif kind[1] == "symlink":
592- symlink_target = workingtree.get_symlink_target(path[1])
593+ elif change.kind[1] == "symlink":
594+ symlink_target = workingtree.get_symlink_target(change.path[1])
595 blob = Blob()
596 blob.data = symlink_target.encode("utf-8")
597 self.store.add_object(blob)
598 sha = blob.id
599 entry.symlink_target = symlink_target
600 st = None
601- elif kind[1] == "tree-reference":
602- sha = read_submodule_head(workingtree.abspath(path[1]))
603- reference_revision = workingtree.get_reference_revision(path[1])
604+ elif change.kind[1] == "tree-reference":
605+ sha = read_submodule_head(workingtree.abspath(change.path[1]))
606+ reference_revision = workingtree.get_reference_revision(change.path[1])
607 entry.reference_revision = reference_revision
608 st = None
609 else:
610- raise AssertionError("Unknown kind %r" % kind[1])
611- mode = object_mode(kind[1], executable[1])
612- self._inv_delta.append((path[0], path[1], file_id, entry))
613- encoded_new_path = path[1].encode("utf-8")
614+ raise AssertionError("Unknown kind %r" % change.kind[1])
615+ mode = object_mode(change.kind[1], change.executable[1])
616+ self._inv_delta.append((change.path[0], change.path[1], change.file_id, entry))
617+ encoded_new_path = change.path[1].encode("utf-8")
618 self._blobs[encoded_new_path] = (mode, sha)
619 if st is not None:
620- yield path[1], (entry.text_sha1, st)
621- if self._mapping.generate_file_id(encoded_new_path) != file_id:
622- self._override_fileids[encoded_new_path] = file_id
623+ yield change.path[1], (entry.text_sha1, st)
624+ if self._mapping.generate_file_id(encoded_new_path) != change.file_id:
625+ self._override_fileids[encoded_new_path] = change.file_id
626 else:
627 self._override_fileids[encoded_new_path] = None
628 if not seen_root and len(self.parents) == 0:
629
630=== modified file 'breezy/git/object_store.py'
631--- breezy/git/object_store.py 2019-06-06 22:22:47 +0000
632+++ breezy/git/object_store.py 2019-06-15 17:35:57 +0000
633@@ -249,16 +249,15 @@
634 raise KeyError
635
636 # Find all the changed blobs
637- for (file_id, path, changed_content, versioned, parent, name, kind,
638- executable) in tree.iter_changes(base_tree):
639- if name[1] in BANNED_FILENAMES:
640+ for change in tree.iter_changes(base_tree):
641+ if change.name[1] in BANNED_FILENAMES:
642 continue
643- if kind[1] == "file":
644- sha1 = tree.get_file_sha1(path[1])
645+ if change.kind[1] == "file":
646+ sha1 = tree.get_file_sha1(change.path[1])
647 blob_id = None
648 try:
649 (pfile_id, prevision) = find_unchanged_parent_ie(
650- file_id, kind[1], sha1, other_parent_trees)
651+ change.file_id, change.kind[1], sha1, other_parent_trees)
652 except KeyError:
653 pass
654 else:
655@@ -271,35 +270,35 @@
656 if not changed_content:
657 # no-change merge ?
658 blob = Blob()
659- blob.data = tree.get_file_text(path[1])
660+ blob.data = tree.get_file_text(change.path[1])
661 blob_id = blob.id
662 if blob_id is None:
663- new_blobs.append((path[1], file_id))
664+ new_blobs.append((change.path[1], change.file_id))
665 else:
666 shamap[path[1]] = blob_id
667 if add_cache_entry is not None:
668 add_cache_entry(
669 ("blob", blob_id),
670- (file_id, tree.get_file_revision(path[1])), path[1])
671- elif kind[1] == "symlink":
672- target = tree.get_symlink_target(path[1])
673+ (file_id, tree.get_file_revision(change.path[1])), change.path[1])
674+ elif change.kind[1] == "symlink":
675+ target = tree.get_symlink_target(change.path[1])
676 blob = symlink_to_blob(target)
677- shamap[path[1]] = blob.id
678+ shamap[change.path[1]] = blob.id
679 if add_cache_entry is not None:
680 add_cache_entry(
681- blob, (file_id, tree.get_file_revision(path[1])), path[1])
682+ blob, (change.file_id, tree.get_file_revision(change.path[1])), change.path[1])
683 try:
684 find_unchanged_parent_ie(
685- file_id, kind[1], target, other_parent_trees)
686+ change.file_id, change.kind[1], target, other_parent_trees)
687 except KeyError:
688- if changed_content:
689- yield (path[1], blob,
690- (file_id, tree.get_file_revision(path[1])))
691- elif kind[1] is None:
692- shamap[path[1]] = None
693- elif kind[1] != 'directory':
694- raise AssertionError(kind[1])
695- for p in path:
696+ if change.changed_content:
697+ yield (change.path[1], blob,
698+ (change.file_id, tree.get_file_revision(change.path[1])))
699+ elif change.kind[1] is None:
700+ shamap[change.path[1]] = None
701+ elif change.kind[1] != 'directory':
702+ raise AssertionError(change.kind[1])
703+ for p in change.path:
704 if p is None:
705 continue
706 dirty_dirs.add(osutils.dirname(p))
707
708=== modified file 'breezy/git/workingtree.py'
709--- breezy/git/workingtree.py 2019-06-04 00:08:59 +0000
710+++ breezy/git/workingtree.py 2019-06-15 17:35:57 +0000
711@@ -350,23 +350,22 @@
712
713 # Bail out if we are going to delete files we shouldn't
714 if not keep_files and not force:
715- for (file_id, path, content_change, versioned, parent_id, name,
716- kind, executable) in self.iter_changes(
717- self.basis_tree(), include_unchanged=True,
718- require_versioned=False, want_unversioned=True,
719- specific_files=files):
720- if versioned[0] is False:
721+ for change in self.iter_changes(
722+ self.basis_tree(), include_unchanged=True,
723+ require_versioned=False, want_unversioned=True,
724+ specific_files=files):
725+ if change.versioned[0] is False:
726 # The record is unknown or newly added
727- files_to_backup.append(path[1])
728+ files_to_backup.append(change.path[1])
729 files_to_backup.extend(
730- osutils.parent_directories(path[1]))
731- elif (content_change and (kind[1] is not None)
732- and osutils.is_inside_any(files, path[1])):
733+ osutils.parent_directories(change.path[1]))
734+ elif (change.changed_content and (change.kind[1] is not None)
735+ and osutils.is_inside_any(files, change.path[1])):
736 # Versioned and changed, but not deleted, and still
737 # in one of the dirs to be deleted.
738- files_to_backup.append(path[1])
739+ files_to_backup.append(change.path[1])
740 files_to_backup.extend(
741- osutils.parent_directories(path[1]))
742+ osutils.parent_directories(change.path[1]))
743
744 for f in files:
745 if f == '':
746
747=== modified file 'breezy/merge.py'
748--- breezy/merge.py 2019-06-03 05:21:20 +0000
749+++ breezy/merge.py 2019-06-15 17:35:57 +0000
750@@ -852,14 +852,13 @@
751 self.interesting_files, trees=[self.other_tree])
752 this_entries = dict(self.this_tree.iter_entries_by_dir(
753 specific_files=this_interesting_files))
754- for (file_id, paths, changed, versioned, parents, names, kind,
755- executable) in iterator:
756- if paths[0] is not None:
757+ for change in iterator:
758+ if change.path[0] is not None:
759 this_path = _mod_tree.find_previous_path(
760- self.base_tree, self.this_tree, paths[0])
761+ self.base_tree, self.this_tree, change.path[0])
762 else:
763 this_path = _mod_tree.find_previous_path(
764- self.other_tree, self.this_tree, paths[1])
765+ self.other_tree, self.this_tree, change.path[1])
766 this_entry = this_entries.get(this_path)
767 if this_entry is not None:
768 this_name = this_entry.name
769@@ -869,12 +868,13 @@
770 this_name = None
771 this_parent = None
772 this_executable = None
773- parents3 = parents + (this_parent,)
774- names3 = names + (this_name,)
775- paths3 = paths + (this_path, )
776- executable3 = executable + (this_executable,)
777- result.append((file_id, changed, paths3,
778- parents3, names3, executable3))
779+ parents3 = change.parent_id + (this_parent,)
780+ names3 = change.name + (this_name,)
781+ paths3 = change.path + (this_path, )
782+ executable3 = change.executable + (this_executable,)
783+ result.append(
784+ (change.file_id, change.changed_content, paths3,
785+ parents3, names3, executable3))
786 return result
787
788 def _entries_lca(self):
789
790=== modified file 'breezy/mutabletree.py'
791--- breezy/mutabletree.py 2019-06-03 23:45:30 +0000
792+++ breezy/mutabletree.py 2019-06-15 17:35:57 +0000
793@@ -202,7 +202,7 @@
794 try:
795 change = next(changes)
796 # Exclude root (talk about black magic... --vila 20090629)
797- if change[4] == (None, None):
798+ if change.parent_id == (None, None):
799 change = next(changes)
800 return True
801 except StopIteration:
802
803=== modified file 'breezy/plugins/fastimport/revision_store.py'
804--- breezy/plugins/fastimport/revision_store.py 2018-11-25 20:44:56 +0000
805+++ breezy/plugins/fastimport/revision_store.py 2019-06-15 17:35:57 +0000
806@@ -25,6 +25,7 @@
807 osutils,
808 revision as _mod_revision,
809 )
810+from ...tree import TreeChange
811 from ...bzr import (
812 inventory,
813 )
814@@ -118,49 +119,53 @@
815 old_ie = None
816 if ie is None:
817 raise AssertionError('How is both old and new None?')
818- change = (file_id,
819- (old_path, new_path),
820- False,
821- (False, False),
822- (None, None),
823- (None, None),
824- (None, None),
825- (None, None),
826- )
827- change = (file_id,
828- (old_path, new_path),
829- True,
830- (False, True),
831- (None, ie.parent_id),
832- (None, ie.name),
833- (None, ie.kind),
834- (None, ie.executable),
835- )
836+ change = TreeChange(
837+ file_id,
838+ (old_path, new_path),
839+ False,
840+ (False, False),
841+ (None, None),
842+ (None, None),
843+ (None, None),
844+ (None, None),
845+ )
846+ change = TreeChange(
847+ file_id,
848+ (old_path, new_path),
849+ True,
850+ (False, True),
851+ (None, ie.parent_id),
852+ (None, ie.name),
853+ (None, ie.kind),
854+ (None, ie.executable),
855+ )
856 else:
857 if ie is None:
858- change = (file_id,
859- (old_path, new_path),
860- True,
861- (True, False),
862- (old_ie.parent_id, None),
863- (old_ie.name, None),
864- (old_ie.kind, None),
865- (old_ie.executable, None),
866- )
867+ change = TreeChange(
868+ file_id,
869+ (old_path, new_path),
870+ True,
871+ (True, False),
872+ (old_ie.parent_id, None),
873+ (old_ie.name, None),
874+ (old_ie.kind, None),
875+ (old_ie.executable, None),
876+ )
877 else:
878 content_modified = (ie.text_sha1 != old_ie.text_sha1 or
879 ie.text_size != old_ie.text_size)
880 # TODO: ie.kind != old_ie.kind
881 # TODO: symlinks changing targets, content_modified?
882- change = (file_id,
883- (old_path, new_path),
884- content_modified,
885- (True, True),
886- (old_ie.parent_id, ie.parent_id),
887- (old_ie.name, ie.name),
888- (old_ie.kind, ie.kind),
889- (old_ie.executable, ie.executable),
890- )
891+ change = TreeChange(
892+ file_id,
893+ (old_path, new_path),
894+ content_modified,
895+ (True, True),
896+ (old_ie.parent_id, ie.parent_id),
897+ (old_ie.name, ie.name),
898+ (old_ie.kind, ie.kind),
899+ (old_ie.executable, ie.executable),
900+ )
901 yield change
902
903
904
905=== modified file 'breezy/plugins/launchpad/lp_propose.py'
906--- breezy/plugins/launchpad/lp_propose.py 2019-01-28 21:00:58 +0000
907+++ breezy/plugins/launchpad/lp_propose.py 2019-06-15 17:35:57 +0000
908@@ -224,7 +224,6 @@
909
910 def modified_files(old_tree, new_tree):
911 """Return a list of paths in the new tree with modified contents."""
912- for f, (op, path), c, v, p, n, (ok, k), e in new_tree.iter_changes(
913- old_tree):
914- if c and k == 'file':
915+ for change in new_tree.iter_changes(old_tree):
916+ if change.changed_content and change.kind[1] == 'file':
917 yield str(path)
918
919=== modified file 'breezy/plugins/propose/launchpad.py'
920--- breezy/plugins/propose/launchpad.py 2019-06-15 14:25:08 +0000
921+++ breezy/plugins/propose/launchpad.py 2019-06-15 17:35:57 +0000
922@@ -687,7 +687,6 @@
923
924 def modified_files(old_tree, new_tree):
925 """Return a list of paths in the new tree with modified contents."""
926- for f, (op, path), c, v, p, n, (ok, k), e in new_tree.iter_changes(
927- old_tree):
928- if c and k == 'file':
929+ for change in new_tree.iter_changes(old_tree):
930+ if change.changed_content and change.kind[1] == 'file':
931 yield str(path)
932
933=== modified file 'breezy/rename_map.py'
934--- breezy/rename_map.py 2018-11-11 04:08:32 +0000
935+++ breezy/rename_map.py 2019-06-15 17:35:57 +0000
936@@ -177,24 +177,24 @@
937 with ui_factory.nested_progress_bar() as task:
938 iterator = self.tree.iter_changes(basis, want_unversioned=True,
939 pb=task)
940- for (file_id, paths, changed_content, versioned, parent, name,
941- kind, executable) in iterator:
942- if kind[1] is None and versioned[1]:
943- if not self.tree.has_filename(self.tree.id2path(parent[0])):
944+ for change in iterator:
945+ if change.kind[1] is None and change.versioned[1]:
946+ if not self.tree.has_filename(
947+ self.tree.id2path(change.parent_id[0])):
948 missing_parents.setdefault(
949- parent[0], set()).add(file_id)
950- if kind[0] == 'file':
951- missing_files.add(file_id)
952+ change.parent_id[0], set()).add(change.file_id)
953+ if change.kind[0] == 'file':
954+ missing_files.add(change.file_id)
955 else:
956 # other kinds are not handled
957 pass
958- if versioned == (False, False):
959- if self.tree.is_ignored(paths[1]):
960+ if change.versioned == (False, False):
961+ if self.tree.is_ignored(change.path[1]):
962 continue
963- if kind[1] == 'file':
964- candidate_files.add(paths[1])
965- if kind[1] == 'directory':
966- for _dir, children in self.tree.walkdirs(paths[1]):
967+ if change.kind[1] == 'file':
968+ candidate_files.add(change.path[1])
969+ if change.kind[1] == 'directory':
970+ for _dir, children in self.tree.walkdirs(change.path[1]):
971 for child in children:
972 if child[2] == 'file':
973 candidate_files.add(child[0])
974
975=== modified file 'breezy/shelf.py'
976--- breezy/shelf.py 2018-11-17 16:53:10 +0000
977+++ breezy/shelf.py 2019-06-15 17:35:57 +0000
978@@ -98,39 +98,38 @@
979 ('modify text', file_id)
980 ('modify target', file_id, target_target, work_target)
981 """
982- for (file_id, paths, changed, versioned, parents, names, kind,
983- executable) in self.iter_changes:
984+ for change in self.iter_changes:
985 # don't shelve add of tree root. Working tree should never
986 # lack roots, and bzr misbehaves when they do.
987 # FIXME ADHB (2009-08-09): should still shelve adds of tree roots
988 # when a tree root was deleted / renamed.
989- if kind[0] is None and names[1] == '':
990+ if change.kind[0] is None and change.name[1] == '':
991 continue
992 # Also don't shelve deletion of tree root.
993- if kind[1] is None and names[0] == '':
994+ if change.kind[1] is None and change.name[0] == '':
995 continue
996- if kind[0] is None or versioned[0] is False:
997- self.creation[file_id] = (kind[1], names[1], parents[1],
998- versioned)
999- yield ('add file', file_id, kind[1], paths[1])
1000- elif kind[1] is None or versioned[0] is False:
1001- self.deletion[file_id] = (kind[0], names[0], parents[0],
1002- versioned)
1003- yield ('delete file', file_id, kind[0], paths[0])
1004+ if change.kind[0] is None or change.versioned[0] is False:
1005+ self.creation[change.file_id] = (
1006+ change.kind[1], change.name[1], change.parent_id[1], change.versioned)
1007+ yield ('add file', change.file_id, change.kind[1], change.path[1])
1008+ elif change.kind[1] is None or change.versioned[0] is False:
1009+ self.deletion[change.file_id] = (
1010+ change.kind[0], change.name[0], change.parent_id[0], change.versioned)
1011+ yield ('delete file', change.file_id, change.kind[0], change.path[0])
1012 else:
1013- if names[0] != names[1] or parents[0] != parents[1]:
1014- self.renames[file_id] = (names, parents)
1015- yield ('rename', file_id) + paths
1016+ if change.name[0] != change.name[1] or change.parent_id[0] != change.parent_id[1]:
1017+ self.renames[change.file_id] = (change.name, change.parent_id)
1018+ yield ('rename', change.file_id) + change.path
1019
1020- if kind[0] != kind[1]:
1021- yield ('change kind', file_id, kind[0], kind[1], paths[0])
1022- elif kind[0] == 'symlink':
1023- t_target = self.target_tree.get_symlink_target(paths[0])
1024- w_target = self.work_tree.get_symlink_target(paths[1])
1025- yield ('modify target', file_id, paths[0], t_target,
1026+ if change.kind[0] != change.kind[1]:
1027+ yield ('change kind', change.file_id, change.kind[0], change.kind[1], change.path[0])
1028+ elif change.kind[0] == 'symlink':
1029+ t_target = self.target_tree.get_symlink_target(change.path[0])
1030+ w_target = self.work_tree.get_symlink_target(change.path[1])
1031+ yield ('modify target', change.file_id, change.path[0], t_target,
1032 w_target)
1033- elif changed:
1034- yield ('modify text', file_id)
1035+ elif change.changed_content:
1036+ yield ('modify text', change.file_id)
1037
1038 def shelve_change(self, change):
1039 """Shelve a change in the iter_shelvable format."""
1040
1041=== modified file 'breezy/tests/per_intertree/test_compare.py'
1042--- breezy/tests/per_intertree/test_compare.py 2018-12-18 20:55:37 +0000
1043+++ breezy/tests/per_intertree/test_compare.py 2019-06-15 17:35:57 +0000
1044@@ -26,6 +26,7 @@
1045 transform,
1046 )
1047 from breezy.osutils import has_symlinks
1048+from breezy.tree import TreeChange
1049 from breezy.tests.per_intertree import TestCaseWithTwoTrees
1050 from breezy.tests import (
1051 features,
1052@@ -50,10 +51,9 @@
1053
1054 def _change_key(change):
1055 """Return a valid key for sorting Tree.iter_changes entries."""
1056- (file_id, paths, content_changed, versioned, parent, name, kind,
1057- executable) = change
1058- return (file_id or b'', (paths[0] or '', paths[1] or ''), versioned,
1059- parent, name, kind, executable)
1060+ return (change.file_id or b'', (change.path[0] or '', change.path[1] or ''),
1061+ change.versioned, change.parent_id, change.name, change.kind,
1062+ change.executable)
1063
1064
1065 class TestCompare(TestCaseWithTwoTrees):
1066@@ -553,9 +553,10 @@
1067
1068 def added(self, tree, file_id):
1069 path, entry = self.get_path_entry(tree, file_id)
1070- return (file_id, (None, path), True, (False, True), (None, entry.parent_id),
1071- (None, entry.name), (None, entry.kind),
1072- (None, entry.executable))
1073+ return TreeChange(
1074+ file_id, (None, path), True, (False, True), (None, entry.parent_id),
1075+ (None, entry.name), (None, entry.kind),
1076+ (None, entry.executable))
1077
1078 @staticmethod
1079 def get_path_entry(tree, file_id):
1080@@ -569,43 +570,48 @@
1081
1082 def content_changed(self, tree, file_id):
1083 path, entry = self.get_path_entry(tree, file_id)
1084- return (file_id, (path, path), True, (True, True),
1085- (entry.parent_id, entry.parent_id),
1086- (entry.name, entry.name), (entry.kind, entry.kind),
1087- (entry.executable, entry.executable))
1088+ return TreeChange(
1089+ file_id, (path, path), True, (True, True),
1090+ (entry.parent_id, entry.parent_id),
1091+ (entry.name, entry.name), (entry.kind, entry.kind),
1092+ (entry.executable, entry.executable))
1093
1094 def kind_changed(self, from_tree, to_tree, file_id):
1095 from_path, old_entry = self.get_path_entry(from_tree, file_id)
1096 path, new_entry = self.get_path_entry(to_tree, file_id)
1097- return (file_id, (from_path, path), True, (True, True),
1098- (old_entry.parent_id, new_entry.parent_id),
1099- (old_entry.name, new_entry.name),
1100- (old_entry.kind, new_entry.kind),
1101- (old_entry.executable, new_entry.executable))
1102+ return TreeChange(
1103+ file_id, (from_path, path), True, (True, True),
1104+ (old_entry.parent_id, new_entry.parent_id),
1105+ (old_entry.name, new_entry.name),
1106+ (old_entry.kind, new_entry.kind),
1107+ (old_entry.executable, new_entry.executable))
1108
1109 def missing(self, file_id, from_path, to_path, parent_id, kind):
1110 _, from_basename = os.path.split(from_path)
1111 _, to_basename = os.path.split(to_path)
1112 # missing files have both paths, but no kind.
1113- return (file_id, (from_path, to_path), True, (True, True),
1114- (parent_id, parent_id),
1115- (from_basename, to_basename), (kind, None), (False, False))
1116+ return TreeChange(
1117+ file_id, (from_path, to_path), True, (True, True),
1118+ (parent_id, parent_id),
1119+ (from_basename, to_basename), (kind, None), (False, False))
1120
1121 def deleted(self, tree, file_id):
1122 entry = tree.root_inventory.get_entry(file_id)
1123 path = tree.id2path(file_id)
1124- return (file_id, (path, None), True, (True, False), (entry.parent_id, None),
1125- (entry.name, None), (entry.kind, None),
1126- (entry.executable, None))
1127+ return TreeChange(
1128+ file_id, (path, None), True, (True, False), (entry.parent_id, None),
1129+ (entry.name, None), (entry.kind, None),
1130+ (entry.executable, None))
1131
1132 def renamed(self, from_tree, to_tree, file_id, content_changed):
1133 from_path, from_entry = self.get_path_entry(from_tree, file_id)
1134 to_path, to_entry = self.get_path_entry(to_tree, file_id)
1135- return (file_id, (from_path, to_path), content_changed, (True, True),
1136- (from_entry.parent_id, to_entry.parent_id),
1137- (from_entry.name, to_entry.name),
1138- (from_entry.kind, to_entry.kind),
1139- (from_entry.executable, to_entry.executable))
1140+ return TreeChange(
1141+ file_id, (from_path, to_path), content_changed, (True, True),
1142+ (from_entry.parent_id, to_entry.parent_id),
1143+ (from_entry.name, to_entry.name),
1144+ (from_entry.kind, to_entry.kind),
1145+ (from_entry.executable, to_entry.executable))
1146
1147 def unchanged(self, tree, file_id):
1148 path, entry = self.get_path_entry(tree, file_id)
1149@@ -613,17 +619,19 @@
1150 name = entry.name
1151 kind = entry.kind
1152 executable = entry.executable
1153- return (file_id, (path, path), False, (True, True),
1154- (parent, parent), (name, name), (kind, kind),
1155- (executable, executable))
1156+ return TreeChange(
1157+ file_id, (path, path), False, (True, True),
1158+ (parent, parent), (name, name), (kind, kind),
1159+ (executable, executable))
1160
1161 def unversioned(self, tree, path):
1162 """Create an unversioned result."""
1163 _, basename = os.path.split(path)
1164 kind = tree._comparison_data(None, path)[0]
1165- return (None, (None, path), True, (False, False), (None, None),
1166- (None, basename), (None, kind),
1167- (None, False))
1168+ return TreeChange(
1169+ None, (None, path), True, (False, False), (None, None),
1170+ (None, basename), (None, kind),
1171+ (None, False))
1172
1173 def sorted(self, changes):
1174 return sorted(changes, key=_change_key)
1175@@ -1086,8 +1094,9 @@
1176 tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1177 self.not_applicable_if_missing_in('file', tree1)
1178 root_id = tree1.path2id('')
1179- expected = [(b'file-id', ('file', None), False, (True, False),
1180- (root_id, None), ('file', None), (None, None), (False, None))]
1181+ expected = [
1182+ TreeChange(b'file-id', ('file', None), False, (True, False),
1183+ (root_id, None), ('file', None), (None, None), (False, None))]
1184 self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
1185
1186 def test_only_in_target_and_missing(self):
1187@@ -1100,8 +1109,9 @@
1188 tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1189 self.not_applicable_if_missing_in('file', tree2)
1190 root_id = tree1.path2id('')
1191- expected = [(b'file-id', (None, 'file'), False, (False, True),
1192- (None, root_id), (None, 'file'), (None, None), (None, False))]
1193+ expected = [
1194+ TreeChange(b'file-id', (None, 'file'), False, (False, True),
1195+ (None, root_id), (None, 'file'), (None, None), (None, False))]
1196 self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
1197
1198 def test_only_in_target_missing_subtree_specific_bug_367632(self):
1199@@ -1116,10 +1126,12 @@
1200 self.not_applicable_if_missing_in('a-dir', tree2)
1201 root_id = tree1.path2id('')
1202 expected = [
1203- (b'dir-id', (None, 'a-dir'), False, (False, True),
1204- (None, root_id), (None, 'a-dir'), (None, None), (None, False)),
1205- (b'file-id', (None, 'a-dir/a-file'), False, (False, True),
1206- (None, b'dir-id'), (None, 'a-file'), (None, None), (None, False))
1207+ TreeChange(
1208+ b'dir-id', (None, 'a-dir'), False, (False, True),
1209+ (None, root_id), (None, 'a-dir'), (None, None), (None, False)),
1210+ TreeChange(
1211+ b'file-id', (None, 'a-dir/a-file'), False, (False, True),
1212+ (None, b'dir-id'), (None, 'a-file'), (None, None), (None, False))
1213 ]
1214 # bug 367632 showed that specifying the root broke some code paths,
1215 # so we check this contract with and without it.
1216@@ -1136,10 +1148,11 @@
1217 tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1218 self.assertEqual(sorted([self.unchanged(tree1, b'root-id'),
1219 self.unchanged(tree1, b'b-id'),
1220- (b'a-id', ('a', 'd'), True, (True, True),
1221- (b'root-id', b'root-id'), ('a',
1222- 'd'), ('file', 'file'),
1223- (False, False)), self.unchanged(tree1, b'c-id')]),
1224+ TreeChange(
1225+ b'a-id', ('a', 'd'), True, (True, True),
1226+ (b'root-id', b'root-id'), ('a', 'd'),
1227+ ('file', 'file'),
1228+ (False, False)), self.unchanged(tree1, b'c-id')]),
1229 self.do_iter_changes(tree1, tree2, include_unchanged=True))
1230
1231 def test_compare_subtrees(self):
1232@@ -1163,22 +1176,24 @@
1233 self.assertEqual([], list(tree2.iter_changes(tree1)))
1234 subtree1.commit('commit', rev_id=b'commit-a')
1235 self.assertEqual([
1236- (b'root-id',
1237- (u'', u''),
1238- False,
1239- (True, True),
1240- (None, None),
1241- (u'', u''),
1242- ('directory', 'directory'),
1243- (False, False)),
1244- (b'subtree-id',
1245- ('sub', 'sub',),
1246- False,
1247- (True, True),
1248- (b'root-id', b'root-id'),
1249- ('sub', 'sub'),
1250- ('tree-reference', 'tree-reference'),
1251- (False, False))],
1252+ TreeChange(
1253+ b'root-id',
1254+ (u'', u''),
1255+ False,
1256+ (True, True),
1257+ (None, None),
1258+ (u'', u''),
1259+ ('directory', 'directory'),
1260+ (False, False)),
1261+ TreeChange(
1262+ b'subtree-id',
1263+ ('sub', 'sub',),
1264+ False,
1265+ (True, True),
1266+ (b'root-id', b'root-id'),
1267+ ('sub', 'sub'),
1268+ ('tree-reference', 'tree-reference'),
1269+ (False, False))],
1270 list(tree2.iter_changes(tree1,
1271 include_unchanged=True)))
1272
1273
1274=== modified file 'breezy/tests/per_repository/test_check.py'
1275--- breezy/tests/per_repository/test_check.py 2018-11-11 04:08:32 +0000
1276+++ breezy/tests/per_repository/test_check.py 2019-06-15 17:35:57 +0000
1277@@ -20,6 +20,7 @@
1278 from breezy import (
1279 revision as _mod_revision,
1280 )
1281+from breezy.tree import TreeChange
1282 from breezy.tests.per_repository import TestCaseWithRepository
1283
1284
1285@@ -32,8 +33,9 @@
1286 self.overrideEnv('BRZ_EMAIL', 'foo@sample.com')
1287 builder = branch.get_commit_builder([], branch.get_config_stack())
1288 list(builder.record_iter_changes(None, _mod_revision.NULL_REVISION, [
1289- (b'TREE_ROOT', (None, ''), True, (False, True), (None, None),
1290- (None, ''), (None, 'directory'), (None, False))]))
1291+ TreeChange(
1292+ b'TREE_ROOT', (None, ''), True, (False, True), (None, None),
1293+ (None, ''), (None, 'directory'), (None, False))]))
1294 builder.finish_inventory()
1295 rev_id = builder.commit('first post')
1296 result = branch.repository.check(None, check_repo=True)
1297
1298=== modified file 'breezy/tests/per_repository/test_commit_builder.py'
1299--- breezy/tests/per_repository/test_commit_builder.py 2018-11-25 20:44:56 +0000
1300+++ breezy/tests/per_repository/test_commit_builder.py 2019-06-15 17:35:57 +0000
1301@@ -26,6 +26,7 @@
1302 revision as _mod_revision,
1303 tests,
1304 )
1305+from breezy.tree import TreeChange
1306 from breezy.bzr import (
1307 inventorytree,
1308 )
1309@@ -193,10 +194,11 @@
1310 with tree.lock_write():
1311 builder = tree.branch.get_commit_builder([rev_id])
1312 try:
1313- delete_change = (foo_id, ('foo', None), True, (True, False),
1314- (tree.path2id(''), None), ('foo',
1315- None), ('file', None),
1316- (False, None))
1317+ delete_change = TreeChange(
1318+ foo_id, ('foo', None), True, (True, False),
1319+ (tree.path2id(''), None),
1320+ ('foo', None), ('file', None),
1321+ (False, None))
1322 list(builder.record_iter_changes(tree, rev_id,
1323 [delete_change]))
1324 self.assertEqual(("foo", None, foo_id, None),
1325
1326=== modified file 'breezy/tests/test__dirstate_helpers.py'
1327--- breezy/tests/test__dirstate_helpers.py 2019-06-03 21:25:01 +0000
1328+++ breezy/tests/test__dirstate_helpers.py 2019-06-15 17:35:57 +0000
1329@@ -1260,7 +1260,7 @@
1330 state._sha1_provider = UppercaseSHA1Provider()
1331 # If we used the standard provider, it would look like nothing has
1332 # changed
1333- file_ids_changed = [change[0] for change
1334+ file_ids_changed = [change.file_id for change
1335 in tree.iter_changes(tree.basis_tree())]
1336 self.assertEqual([b'a-file-id'], file_ids_changed)
1337
1338@@ -1291,12 +1291,9 @@
1339 self.overrideAttr(dirstate, '_process_entry', self._process_entry)
1340
1341 def assertChangedFileIds(self, expected, tree):
1342- tree.lock_read()
1343- try:
1344- file_ids = [info[0] for info
1345+ with tree.lock_read():
1346+ file_ids = [info.file_id for info
1347 in tree.iter_changes(tree.basis_tree())]
1348- finally:
1349- tree.unlock()
1350 self.assertEqual(sorted(expected), sorted(file_ids))
1351
1352 def test_exceptions_raised(self):
1353
1354=== modified file 'breezy/tests/test_commit.py'
1355--- breezy/tests/test_commit.py 2019-06-03 23:24:45 +0000
1356+++ breezy/tests/test_commit.py 2019-06-15 17:35:57 +0000
1357@@ -38,6 +38,7 @@
1358 BzrError,
1359 LockContention,
1360 )
1361+from ..tree import TreeChange
1362 from . import (
1363 TestCase,
1364 TestCaseWithTransport,
1365@@ -894,30 +895,34 @@
1366
1367 def test_add_file_not_excluded(self):
1368 changes = [
1369- ('fid', (None, 'newpath'),
1370- 0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
1371- ('file', 'file'), (True, True))]
1372+ TreeChange(
1373+ 'fid', (None, 'newpath'),
1374+ 0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
1375+ ('file', 'file'), (True, True))]
1376 self.assertEqual(changes, list(
1377 filter_excluded(changes, ['otherpath'])))
1378
1379 def test_add_file_excluded(self):
1380 changes = [
1381- ('fid', (None, 'newpath'),
1382- 0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
1383- ('file', 'file'), (True, True))]
1384+ TreeChange(
1385+ 'fid', (None, 'newpath'),
1386+ 0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
1387+ ('file', 'file'), (True, True))]
1388 self.assertEqual([], list(filter_excluded(changes, ['newpath'])))
1389
1390 def test_delete_file_excluded(self):
1391 changes = [
1392- ('fid', ('somepath', None),
1393- 0, (False, None), ('pid', None), ('newpath', None),
1394- ('file', None), (True, None))]
1395+ TreeChange(
1396+ 'fid', ('somepath', None),
1397+ 0, (False, None), ('pid', None), ('newpath', None),
1398+ ('file', None), (True, None))]
1399 self.assertEqual([], list(filter_excluded(changes, ['somepath'])))
1400
1401 def test_move_from_or_to_excluded(self):
1402 changes = [
1403- ('fid', ('oldpath', 'newpath'),
1404- 0, (False, False), ('pid', 'pid'), ('oldpath', 'newpath'),
1405- ('file', 'file'), (True, True))]
1406+ TreeChange(
1407+ 'fid', ('oldpath', 'newpath'),
1408+ 0, (False, False), ('pid', 'pid'), ('oldpath', 'newpath'),
1409+ ('file', 'file'), (True, True))]
1410 self.assertEqual([], list(filter_excluded(changes, ['oldpath'])))
1411 self.assertEqual([], list(filter_excluded(changes, ['newpath'])))
1412
1413=== modified file 'breezy/tests/test_transform.py'
1414--- breezy/tests/test_transform.py 2019-06-03 23:45:30 +0000
1415+++ breezy/tests/test_transform.py 2019-06-15 17:35:57 +0000
1416@@ -2838,7 +2838,7 @@
1417 self.addCleanup(preview.finalize)
1418 preview.delete_versioned(preview.trans_id_tree_path('foo'))
1419 preview_tree = preview.get_preview_tree()
1420- out = StringIO()
1421+ out = BytesIO()
1422 log = BytesIO()
1423 trace.push_log_file(log)
1424 os_symlink = getattr(os, 'symlink', None)
1425@@ -2847,8 +2847,7 @@
1426 show_diff_trees(revision_tree, preview_tree, out)
1427 lines = out.getvalue().splitlines()
1428 finally:
1429- if os_symlink:
1430- os.symlink = os_symlink
1431+ os.symlink = os_symlink
1432 self.assertContainsRe(
1433 log.getvalue(),
1434 b'Ignoring "foo" as symlinks are not supported on this filesystem')
1435
1436=== modified file 'breezy/transform.py'
1437--- breezy/transform.py 2019-03-04 01:44:35 +0000
1438+++ breezy/transform.py 2019-06-15 17:35:57 +0000
1439@@ -71,6 +71,7 @@
1440 )
1441 from .tree import (
1442 find_previous_path,
1443+ TreeChange,
1444 )
1445
1446
1447@@ -1002,16 +1003,17 @@
1448 and from_parent == to_parent and from_name == to_name
1449 and from_executable == to_executable):
1450 continue
1451- results.append((file_id, (from_path, to_path), modified,
1452- (from_versioned, to_versioned),
1453- (from_parent, to_parent),
1454- (from_name, to_name),
1455- (from_kind, to_kind),
1456- (from_executable, to_executable)))
1457+ results.append(
1458+ TreeChange(
1459+ file_id, (from_path, to_path), modified,
1460+ (from_versioned, to_versioned),
1461+ (from_parent, to_parent),
1462+ (from_name, to_name),
1463+ (from_kind, to_kind),
1464+ (from_executable, to_executable)))
1465
1466- def path_key(t):
1467- paths = t[1]
1468- return (paths[0] or '', paths[1] or '')
1469+ def path_key(c):
1470+ return (c.path[0] or '', c.path[1] or '')
1471 return iter(sorted(results, key=path_key))
1472
1473 def get_preview_tree(self):
1474@@ -1991,7 +1993,7 @@
1475 self._all_children_cache = {}
1476 self._path2trans_id_cache = {}
1477 self._final_name_cache = {}
1478- self._iter_changes_cache = dict((c[0], c) for c in
1479+ self._iter_changes_cache = dict((c.file_id, c) for c in
1480 self._transform.iter_changes())
1481
1482 def _content_change(self, file_id):
1483@@ -2413,8 +2415,8 @@
1484 if changes is None:
1485 get_old = True
1486 else:
1487- changed_content, versioned, kind = (changes[2], changes[3],
1488- changes[6])
1489+ changed_content, versioned, kind = (
1490+ changes.changed_content, changes.versioned, changes.kind)
1491 if kind[1] is None:
1492 return None
1493 get_old = (kind[0] == 'file' and versioned[0])
1494@@ -2693,8 +2695,9 @@
1495 new_desired_files = desired_files
1496 else:
1497 iter = accelerator_tree.iter_changes(tree, include_unchanged=True)
1498- unchanged = [(p[0], p[1]) for (f, p, c, v, d, n, k, e)
1499- in iter if not (c or e[0] != e[1])]
1500+ unchanged = [
1501+ change.path for change in iter
1502+ if not (change.changed_content or change.executable[0] != change.executable[1])]
1503 if accelerator_tree.supports_content_filtering():
1504 unchanged = [(tp, ap) for (tp, ap) in unchanged
1505 if not next(accelerator_tree.iter_search_rules([ap]))]
1506@@ -2907,19 +2910,19 @@
1507 skip_root = False
1508 try:
1509 deferred_files = []
1510- for id_num, (file_id, path, changed_content, versioned, parent, name,
1511- kind, executable) in enumerate(change_list):
1512- target_path, wt_path = path
1513- target_versioned, wt_versioned = versioned
1514- target_parent, wt_parent = parent
1515- target_name, wt_name = name
1516- target_kind, wt_kind = kind
1517- target_executable, wt_executable = executable
1518+ for id_num, change in enumerate(change_list):
1519+ file_id = change.file_id
1520+ target_path, wt_path = change.path
1521+ target_versioned, wt_versioned = change.versioned
1522+ target_parent, wt_parent = change.parent_id
1523+ target_name, wt_name = change.name
1524+ target_kind, wt_kind = change.kind
1525+ target_executable, wt_executable = change.executable
1526 if skip_root and wt_parent is None:
1527 continue
1528 trans_id = tt.trans_id_file_id(file_id)
1529 mode_id = None
1530- if changed_content:
1531+ if change.changed_content:
1532 keep_content = False
1533 if wt_kind == 'file' and (backups or target_kind is None):
1534 wt_sha1 = working_tree.get_file_sha1(wt_path)
1535@@ -3231,18 +3234,16 @@
1536 """
1537 tt = TreeTransform(target_tree)
1538 try:
1539- for (file_id, paths, changed_content, versioned, parent, name, kind,
1540- executable) in target_tree.iter_changes(source_tree,
1541- include_unchanged=True):
1542- if changed_content:
1543- continue
1544- if kind != ('file', 'file'):
1545- continue
1546- if executable[0] != executable[1]:
1547- continue
1548- trans_id = tt.trans_id_tree_path(paths[1])
1549+ for change in target_tree.iter_changes(source_tree, include_unchanged=True):
1550+ if change.changed_content:
1551+ continue
1552+ if change.kind != ('file', 'file'):
1553+ continue
1554+ if change.executable[0] != change.executable[1]:
1555+ continue
1556+ trans_id = tt.trans_id_tree_path(change.path[1])
1557 tt.delete_contents(trans_id)
1558- tt.create_hardlink(source_tree.abspath(paths[0]), trans_id)
1559+ tt.create_hardlink(source_tree.abspath(change.path[0]), trans_id)
1560 tt.apply()
1561 finally:
1562 tt.finalize()
1563
1564=== modified file 'breezy/tree.py'
1565--- breezy/tree.py 2019-06-15 15:17:02 +0000
1566+++ breezy/tree.py 2019-06-15 17:35:57 +0000
1567@@ -153,11 +153,21 @@
1568 return tuple(self) == other
1569 return False
1570
1571+ def __lt__(self, other):
1572+ return tuple(self) < tuple(other)
1573+
1574 def __getitem__(self, i):
1575 if isinstance(i, slice):
1576 return tuple(self).__getitem__(i)
1577 return getattr(self, self.__slots__[i])
1578
1579+ def discard_new(self):
1580+ return self.__class__(
1581+ self.file_id, (self.path[0], None), self.changed_content,
1582+ (self.versioned[0], None), (self.parent_id[0], None),
1583+ (self.name[0], None), (self.kind[0], None),
1584+ (self.executable[0], None))
1585+
1586
1587 class Tree(object):
1588 """Abstract file tree.
1589@@ -1094,18 +1104,18 @@
1590 new_parent_id = result[4][1]
1591 precise_file_ids.add(new_parent_id)
1592 if changes:
1593- if (result[6][0] == 'directory' and
1594- result[6][1] != 'directory'):
1595+ if (result.kind[0] == 'directory' and
1596+ result.kind[1] != 'directory'):
1597 # This stopped being a directory, the old children have
1598 # to be included.
1599 if source_entry is None:
1600 # Reusing a discarded change.
1601 source_entry = self._get_entry(
1602- self.source, result[1][0])
1603+ self.source, result.path[0])
1604 precise_file_ids.update(
1605 child.file_id
1606- for child in self.source.iter_child_entries(result[1][0]))
1607- changed_file_ids.add(result[0])
1608+ for child in self.source.iter_child_entries(result.path[0]))
1609+ changed_file_ids.add(result.file_id)
1610 yield result
1611
1612 def file_content_matches(

Subscribers

People subscribed via source and target branches