Merge lp:~jelmer/brz/get-delta-revisions-files into lp:brz/3.1
- get-delta-revisions-files
- Merge into 3.1
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/get-delta-revisions-files |
Merge into: | lp:brz/3.1 |
Diff against target: |
285 lines (+160/-19) 7 files modified
breezy/bzr/remote.py (+8/-6) breezy/bzr/tests/per_repository_vf/test_repository.py (+13/-2) breezy/git/tree.py (+8/-6) breezy/log.py (+1/-1) breezy/plugins/stats/cmds.py (+2/-2) breezy/repository.py (+38/-0) breezy/tests/per_repository/test_repository.py (+90/-2) |
To merge this branch: | bzr merge lp:~jelmer/brz/get-delta-revisions-files |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jelmer Vernooij | Approve | ||
Review via email: mp+386469@code.launchpad.net |
Commit message
Add Repository.
Description of the change
Add Repository.
To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'breezy/bzr/remote.py' | |||
2 | --- breezy/bzr/remote.py 2020-03-22 19:12:43 +0000 | |||
3 | +++ breezy/bzr/remote.py 2020-06-28 18:07:07 +0000 | |||
4 | @@ -2590,12 +2590,14 @@ | |||
5 | 2590 | # file-id based, so filtering before or afterwards is | 2590 | # file-id based, so filtering before or afterwards is |
6 | 2591 | # currently easier. | 2591 | # currently easier. |
7 | 2592 | if specific_fileids is None: | 2592 | if specific_fileids is None: |
10 | 2593 | trees = dict((t.get_revision_id(), t) for | 2593 | trees = { |
11 | 2594 | t in self.revision_trees(required_trees)) | 2594 | t.get_revision_id(): t |
12 | 2595 | for t in self.revision_trees(required_trees)} | ||
13 | 2595 | else: | 2596 | else: |
17 | 2596 | trees = dict((t.get_revision_id(), t) for | 2597 | trees = { |
18 | 2597 | t in self._filtered_revision_trees(required_trees, | 2598 | t.get_revision_id(): t |
19 | 2598 | specific_fileids)) | 2599 | for t in self._filtered_revision_trees( |
20 | 2600 | required_trees, specific_fileids)} | ||
21 | 2599 | 2601 | ||
22 | 2600 | # Calculate the deltas | 2602 | # Calculate the deltas |
23 | 2601 | for revision in revisions: | 2603 | for revision in revisions: |
24 | @@ -2608,7 +2610,7 @@ | |||
25 | 2608 | def get_revision_delta(self, revision_id): | 2610 | def get_revision_delta(self, revision_id): |
26 | 2609 | with self.lock_read(): | 2611 | with self.lock_read(): |
27 | 2610 | r = self.get_revision(revision_id) | 2612 | r = self.get_revision(revision_id) |
29 | 2611 | return list(self.get_deltas_for_revisions([r]))[0] | 2613 | return list(self.get_revision_deltas([r]))[0] |
30 | 2612 | 2614 | ||
31 | 2613 | def revision_trees(self, revision_ids): | 2615 | def revision_trees(self, revision_ids): |
32 | 2614 | with self.lock_read(): | 2616 | with self.lock_read(): |
33 | 2615 | 2617 | ||
34 | === modified file 'breezy/bzr/tests/per_repository_vf/test_repository.py' | |||
35 | --- breezy/bzr/tests/per_repository_vf/test_repository.py 2020-06-10 02:56:53 +0000 | |||
36 | +++ breezy/bzr/tests/per_repository_vf/test_repository.py 2020-06-28 18:07:07 +0000 | |||
37 | @@ -364,8 +364,19 @@ | |||
38 | 364 | revisions = [repository.get_revision(r) for r in | 364 | revisions = [repository.get_revision(r) for r in |
39 | 365 | [b'rev1', b'rev2', b'rev3', b'rev4']] | 365 | [b'rev1', b'rev2', b'rev3', b'rev4']] |
40 | 366 | deltas1 = list(repository.get_deltas_for_revisions(revisions)) | 366 | deltas1 = list(repository.get_deltas_for_revisions(revisions)) |
43 | 367 | deltas2 = [repository.get_revision_delta(r.revision_id) for r in | 367 | deltas2 = [repository.get_revision_delta(r.revision_id) |
44 | 368 | revisions] | 368 | for r in revisions] |
45 | 369 | self.assertEqual(deltas1, deltas2) | ||
46 | 370 | |||
47 | 371 | def test_get_revision_deltas(self): | ||
48 | 372 | repository = self.controldir.open_repository() | ||
49 | 373 | repository.lock_read() | ||
50 | 374 | self.addCleanup(repository.unlock) | ||
51 | 375 | revisions = [repository.get_revision(r) for r in | ||
52 | 376 | [b'rev1', b'rev2', b'rev3', b'rev4']] | ||
53 | 377 | deltas1 = list(repository.get_revision_deltas(revisions)) | ||
54 | 378 | deltas2 = [repository.get_revision_delta(r.revision_id) | ||
55 | 379 | for r in revisions] | ||
56 | 369 | self.assertEqual(deltas1, deltas2) | 380 | self.assertEqual(deltas1, deltas2) |
57 | 370 | 381 | ||
58 | 371 | def test_all_revision_ids(self): | 382 | def test_all_revision_ids(self): |
59 | 372 | 383 | ||
60 | === modified file 'breezy/git/tree.py' | |||
61 | --- breezy/git/tree.py 2020-06-27 14:48:19 +0000 | |||
62 | +++ breezy/git/tree.py 2020-06-28 18:07:07 +0000 | |||
63 | @@ -1029,10 +1029,11 @@ | |||
64 | 1029 | ret = {} | 1029 | ret = {} |
65 | 1030 | changes = self._iter_git_changes(specific_files=paths)[0] | 1030 | changes = self._iter_git_changes(specific_files=paths)[0] |
66 | 1031 | for (change_type, old, new) in changes: | 1031 | for (change_type, old, new) in changes: |
69 | 1032 | oldpath = old[0] | 1032 | if old[0] is None: |
70 | 1033 | newpath = new[0] | 1033 | continue |
71 | 1034 | oldpath = decode_git_path(old[0]) | ||
72 | 1034 | if oldpath in paths: | 1035 | if oldpath in paths: |
74 | 1035 | ret[oldpath] = newpath | 1036 | ret[oldpath] = decode_git_path(new[0]) if new[0] else None |
75 | 1036 | for path in paths: | 1037 | for path in paths: |
76 | 1037 | if path not in ret: | 1038 | if path not in ret: |
77 | 1038 | if self.source.has_filename(path): | 1039 | if self.source.has_filename(path): |
78 | @@ -1049,10 +1050,11 @@ | |||
79 | 1049 | ret = {} | 1050 | ret = {} |
80 | 1050 | changes = self._iter_git_changes(specific_files=paths)[0] | 1051 | changes = self._iter_git_changes(specific_files=paths)[0] |
81 | 1051 | for (change_type, old, new) in changes: | 1052 | for (change_type, old, new) in changes: |
84 | 1052 | oldpath = old[0] | 1053 | if new[0] is None: |
85 | 1053 | newpath = new[0] | 1054 | continue |
86 | 1055 | newpath = decode_git_path(new[0]) | ||
87 | 1054 | if newpath in paths: | 1056 | if newpath in paths: |
89 | 1055 | ret[newpath] = oldpath | 1057 | ret[newpath] = decode_git_path(old[0]) if old[0] else None |
90 | 1056 | for path in paths: | 1058 | for path in paths: |
91 | 1057 | if path not in ret: | 1059 | if path not in ret: |
92 | 1058 | if self.target.has_filename(path): | 1060 | if self.target.has_filename(path): |
93 | 1059 | 1061 | ||
94 | === modified file 'breezy/log.py' | |||
95 | --- breezy/log.py 2020-06-21 02:15:25 +0000 | |||
96 | +++ breezy/log.py 2020-06-28 18:07:07 +0000 | |||
97 | @@ -982,7 +982,7 @@ | |||
98 | 982 | revisions = [rev[1] for rev in revs] | 982 | revisions = [rev[1] for rev in revs] |
99 | 983 | new_revs = [] | 983 | new_revs = [] |
100 | 984 | if delta_type == 'full' and not check_fileids: | 984 | if delta_type == 'full' and not check_fileids: |
102 | 985 | deltas = repository.get_deltas_for_revisions(revisions) | 985 | deltas = repository.get_revision_deltas(revisions) |
103 | 986 | for rev, delta in zip(revs, deltas): | 986 | for rev, delta in zip(revs, deltas): |
104 | 987 | new_revs.append((rev[0], rev[1], delta)) | 987 | new_revs.append((rev[0], rev[1], delta)) |
105 | 988 | else: | 988 | else: |
106 | 989 | 989 | ||
107 | === modified file 'breezy/plugins/stats/cmds.py' | |||
108 | --- breezy/plugins/stats/cmds.py 2019-12-23 00:34:25 +0000 | |||
109 | +++ breezy/plugins/stats/cmds.py 2020-06-28 18:07:07 +0000 | |||
110 | @@ -315,7 +315,7 @@ | |||
111 | 315 | with ui.ui_factory.nested_progress_bar() as pb: | 315 | with ui.ui_factory.nested_progress_bar() as pb: |
112 | 316 | with repository.lock_read(): | 316 | with repository.lock_read(): |
113 | 317 | i = 0 | 317 | i = 0 |
115 | 318 | for delta in repository.get_deltas_for_revisions(revs): | 318 | for delta in repository.get_revision_deltas(revs): |
116 | 319 | pb.update("classifying commits", i, len(revs)) | 319 | pb.update("classifying commits", i, len(revs)) |
117 | 320 | for c in classify_delta(delta): | 320 | for c in classify_delta(delta): |
118 | 321 | if c not in ret: | 321 | if c not in ret: |
119 | @@ -364,7 +364,7 @@ | |||
120 | 364 | if ps is not None and r != NULL_REVISION] | 364 | if ps is not None and r != NULL_REVISION] |
121 | 365 | revs = repository.get_revisions(ancestry) | 365 | revs = repository.get_revisions(ancestry) |
122 | 366 | with ui.ui_factory.nested_progress_bar() as pb: | 366 | with ui.ui_factory.nested_progress_bar() as pb: |
124 | 367 | iterator = zip(revs, repository.get_deltas_for_revisions(revs)) | 367 | iterator = zip(revs, repository.get_revision_deltas(revs)) |
125 | 368 | for i, (rev, delta) in enumerate(iterator): | 368 | for i, (rev, delta) in enumerate(iterator): |
126 | 369 | pb.update("analysing revisions", i, len(revs)) | 369 | pb.update("analysing revisions", i, len(revs)) |
127 | 370 | # Don't count merges | 370 | # Don't count merges |
128 | 371 | 371 | ||
129 | === modified file 'breezy/repository.py' | |||
130 | --- breezy/repository.py 2020-01-20 00:03:54 +0000 | |||
131 | +++ breezy/repository.py 2020-06-28 18:07:07 +0000 | |||
132 | @@ -913,6 +913,44 @@ | |||
133 | 913 | r = self.get_revision(revision_id) | 913 | r = self.get_revision(revision_id) |
134 | 914 | return list(self.get_deltas_for_revisions([r]))[0] | 914 | return list(self.get_deltas_for_revisions([r]))[0] |
135 | 915 | 915 | ||
136 | 916 | def get_revision_deltas(self, revisions, specific_files=None): | ||
137 | 917 | """Produce a generator of revision deltas. | ||
138 | 918 | |||
139 | 919 | Note that the input is a sequence of REVISIONS, not revision ids. | ||
140 | 920 | Trees will be held in memory until the generator exits. | ||
141 | 921 | Each delta is relative to the revision's lefthand predecessor. | ||
142 | 922 | |||
143 | 923 | specific_files should exist in the first revision. | ||
144 | 924 | |||
145 | 925 | :param specific_files: if not None, the result is filtered | ||
146 | 926 | so that only those files, their parents and their | ||
147 | 927 | children are included. | ||
148 | 928 | """ | ||
149 | 929 | from .tree import InterTree | ||
150 | 930 | # Get the revision-ids of interest | ||
151 | 931 | required_trees = set() | ||
152 | 932 | for revision in revisions: | ||
153 | 933 | required_trees.add(revision.revision_id) | ||
154 | 934 | required_trees.update(revision.parent_ids[:1]) | ||
155 | 935 | |||
156 | 936 | trees = { | ||
157 | 937 | t.get_revision_id(): t | ||
158 | 938 | for t in self.revision_trees(required_trees)} | ||
159 | 939 | |||
160 | 940 | # Calculate the deltas | ||
161 | 941 | for revision in revisions: | ||
162 | 942 | if not revision.parent_ids: | ||
163 | 943 | old_tree = self.revision_tree(_mod_revision.NULL_REVISION) | ||
164 | 944 | else: | ||
165 | 945 | old_tree = trees[revision.parent_ids[0]] | ||
166 | 946 | intertree = InterTree.get(old_tree, trees[revision.revision_id]) | ||
167 | 947 | yield intertree.compare(specific_files=specific_files) | ||
168 | 948 | if specific_files is not None: | ||
169 | 949 | specific_files = [ | ||
170 | 950 | p for p in intertree.find_source_paths( | ||
171 | 951 | specific_files).values() | ||
172 | 952 | if p is not None] | ||
173 | 953 | |||
174 | 916 | def store_revision_signature(self, gpg_strategy, plaintext, revision_id): | 954 | def store_revision_signature(self, gpg_strategy, plaintext, revision_id): |
175 | 917 | raise NotImplementedError(self.store_revision_signature) | 955 | raise NotImplementedError(self.store_revision_signature) |
176 | 918 | 956 | ||
177 | 919 | 957 | ||
178 | === modified file 'breezy/tests/per_repository/test_repository.py' | |||
179 | --- breezy/tests/per_repository/test_repository.py 2019-09-21 16:12:01 +0000 | |||
180 | +++ breezy/tests/per_repository/test_repository.py 2020-06-28 18:07:07 +0000 | |||
181 | @@ -997,10 +997,10 @@ | |||
182 | 997 | self.assertEqual(repo.control_url, repo.control_transport.base) | 997 | self.assertEqual(repo.control_url, repo.control_transport.base) |
183 | 998 | 998 | ||
184 | 999 | 999 | ||
186 | 1000 | class TestDeltaRevisionFiltered(per_repository.TestCaseWithRepository): | 1000 | class TestDeltaRevisionFileIdFiltered(per_repository.TestCaseWithRepository): |
187 | 1001 | 1001 | ||
188 | 1002 | def setUp(self): | 1002 | def setUp(self): |
190 | 1003 | super(TestDeltaRevisionFiltered, self).setUp() | 1003 | super(TestDeltaRevisionFileIdFiltered, self).setUp() |
191 | 1004 | self.tree_a = self.make_branch_and_tree('a') | 1004 | self.tree_a = self.make_branch_and_tree('a') |
192 | 1005 | self.build_tree(['a/foo', 'a/bar/', 'a/bar/b1', 'a/bar/b2', 'a/baz']) | 1005 | self.build_tree(['a/foo', 'a/bar/', 'a/bar/b1', 'a/bar/b2', 'a/baz']) |
193 | 1006 | self.tree_a.add(['foo', 'bar', 'bar/b1', 'bar/b2', 'baz']) | 1006 | self.tree_a.add(['foo', 'bar', 'bar/b1', 'bar/b2', 'baz']) |
194 | @@ -1067,3 +1067,91 @@ | |||
195 | 1067 | self.assertEqual([ | 1067 | self.assertEqual([ |
196 | 1068 | ('bar/b3', 'file'), | 1068 | ('bar/b3', 'file'), |
197 | 1069 | ], [(c.path[1], c.kind[1]) for c in delta.added]) | 1069 | ], [(c.path[1], c.kind[1]) for c in delta.added]) |
198 | 1070 | |||
199 | 1071 | |||
200 | 1072 | class TestDeltaRevisionFilesFiltered(per_repository.TestCaseWithRepository): | ||
201 | 1073 | |||
202 | 1074 | def setUp(self): | ||
203 | 1075 | super(TestDeltaRevisionFilesFiltered, self).setUp() | ||
204 | 1076 | self.tree_a = self.make_branch_and_tree('a') | ||
205 | 1077 | self.build_tree( | ||
206 | 1078 | ['a/foo', 'a/bar/', 'a/bar/b1', 'a/bar/b2', 'a/baz', 'a/oldname']) | ||
207 | 1079 | self.tree_a.add(['foo', 'bar', 'bar/b1', 'bar/b2', 'baz', 'oldname']) | ||
208 | 1080 | self.rev1 = self.tree_a.commit('rev1') | ||
209 | 1081 | self.build_tree(['a/bar/b3']) | ||
210 | 1082 | self.tree_a.add('bar/b3') | ||
211 | 1083 | self.tree_a.rename_one('oldname', 'newname') | ||
212 | 1084 | self.rev2 = self.tree_a.commit('rev2') | ||
213 | 1085 | self.repository = self.tree_a.branch.repository | ||
214 | 1086 | self.addCleanup(self.repository.lock_read().unlock) | ||
215 | 1087 | |||
216 | 1088 | def test_multiple_files(self): | ||
217 | 1089 | # Test multiple files | ||
218 | 1090 | delta = list(self.repository.get_revision_deltas( | ||
219 | 1091 | [self.repository.get_revision(self.rev1)], specific_files=[ | ||
220 | 1092 | 'foo', 'baz']))[0] | ||
221 | 1093 | self.assertIsInstance(delta, _mod_delta.TreeDelta) | ||
222 | 1094 | self.assertEqual([ | ||
223 | 1095 | ('baz', 'file'), | ||
224 | 1096 | ('foo', 'file'), | ||
225 | 1097 | ], [(c.path[1], c.kind[1]) for c in delta.added]) | ||
226 | 1098 | |||
227 | 1099 | def test_directory(self): | ||
228 | 1100 | # Test a directory | ||
229 | 1101 | delta = list(self.repository.get_revision_deltas( | ||
230 | 1102 | [self.repository.get_revision(self.rev1)], | ||
231 | 1103 | specific_files=['bar']))[0] | ||
232 | 1104 | self.assertIsInstance(delta, _mod_delta.TreeDelta) | ||
233 | 1105 | self.assertEqual([ | ||
234 | 1106 | ('bar', 'directory'), | ||
235 | 1107 | ('bar/b1', 'file'), | ||
236 | 1108 | ('bar/b2', 'file'), | ||
237 | 1109 | ], [(c.path[1], c.kind[1]) for c in delta.added]) | ||
238 | 1110 | |||
239 | 1111 | def test_unrelated(self): | ||
240 | 1112 | # Try another revision | ||
241 | 1113 | delta = list(self.repository.get_revision_deltas( | ||
242 | 1114 | [self.repository.get_revision(self.rev2)], | ||
243 | 1115 | specific_files=['foo']))[0] | ||
244 | 1116 | self.assertIsInstance(delta, _mod_delta.TreeDelta) | ||
245 | 1117 | self.assertEqual([], delta.added) | ||
246 | 1118 | |||
247 | 1119 | def test_renamed(self): | ||
248 | 1120 | # Try another revision | ||
249 | 1121 | self.assertTrue( | ||
250 | 1122 | self.repository.revision_tree(self.rev2).has_filename('newname')) | ||
251 | 1123 | self.assertTrue( | ||
252 | 1124 | self.repository.revision_tree(self.rev1).has_filename('oldname')) | ||
253 | 1125 | revs = [ | ||
254 | 1126 | self.repository.get_revision(self.rev2), | ||
255 | 1127 | self.repository.get_revision(self.rev1)] | ||
256 | 1128 | delta2, delta1 = list(self.repository.get_revision_deltas( | ||
257 | 1129 | revs, specific_files=['newname'])) | ||
258 | 1130 | self.assertIsInstance(delta1, _mod_delta.TreeDelta) | ||
259 | 1131 | self.assertEqual([('oldname', 'newname')], [c.path for c in delta2.renamed]) | ||
260 | 1132 | self.assertIsInstance(delta2, _mod_delta.TreeDelta) | ||
261 | 1133 | self.assertEqual(['oldname'], [c.path[1] for c in delta1.added]) | ||
262 | 1134 | |||
263 | 1135 | def test_file_in_directory(self): | ||
264 | 1136 | # Test a file in a directory, both of which were added | ||
265 | 1137 | delta = list(self.repository.get_revision_deltas( | ||
266 | 1138 | [self.repository.get_revision(self.rev1)], | ||
267 | 1139 | specific_files=['bar/b2']))[0] | ||
268 | 1140 | self.assertIsInstance(delta, _mod_delta.TreeDelta) | ||
269 | 1141 | self.assertEqual([ | ||
270 | 1142 | ('bar', 'directory'), | ||
271 | 1143 | ('bar/b2', 'file'), | ||
272 | 1144 | ], [(c.path[1], c.kind[1]) for c in delta.added]) | ||
273 | 1145 | |||
274 | 1146 | def test_file_in_unchanged_directory(self): | ||
275 | 1147 | delta = list(self.repository.get_revision_deltas( | ||
276 | 1148 | [self.repository.get_revision(self.rev2)], | ||
277 | 1149 | specific_files=['bar/b3']))[0] | ||
278 | 1150 | self.assertIsInstance(delta, _mod_delta.TreeDelta) | ||
279 | 1151 | if [(c.path[1], c.kind[1]) for c in delta.added] == [ | ||
280 | 1152 | ('bar', 'directory'), ('bar/b3', 'file')]: | ||
281 | 1153 | self.knownFailure("bzr incorrectly reports 'bar' as added - " | ||
282 | 1154 | "bug 878217") | ||
283 | 1155 | self.assertEqual([ | ||
284 | 1156 | ('bar/b3', 'file'), | ||
285 | 1157 | ], [(c.path[1], c.kind[1]) for c in delta.added]) |