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
=== modified file 'breezy/bzr/_dirstate_helpers_pyx.pyx'
--- breezy/bzr/_dirstate_helpers_pyx.pyx 2019-01-27 18:53:46 +0000
+++ breezy/bzr/_dirstate_helpers_pyx.pyx 2019-06-15 12:02:54 +0000
@@ -31,6 +31,7 @@
31from .. import cache_utf8, errors, osutils31from .. import cache_utf8, errors, osutils
32from .dirstate import DirState, DirstateCorrupt32from .dirstate import DirState, DirstateCorrupt
33from ..osutils import parent_directories, pathjoin, splitpath, is_inside_any, is_inside33from ..osutils import parent_directories, pathjoin, splitpath, is_inside_any, is_inside
34from ..tree import TreeChange
3435
3536
36# This is the Windows equivalent of ENOTDIR37# This is the Windows equivalent of ENOTDIR
@@ -1293,7 +1294,7 @@
1293 else:1294 else:
1294 path_u = self.utf8_decode(path)[0]1295 path_u = self.utf8_decode(path)[0]
1295 source_kind = _minikind_to_kind(source_minikind)1296 source_kind = _minikind_to_kind(source_minikind)
1296 return (entry[0][2],1297 return TreeChange(entry[0][2],
1297 (old_path_u, path_u),1298 (old_path_u, path_u),
1298 content_change,1299 content_change,
1299 (True, True),1300 (True, True),
@@ -1326,7 +1327,7 @@
1326 and S_IXUSR & path_info[3].st_mode)1327 and S_IXUSR & path_info[3].st_mode)
1327 else:1328 else:
1328 target_exec = target_details[3]1329 target_exec = target_details[3]
1329 return (entry[0][2],1330 return TreeChange(entry[0][2],
1330 (None, self.utf8_decode(path)[0]),1331 (None, self.utf8_decode(path)[0]),
1331 True,1332 True,
1332 (False, True),1333 (False, True),
@@ -1336,7 +1337,7 @@
1336 (None, target_exec)), True1337 (None, target_exec)), True
1337 else:1338 else:
1338 # Its a missing file, report it as such.1339 # Its a missing file, report it as such.
1339 return (entry[0][2],1340 return TreeChange(entry[0][2],
1340 (None, self.utf8_decode(path)[0]),1341 (None, self.utf8_decode(path)[0]),
1341 False,1342 False,
1342 (False, True),1343 (False, True),
@@ -1354,7 +1355,8 @@
1354 parent_id = self.state._get_entry(self.source_index, path_utf8=entry[0][0])[0][2]1355 parent_id = self.state._get_entry(self.source_index, path_utf8=entry[0][0])[0][2]
1355 if parent_id == entry[0][2]:1356 if parent_id == entry[0][2]:
1356 parent_id = None1357 parent_id = None
1357 return (entry[0][2],1358 return TreeChange(
1359 entry[0][2],
1358 (self.utf8_decode(old_path)[0], None),1360 (self.utf8_decode(old_path)[0], None),
1359 True,1361 True,
1360 (True, False),1362 (True, False),
13611363
=== modified file 'breezy/bzr/dirstate.py'
--- breezy/bzr/dirstate.py 2019-03-04 00:16:27 +0000
+++ breezy/bzr/dirstate.py 2019-06-15 12:02:54 +0000
@@ -250,6 +250,7 @@
250 viewitems,250 viewitems,
251 viewvalues,251 viewvalues,
252 )252 )
253from ..tree import TreeChange
253254
254255
255# This is the Windows equivalent of ENOTDIR256# This is the Windows equivalent of ENOTDIR
@@ -3768,15 +3769,16 @@
3768 else:3769 else:
3769 path_u = self.utf8_decode(path)[0]3770 path_u = self.utf8_decode(path)[0]
3770 source_kind = DirState._minikind_to_kind[source_minikind]3771 source_kind = DirState._minikind_to_kind[source_minikind]
3771 return (entry[0][2],3772 return TreeChange(
3772 (old_path_u, path_u),3773 entry[0][2],
3773 content_change,3774 (old_path_u, path_u),
3774 (True, True),3775 content_change,
3775 (source_parent_id, target_parent_id),3776 (True, True),
3776 (self.utf8_decode(old_basename)[3777 (source_parent_id, target_parent_id),
3777 0], self.utf8_decode(entry[0][1])[0]),3778 (self.utf8_decode(old_basename)[
3778 (source_kind, target_kind),3779 0], self.utf8_decode(entry[0][1])[0]),
3779 (source_exec, target_exec)), changed3780 (source_kind, target_kind),
3781 (source_exec, target_exec)), changed
3780 elif source_minikind in b'a' and target_minikind in _fdlt:3782 elif source_minikind in b'a' and target_minikind in _fdlt:
3781 # looks like a new file3783 # looks like a new file
3782 path = pathjoin(entry[0][0], entry[0][1])3784 path = pathjoin(entry[0][0], entry[0][1])
@@ -3796,24 +3798,26 @@
3796 and stat.S_IEXEC & path_info[3].st_mode)3798 and stat.S_IEXEC & path_info[3].st_mode)
3797 else:3799 else:
3798 target_exec = target_details[3]3800 target_exec = target_details[3]
3799 return (entry[0][2],3801 return TreeChange(
3800 (None, self.utf8_decode(path)[0]),3802 entry[0][2],
3801 True,3803 (None, self.utf8_decode(path)[0]),
3802 (False, True),3804 True,
3803 (None, parent_id),3805 (False, True),
3804 (None, self.utf8_decode(entry[0][1])[0]),3806 (None, parent_id),
3805 (None, path_info[2]),3807 (None, self.utf8_decode(entry[0][1])[0]),
3806 (None, target_exec)), True3808 (None, path_info[2]),
3809 (None, target_exec)), True
3807 else:3810 else:
3808 # Its a missing file, report it as such.3811 # Its a missing file, report it as such.
3809 return (entry[0][2],3812 return TreeChange(
3810 (None, self.utf8_decode(path)[0]),3813 entry[0][2],
3811 False,3814 (None, self.utf8_decode(path)[0]),
3812 (False, True),3815 False,
3813 (None, parent_id),3816 (False, True),
3814 (None, self.utf8_decode(entry[0][1])[0]),3817 (None, parent_id),
3815 (None, None),3818 (None, self.utf8_decode(entry[0][1])[0]),
3816 (None, False)), True3819 (None, None),
3820 (None, False)), True
3817 elif source_minikind in _fdlt and target_minikind in b'a':3821 elif source_minikind in _fdlt and target_minikind in b'a':
3818 # unversioned, possibly, or possibly not deleted: we dont care.3822 # unversioned, possibly, or possibly not deleted: we dont care.
3819 # if its still on disk, *and* theres no other entry at this3823 # if its still on disk, *and* theres no other entry at this
@@ -3825,14 +3829,15 @@
3825 self.source_index, path_utf8=entry[0][0])[0][2]3829 self.source_index, path_utf8=entry[0][0])[0][2]
3826 if parent_id == entry[0][2]:3830 if parent_id == entry[0][2]:
3827 parent_id = None3831 parent_id = None
3828 return (entry[0][2],3832 return TreeChange(
3829 (self.utf8_decode(old_path)[0], None),3833 entry[0][2],
3830 True,3834 (self.utf8_decode(old_path)[0], None),
3831 (True, False),3835 True,
3832 (parent_id, None),3836 (True, False),
3833 (self.utf8_decode(entry[0][1])[0], None),3837 (parent_id, None),
3834 (DirState._minikind_to_kind[source_minikind], None),3838 (self.utf8_decode(entry[0][1])[0], None),
3835 (source_details[3], None)), True3839 (DirState._minikind_to_kind[source_minikind], None),
3840 (source_details[3], None)), True
3836 elif source_minikind in _fdlt and target_minikind in b'r':3841 elif source_minikind in _fdlt and target_minikind in b'r':
3837 # a rename; could be a true rename, or a rename inherited from3842 # a rename; could be a true rename, or a rename inherited from
3838 # a renamed parent. TODO: handle this efficiently. Its not3843 # a renamed parent. TODO: handle this efficiently. Its not
@@ -3966,15 +3971,16 @@
3966 new_executable = bool(3971 new_executable = bool(
3967 stat.S_ISREG(root_dir_info[3].st_mode)3972 stat.S_ISREG(root_dir_info[3].st_mode)
3968 and stat.S_IEXEC & root_dir_info[3].st_mode)3973 and stat.S_IEXEC & root_dir_info[3].st_mode)
3969 yield (None,3974 yield TreeChange(
3970 (None, current_root_unicode),3975 None,
3971 True,3976 (None, current_root_unicode),
3972 (False, False),3977 True,
3973 (None, None),3978 (False, False),
3974 (None, splitpath(current_root_unicode)[-1]),3979 (None, None),
3975 (None, root_dir_info[2]),3980 (None, splitpath(current_root_unicode)[-1]),
3976 (None, new_executable)3981 (None, root_dir_info[2]),
3977 )3982 (None, new_executable)
3983 )
3978 initial_key = (current_root, b'', b'')3984 initial_key = (current_root, b'', b'')
3979 block_index, _ = self.state._find_block_index_from_key(initial_key)3985 block_index, _ = self.state._find_block_index_from_key(initial_key)
3980 if block_index == 0:3986 if block_index == 0:
@@ -4048,16 +4054,15 @@
4048 new_executable = bool(4054 new_executable = bool(
4049 stat.S_ISREG(current_path_info[3].st_mode)4055 stat.S_ISREG(current_path_info[3].st_mode)
4050 and stat.S_IEXEC & current_path_info[3].st_mode)4056 and stat.S_IEXEC & current_path_info[3].st_mode)
4051 yield (None,4057 yield TreeChange(
4052 (None, utf8_decode(4058 None,
4053 current_path_info[0])[0]),4059 (None, utf8_decode(current_path_info[0])[0]),
4054 True,4060 True,
4055 (False, False),4061 (False, False),
4056 (None, None),4062 (None, None),
4057 (None, utf8_decode(4063 (None, utf8_decode(current_path_info[1])[0]),
4058 current_path_info[1])[0]),4064 (None, current_path_info[2]),
4059 (None, current_path_info[2]),4065 (None, new_executable))
4060 (None, new_executable))
4061 # dont descend into this unversioned path if it is4066 # dont descend into this unversioned path if it is
4062 # a dir4067 # a dir
4063 if current_path_info[2] in ('directory',4068 if current_path_info[2] in ('directory',
40644069
=== modified file 'breezy/bzr/inventorytree.py'
--- breezy/bzr/inventorytree.py 2019-03-04 00:16:27 +0000
+++ breezy/bzr/inventorytree.py 2019-06-15 12:02:54 +0000
@@ -52,6 +52,7 @@
52 FileTimestampUnavailable,52 FileTimestampUnavailable,
53 InterTree,53 InterTree,
54 Tree,54 Tree,
55 TreeChange,
55 )56 )
5657
5758
@@ -920,14 +921,15 @@
920 entry.file_id not in specific_file_ids):921 entry.file_id not in specific_file_ids):
921 continue922 continue
922 if entry.file_id not in changed_file_ids:923 if entry.file_id not in changed_file_ids:
923 yield (entry.file_id,924 yield TreeChange(
924 (relpath, relpath), # Not renamed925 entry.file_id,
925 False, # Not modified926 (relpath, relpath), # Not renamed
926 (True, True), # Still versioned927 False, # Not modified
927 (entry.parent_id, entry.parent_id),928 (True, True), # Still versioned
928 (entry.name, entry.name),929 (entry.parent_id, entry.parent_id),
929 (entry.kind, entry.kind),930 (entry.name, entry.name),
930 (entry.executable, entry.executable))931 (entry.kind, entry.kind),
932 (entry.executable, entry.executable))
931933
932934
933InterTree.register_optimiser(InterCHKRevisionTree)935InterTree.register_optimiser(InterCHKRevisionTree)
934936
=== modified file 'breezy/git/tree.py'
--- breezy/git/tree.py 2019-06-03 03:10:29 +0000
+++ breezy/git/tree.py 2019-06-15 12:02:54 +0000
@@ -828,10 +828,11 @@
828 oldkind == 'directory' and newkind == 'directory' and828 oldkind == 'directory' and newkind == 'directory' and
829 oldpath_decoded == newpath_decoded):829 oldpath_decoded == newpath_decoded):
830 continue830 continue
831 yield (fileid, (oldpath_decoded, newpath_decoded), (oldsha != newsha),831 yield _mod_tree.TreeChange(
832 (oldversioned, newversioned),832 fileid, (oldpath_decoded, newpath_decoded), (oldsha != newsha),
833 (oldparent, newparent), (oldname, newname),833 (oldversioned, newversioned),
834 (oldkind, newkind), (oldexe, newexe))834 (oldparent, newparent), (oldname, newname),
835 (oldkind, newkind), (oldexe, newexe))
835836
836837
837class InterGitTrees(_mod_tree.InterTree):838class InterGitTrees(_mod_tree.InterTree):
838839
=== modified file 'breezy/tree.py'
--- breezy/tree.py 2019-06-04 00:08:59 +0000
+++ breezy/tree.py 2019-06-15 12:02:54 +0000
@@ -112,6 +112,43 @@
112 return '+'112 return '+'
113113
114114
115class TreeChange(object):
116 """Describes the changes between the same item in two different trees."""
117
118 __slots__ = ['file_id', 'path', 'changed_content', 'versioned', 'parent_id',
119 'name', 'kind', 'executable']
120
121 def __init__(self, file_id, path, changed_content, versioned, parent_id,
122 name, kind, executable):
123 self.file_id = file_id
124 self.path = path
125 self.changed_content = changed_content
126 self.versioned = versioned
127 self.parent_id = parent_id
128 self.name = name
129 self.kind = kind
130 self.executable = executable
131
132 def __len__(self):
133 return len(self.__slots__)
134
135 def __tuple__(self):
136 return (self.file_id, self.path, self.changed_content, self.versioned,
137 self.parent_id, self.name, self.kind, self.executable)
138
139 def __eq__(self, other):
140 if isinstance(other, TreeChange):
141 return tuple(self) == tuple(other)
142 if isinstance(other, tuple):
143 return tuple(self) == other
144 return False
145
146 def __getitem__(self, i):
147 if isinstance(i, slice):
148 return tuple(self).__getitem__(i)
149 return getattr(self, self.__slots__[i])
150
151
115class Tree(object):152class Tree(object):
116 """Abstract file tree.153 """Abstract file tree.
117154
@@ -762,8 +799,9 @@
762 changes = True799 changes = True
763 else:800 else:
764 changes = False801 changes = False
765 return (file_id, (source_path, target_path), changed_content,802 return TreeChange(
766 versioned, parent, name, kind, executable), changes803 file_id, (source_path, target_path), changed_content,
804 versioned, parent, name, kind, executable), changes
767805
768 def compare(self, want_unchanged=False, specific_files=None,806 def compare(self, want_unchanged=False, specific_files=None,
769 extra_trees=None, require_versioned=False, include_root=False,807 extra_trees=None, require_versioned=False, include_root=False,
@@ -882,11 +920,12 @@
882 target_kind, target_executable, target_stat = \920 target_kind, target_executable, target_stat = \
883 self.target._comparison_data(921 self.target._comparison_data(
884 fake_entry, unversioned_path[1])922 fake_entry, unversioned_path[1])
885 yield (None, (None, unversioned_path[1]), True, (False, False),923 yield TreeChange(
886 (None, None),924 None, (None, unversioned_path[1]), True, (False, False),
887 (None, unversioned_path[0][-1]),925 (None, None),
888 (None, target_kind),926 (None, unversioned_path[0][-1]),
889 (None, target_executable))927 (None, target_kind),
928 (None, target_executable))
890 source_path, source_entry = from_data.get(target_entry.file_id,929 source_path, source_entry = from_data.get(target_entry.file_id,
891 (None, None))930 (None, None))
892 result, changes = self._changes_from_entries(source_entry,931 result, changes = self._changes_from_entries(source_entry,
@@ -918,11 +957,12 @@
918 unversioned_path = all_unversioned.popleft()957 unversioned_path = all_unversioned.popleft()
919 to_kind, to_executable, to_stat = \958 to_kind, to_executable, to_stat = \
920 self.target._comparison_data(fake_entry, unversioned_path[1])959 self.target._comparison_data(fake_entry, unversioned_path[1])
921 yield (None, (None, unversioned_path[1]), True, (False, False),960 yield TreeChange(
922 (None, None),961 None, (None, unversioned_path[1]), True, (False, False),
923 (None, unversioned_path[0][-1]),962 (None, None),
924 (None, to_kind),963 (None, unversioned_path[0][-1]),
925 (None, to_executable))964 (None, to_kind),
965 (None, to_executable))
926 # Yield all remaining source paths966 # Yield all remaining source paths
927 for path, from_entry in from_entries_by_dir:967 for path, from_entry in from_entries_by_dir:
928 file_id = from_entry.file_id968 file_id = from_entry.file_id
@@ -943,8 +983,9 @@
943 changed_content = from_kind is not None983 changed_content = from_kind is not None
944 # the parent's path is necessarily known at this point.984 # the parent's path is necessarily known at this point.
945 changed_file_ids.append(file_id)985 changed_file_ids.append(file_id)
946 yield(file_id, (path, to_path), changed_content, versioned, parent,986 yield TreeChange(
947 name, kind, executable)987 file_id, (path, to_path), changed_content, versioned, parent,
988 name, kind, executable)
948 changed_file_ids = set(changed_file_ids)989 changed_file_ids = set(changed_file_ids)
949 if specific_files is not None:990 if specific_files is not None:
950 for result in self._handle_precise_ids(precise_file_ids,991 for result in self._handle_precise_ids(precise_file_ids,

Subscribers

People subscribed via source and target branches