Merge lp:~jelmer/brz/objects 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
Merge into: lp:brz
Diff against target: 369 lines (+133/-82)
5 files modified
breezy/bzr/_dirstate_helpers_pyx.pyx (+6/-4)
breezy/bzr/dirstate.py (+57/-52)
breezy/bzr/inventorytree.py (+10/-8)
breezy/git/tree.py (+5/-4)
breezy/tree.py (+55/-14)
To merge this branch: bzr merge lp:~jelmer/brz/objects
Reviewer Review Type Date Requested Status
Martin Packman Approve
Review via email: mp+368856@code.launchpad.net

Commit message

Add a TreeChange object that can serve as alternative to a tuple returned by Tree.iter_changes.

Description of the change

Add a TreeChange object that can serve as alternative to a tuple returned by Tree.iter_changes.

This allows addition of extra fields in the future, and not relying on indexing
but attribute names when accessing iter_changes results.

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

Looks sensible, see one inline comment about slice still.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'breezy/bzr/_dirstate_helpers_pyx.pyx'
2--- breezy/bzr/_dirstate_helpers_pyx.pyx 2019-01-27 18:53:46 +0000
3+++ breezy/bzr/_dirstate_helpers_pyx.pyx 2019-06-15 12:02:54 +0000
4@@ -31,6 +31,7 @@
5 from .. import cache_utf8, errors, osutils
6 from .dirstate import DirState, DirstateCorrupt
7 from ..osutils import parent_directories, pathjoin, splitpath, is_inside_any, is_inside
8+from ..tree import TreeChange
9
10
11 # This is the Windows equivalent of ENOTDIR
12@@ -1293,7 +1294,7 @@
13 else:
14 path_u = self.utf8_decode(path)[0]
15 source_kind = _minikind_to_kind(source_minikind)
16- return (entry[0][2],
17+ return TreeChange(entry[0][2],
18 (old_path_u, path_u),
19 content_change,
20 (True, True),
21@@ -1326,7 +1327,7 @@
22 and S_IXUSR & path_info[3].st_mode)
23 else:
24 target_exec = target_details[3]
25- return (entry[0][2],
26+ return TreeChange(entry[0][2],
27 (None, self.utf8_decode(path)[0]),
28 True,
29 (False, True),
30@@ -1336,7 +1337,7 @@
31 (None, target_exec)), True
32 else:
33 # Its a missing file, report it as such.
34- return (entry[0][2],
35+ return TreeChange(entry[0][2],
36 (None, self.utf8_decode(path)[0]),
37 False,
38 (False, True),
39@@ -1354,7 +1355,8 @@
40 parent_id = self.state._get_entry(self.source_index, path_utf8=entry[0][0])[0][2]
41 if parent_id == entry[0][2]:
42 parent_id = None
43- return (entry[0][2],
44+ return TreeChange(
45+ entry[0][2],
46 (self.utf8_decode(old_path)[0], None),
47 True,
48 (True, False),
49
50=== modified file 'breezy/bzr/dirstate.py'
51--- breezy/bzr/dirstate.py 2019-03-04 00:16:27 +0000
52+++ breezy/bzr/dirstate.py 2019-06-15 12:02:54 +0000
53@@ -250,6 +250,7 @@
54 viewitems,
55 viewvalues,
56 )
57+from ..tree import TreeChange
58
59
60 # This is the Windows equivalent of ENOTDIR
61@@ -3768,15 +3769,16 @@
62 else:
63 path_u = self.utf8_decode(path)[0]
64 source_kind = DirState._minikind_to_kind[source_minikind]
65- return (entry[0][2],
66- (old_path_u, path_u),
67- content_change,
68- (True, True),
69- (source_parent_id, target_parent_id),
70- (self.utf8_decode(old_basename)[
71- 0], self.utf8_decode(entry[0][1])[0]),
72- (source_kind, target_kind),
73- (source_exec, target_exec)), changed
74+ return TreeChange(
75+ entry[0][2],
76+ (old_path_u, path_u),
77+ content_change,
78+ (True, True),
79+ (source_parent_id, target_parent_id),
80+ (self.utf8_decode(old_basename)[
81+ 0], self.utf8_decode(entry[0][1])[0]),
82+ (source_kind, target_kind),
83+ (source_exec, target_exec)), changed
84 elif source_minikind in b'a' and target_minikind in _fdlt:
85 # looks like a new file
86 path = pathjoin(entry[0][0], entry[0][1])
87@@ -3796,24 +3798,26 @@
88 and stat.S_IEXEC & path_info[3].st_mode)
89 else:
90 target_exec = target_details[3]
91- return (entry[0][2],
92- (None, self.utf8_decode(path)[0]),
93- True,
94- (False, True),
95- (None, parent_id),
96- (None, self.utf8_decode(entry[0][1])[0]),
97- (None, path_info[2]),
98- (None, target_exec)), True
99+ return TreeChange(
100+ entry[0][2],
101+ (None, self.utf8_decode(path)[0]),
102+ True,
103+ (False, True),
104+ (None, parent_id),
105+ (None, self.utf8_decode(entry[0][1])[0]),
106+ (None, path_info[2]),
107+ (None, target_exec)), True
108 else:
109 # Its a missing file, report it as such.
110- return (entry[0][2],
111- (None, self.utf8_decode(path)[0]),
112- False,
113- (False, True),
114- (None, parent_id),
115- (None, self.utf8_decode(entry[0][1])[0]),
116- (None, None),
117- (None, False)), True
118+ return TreeChange(
119+ entry[0][2],
120+ (None, self.utf8_decode(path)[0]),
121+ False,
122+ (False, True),
123+ (None, parent_id),
124+ (None, self.utf8_decode(entry[0][1])[0]),
125+ (None, None),
126+ (None, False)), True
127 elif source_minikind in _fdlt and target_minikind in b'a':
128 # unversioned, possibly, or possibly not deleted: we dont care.
129 # if its still on disk, *and* theres no other entry at this
130@@ -3825,14 +3829,15 @@
131 self.source_index, path_utf8=entry[0][0])[0][2]
132 if parent_id == entry[0][2]:
133 parent_id = None
134- return (entry[0][2],
135- (self.utf8_decode(old_path)[0], None),
136- True,
137- (True, False),
138- (parent_id, None),
139- (self.utf8_decode(entry[0][1])[0], None),
140- (DirState._minikind_to_kind[source_minikind], None),
141- (source_details[3], None)), True
142+ return TreeChange(
143+ entry[0][2],
144+ (self.utf8_decode(old_path)[0], None),
145+ True,
146+ (True, False),
147+ (parent_id, None),
148+ (self.utf8_decode(entry[0][1])[0], None),
149+ (DirState._minikind_to_kind[source_minikind], None),
150+ (source_details[3], None)), True
151 elif source_minikind in _fdlt and target_minikind in b'r':
152 # a rename; could be a true rename, or a rename inherited from
153 # a renamed parent. TODO: handle this efficiently. Its not
154@@ -3966,15 +3971,16 @@
155 new_executable = bool(
156 stat.S_ISREG(root_dir_info[3].st_mode)
157 and stat.S_IEXEC & root_dir_info[3].st_mode)
158- yield (None,
159- (None, current_root_unicode),
160- True,
161- (False, False),
162- (None, None),
163- (None, splitpath(current_root_unicode)[-1]),
164- (None, root_dir_info[2]),
165- (None, new_executable)
166- )
167+ yield TreeChange(
168+ None,
169+ (None, current_root_unicode),
170+ True,
171+ (False, False),
172+ (None, None),
173+ (None, splitpath(current_root_unicode)[-1]),
174+ (None, root_dir_info[2]),
175+ (None, new_executable)
176+ )
177 initial_key = (current_root, b'', b'')
178 block_index, _ = self.state._find_block_index_from_key(initial_key)
179 if block_index == 0:
180@@ -4048,16 +4054,15 @@
181 new_executable = bool(
182 stat.S_ISREG(current_path_info[3].st_mode)
183 and stat.S_IEXEC & current_path_info[3].st_mode)
184- yield (None,
185- (None, utf8_decode(
186- current_path_info[0])[0]),
187- True,
188- (False, False),
189- (None, None),
190- (None, utf8_decode(
191- current_path_info[1])[0]),
192- (None, current_path_info[2]),
193- (None, new_executable))
194+ yield TreeChange(
195+ None,
196+ (None, utf8_decode(current_path_info[0])[0]),
197+ True,
198+ (False, False),
199+ (None, None),
200+ (None, utf8_decode(current_path_info[1])[0]),
201+ (None, current_path_info[2]),
202+ (None, new_executable))
203 # dont descend into this unversioned path if it is
204 # a dir
205 if current_path_info[2] in ('directory',
206
207=== modified file 'breezy/bzr/inventorytree.py'
208--- breezy/bzr/inventorytree.py 2019-03-04 00:16:27 +0000
209+++ breezy/bzr/inventorytree.py 2019-06-15 12:02:54 +0000
210@@ -52,6 +52,7 @@
211 FileTimestampUnavailable,
212 InterTree,
213 Tree,
214+ TreeChange,
215 )
216
217
218@@ -920,14 +921,15 @@
219 entry.file_id not in specific_file_ids):
220 continue
221 if entry.file_id not in changed_file_ids:
222- yield (entry.file_id,
223- (relpath, relpath), # Not renamed
224- False, # Not modified
225- (True, True), # Still versioned
226- (entry.parent_id, entry.parent_id),
227- (entry.name, entry.name),
228- (entry.kind, entry.kind),
229- (entry.executable, entry.executable))
230+ yield TreeChange(
231+ entry.file_id,
232+ (relpath, relpath), # Not renamed
233+ False, # Not modified
234+ (True, True), # Still versioned
235+ (entry.parent_id, entry.parent_id),
236+ (entry.name, entry.name),
237+ (entry.kind, entry.kind),
238+ (entry.executable, entry.executable))
239
240
241 InterTree.register_optimiser(InterCHKRevisionTree)
242
243=== modified file 'breezy/git/tree.py'
244--- breezy/git/tree.py 2019-06-03 03:10:29 +0000
245+++ breezy/git/tree.py 2019-06-15 12:02:54 +0000
246@@ -828,10 +828,11 @@
247 oldkind == 'directory' and newkind == 'directory' and
248 oldpath_decoded == newpath_decoded):
249 continue
250- yield (fileid, (oldpath_decoded, newpath_decoded), (oldsha != newsha),
251- (oldversioned, newversioned),
252- (oldparent, newparent), (oldname, newname),
253- (oldkind, newkind), (oldexe, newexe))
254+ yield _mod_tree.TreeChange(
255+ fileid, (oldpath_decoded, newpath_decoded), (oldsha != newsha),
256+ (oldversioned, newversioned),
257+ (oldparent, newparent), (oldname, newname),
258+ (oldkind, newkind), (oldexe, newexe))
259
260
261 class InterGitTrees(_mod_tree.InterTree):
262
263=== modified file 'breezy/tree.py'
264--- breezy/tree.py 2019-06-04 00:08:59 +0000
265+++ breezy/tree.py 2019-06-15 12:02:54 +0000
266@@ -112,6 +112,43 @@
267 return '+'
268
269
270+class TreeChange(object):
271+ """Describes the changes between the same item in two different trees."""
272+
273+ __slots__ = ['file_id', 'path', 'changed_content', 'versioned', 'parent_id',
274+ 'name', 'kind', 'executable']
275+
276+ def __init__(self, file_id, path, changed_content, versioned, parent_id,
277+ name, kind, executable):
278+ self.file_id = file_id
279+ self.path = path
280+ self.changed_content = changed_content
281+ self.versioned = versioned
282+ self.parent_id = parent_id
283+ self.name = name
284+ self.kind = kind
285+ self.executable = executable
286+
287+ def __len__(self):
288+ return len(self.__slots__)
289+
290+ def __tuple__(self):
291+ return (self.file_id, self.path, self.changed_content, self.versioned,
292+ self.parent_id, self.name, self.kind, self.executable)
293+
294+ def __eq__(self, other):
295+ if isinstance(other, TreeChange):
296+ return tuple(self) == tuple(other)
297+ if isinstance(other, tuple):
298+ return tuple(self) == other
299+ return False
300+
301+ def __getitem__(self, i):
302+ if isinstance(i, slice):
303+ return tuple(self).__getitem__(i)
304+ return getattr(self, self.__slots__[i])
305+
306+
307 class Tree(object):
308 """Abstract file tree.
309
310@@ -762,8 +799,9 @@
311 changes = True
312 else:
313 changes = False
314- return (file_id, (source_path, target_path), changed_content,
315- versioned, parent, name, kind, executable), changes
316+ return TreeChange(
317+ file_id, (source_path, target_path), changed_content,
318+ versioned, parent, name, kind, executable), changes
319
320 def compare(self, want_unchanged=False, specific_files=None,
321 extra_trees=None, require_versioned=False, include_root=False,
322@@ -882,11 +920,12 @@
323 target_kind, target_executable, target_stat = \
324 self.target._comparison_data(
325 fake_entry, unversioned_path[1])
326- yield (None, (None, unversioned_path[1]), True, (False, False),
327- (None, None),
328- (None, unversioned_path[0][-1]),
329- (None, target_kind),
330- (None, target_executable))
331+ yield TreeChange(
332+ None, (None, unversioned_path[1]), True, (False, False),
333+ (None, None),
334+ (None, unversioned_path[0][-1]),
335+ (None, target_kind),
336+ (None, target_executable))
337 source_path, source_entry = from_data.get(target_entry.file_id,
338 (None, None))
339 result, changes = self._changes_from_entries(source_entry,
340@@ -918,11 +957,12 @@
341 unversioned_path = all_unversioned.popleft()
342 to_kind, to_executable, to_stat = \
343 self.target._comparison_data(fake_entry, unversioned_path[1])
344- yield (None, (None, unversioned_path[1]), True, (False, False),
345- (None, None),
346- (None, unversioned_path[0][-1]),
347- (None, to_kind),
348- (None, to_executable))
349+ yield TreeChange(
350+ None, (None, unversioned_path[1]), True, (False, False),
351+ (None, None),
352+ (None, unversioned_path[0][-1]),
353+ (None, to_kind),
354+ (None, to_executable))
355 # Yield all remaining source paths
356 for path, from_entry in from_entries_by_dir:
357 file_id = from_entry.file_id
358@@ -943,8 +983,9 @@
359 changed_content = from_kind is not None
360 # the parent's path is necessarily known at this point.
361 changed_file_ids.append(file_id)
362- yield(file_id, (path, to_path), changed_content, versioned, parent,
363- name, kind, executable)
364+ yield TreeChange(
365+ file_id, (path, to_path), changed_content, versioned, parent,
366+ name, kind, executable)
367 changed_file_ids = set(changed_file_ids)
368 if specific_files is not None:
369 for result in self._handle_precise_ids(precise_file_ids,

Subscribers

People subscribed via source and target branches