Merge lp:~jelmer/brz/iter-revisions into lp:brz
- iter-revisions
- Merge into trunk
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/iter-revisions |
Merge into: | lp:brz |
Diff against target: |
328 lines (+87/-89) 11 files modified
breezy/annotate.py (+4/-4) breezy/bzr/groupcompress_repo.py (+1/-1) breezy/bzr/remote.py (+13/-23) breezy/bzr/vf_repository.py (+21/-36) breezy/check.py (+1/-1) breezy/plugins/stats/cmds.py (+2/-2) breezy/plugins/weave_fmt/repository.py (+0/-5) breezy/repository.py (+21/-3) breezy/status.py (+2/-14) breezy/tests/per_repository/test_repository.py (+19/-0) doc/en/release-notes/brz-3.0.txt (+3/-0) |
To merge this branch: | bzr merge lp:~jelmer/brz/iter-revisions |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Packman | Approve | ||
Review via email: mp+326118@code.launchpad.net |
Commit message
Add Repository.
Description of the change
Add Repository.
This functionality already existed, but was mostly private. It's like Repository.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'breezy/annotate.py' | |||
2 | --- breezy/annotate.py 2017-06-04 18:09:30 +0000 | |||
3 | +++ breezy/annotate.py 2017-06-22 22:20:42 +0000 | |||
4 | @@ -188,10 +188,10 @@ | |||
5 | 188 | revision_id_to_revno[CURRENT_REVISION] = ( | 188 | revision_id_to_revno[CURRENT_REVISION] = ( |
6 | 189 | "%d?" % (branch.revno() + 1),) | 189 | "%d?" % (branch.revno() + 1),) |
7 | 190 | revisions[CURRENT_REVISION] = current_rev | 190 | revisions[CURRENT_REVISION] = current_rev |
12 | 191 | revision_ids = [o for o in revision_ids if | 191 | revisions.update( |
13 | 192 | repository.has_revision(o)] | 192 | entry for entry in |
14 | 193 | revisions.update((r.revision_id, r) for r in | 193 | repository.iter_revisions(revision_ids) |
15 | 194 | repository.get_revisions(revision_ids)) | 194 | if entry[1] is not None) |
16 | 195 | for origin, text in annotations: | 195 | for origin, text in annotations: |
17 | 196 | text = text.rstrip('\r\n') | 196 | text = text.rstrip('\r\n') |
18 | 197 | if origin == last_origin: | 197 | if origin == last_origin: |
19 | 198 | 198 | ||
20 | === modified file 'breezy/bzr/groupcompress_repo.py' | |||
21 | --- breezy/bzr/groupcompress_repo.py 2017-06-22 00:21:13 +0000 | |||
22 | +++ breezy/bzr/groupcompress_repo.py 2017-06-22 22:20:42 +0000 | |||
23 | @@ -1136,7 +1136,7 @@ | |||
24 | 1136 | raise AssertionError() | 1136 | raise AssertionError() |
25 | 1137 | vf = self.revisions | 1137 | vf = self.revisions |
26 | 1138 | if revisions_iterator is None: | 1138 | if revisions_iterator is None: |
28 | 1139 | revisions_iterator = self._iter_revisions(self.all_revision_ids()) | 1139 | revisions_iterator = self.iter_revisions(self.all_revision_ids()) |
29 | 1140 | for revid, revision in revisions_iterator: | 1140 | for revid, revision in revisions_iterator: |
30 | 1141 | if revision is None: | 1141 | if revision is None: |
31 | 1142 | pass | 1142 | pass |
32 | 1143 | 1143 | ||
33 | === modified file 'breezy/bzr/remote.py' | |||
34 | --- breezy/bzr/remote.py 2017-06-22 00:23:56 +0000 | |||
35 | +++ breezy/bzr/remote.py 2017-06-22 22:20:42 +0000 | |||
36 | @@ -2658,39 +2658,29 @@ | |||
37 | 2658 | yield serializer.read_revision_from_string("".join(chunks)) | 2658 | yield serializer.read_revision_from_string("".join(chunks)) |
38 | 2659 | 2659 | ||
39 | 2660 | @needs_read_lock | 2660 | @needs_read_lock |
41 | 2661 | def get_revisions(self, revision_ids): | 2661 | def iter_revisions(self, revision_ids): |
42 | 2662 | for rev_id in revision_ids: | 2662 | for rev_id in revision_ids: |
43 | 2663 | if not rev_id or not isinstance(rev_id, bytes): | 2663 | if not rev_id or not isinstance(rev_id, bytes): |
44 | 2664 | raise errors.InvalidRevisionId( | 2664 | raise errors.InvalidRevisionId( |
45 | 2665 | revision_id=rev_id, branch=self) | 2665 | revision_id=rev_id, branch=self) |
46 | 2666 | try: | 2666 | try: |
47 | 2667 | missing = set(revision_ids) | 2667 | missing = set(revision_ids) |
48 | 2668 | revs = {} | ||
49 | 2669 | for rev in self._iter_revisions_rpc(revision_ids): | 2668 | for rev in self._iter_revisions_rpc(revision_ids): |
50 | 2670 | missing.remove(rev.revision_id) | 2669 | missing.remove(rev.revision_id) |
52 | 2671 | revs[rev.revision_id] = rev | 2670 | yield rev.revision_id, rev |
53 | 2671 | for fallback in self._fallback_repositories: | ||
54 | 2672 | if not missing: | ||
55 | 2673 | break | ||
56 | 2674 | for revid, rev in fallback.iter_revisions(missing): | ||
57 | 2675 | if rev is not None: | ||
58 | 2676 | yield revid, rev | ||
59 | 2677 | missing.remove(revid) | ||
60 | 2678 | for revid in missing: | ||
61 | 2679 | yield revid, None | ||
62 | 2672 | except errors.UnknownSmartMethod: | 2680 | except errors.UnknownSmartMethod: |
63 | 2673 | self._ensure_real() | 2681 | self._ensure_real() |
84 | 2674 | return self._real_repository.get_revisions(revision_ids) | 2682 | for entry in self._real_repository.iter_revisions(revision_ids): |
85 | 2675 | for fallback in self._fallback_repositories: | 2683 | yield entry |
66 | 2676 | if not missing: | ||
67 | 2677 | break | ||
68 | 2678 | for revid in list(missing): | ||
69 | 2679 | # XXX JRV 2011-11-20: It would be nice if there was a | ||
70 | 2680 | # public method on Repository that could be used to query | ||
71 | 2681 | # for revision objects *without* failing completely if one | ||
72 | 2682 | # was missing. There is VersionedFileRepository._iter_revisions, | ||
73 | 2683 | # but unfortunately that's private and not provided by | ||
74 | 2684 | # all repository implementations. | ||
75 | 2685 | try: | ||
76 | 2686 | revs[revid] = fallback.get_revision(revid) | ||
77 | 2687 | except errors.NoSuchRevision: | ||
78 | 2688 | pass | ||
79 | 2689 | else: | ||
80 | 2690 | missing.remove(revid) | ||
81 | 2691 | if missing: | ||
82 | 2692 | raise errors.NoSuchRevision(self, list(missing)[0]) | ||
83 | 2693 | return [revs[revid] for revid in revision_ids] | ||
86 | 2694 | 2684 | ||
87 | 2695 | def supports_rich_root(self): | 2685 | def supports_rich_root(self): |
88 | 2696 | return self._format.rich_root_data | 2686 | return self._format.rich_root_data |
89 | 2697 | 2687 | ||
90 | === modified file 'breezy/bzr/vf_repository.py' | |||
91 | --- breezy/bzr/vf_repository.py 2017-06-22 00:21:13 +0000 | |||
92 | +++ breezy/bzr/vf_repository.py 2017-06-22 22:20:42 +0000 | |||
93 | @@ -1102,28 +1102,9 @@ | |||
94 | 1102 | be used by reconcile, or reconcile-alike commands that are correcting | 1102 | be used by reconcile, or reconcile-alike commands that are correcting |
95 | 1103 | or testing the revision graph. | 1103 | or testing the revision graph. |
96 | 1104 | """ | 1104 | """ |
119 | 1105 | return self._get_revisions([revision_id])[0] | 1105 | return self.get_revisions([revision_id])[0] |
120 | 1106 | 1106 | ||
121 | 1107 | @needs_read_lock | 1107 | def iter_revisions(self, revision_ids): |
100 | 1108 | def get_revisions(self, revision_ids): | ||
101 | 1109 | """Get many revisions at once. | ||
102 | 1110 | |||
103 | 1111 | Repositories that need to check data on every revision read should | ||
104 | 1112 | subclass this method. | ||
105 | 1113 | """ | ||
106 | 1114 | return self._get_revisions(revision_ids) | ||
107 | 1115 | |||
108 | 1116 | @needs_read_lock | ||
109 | 1117 | def _get_revisions(self, revision_ids): | ||
110 | 1118 | """Core work logic to get many revisions without sanity checks.""" | ||
111 | 1119 | revs = {} | ||
112 | 1120 | for revid, rev in self._iter_revisions(revision_ids): | ||
113 | 1121 | if rev is None: | ||
114 | 1122 | raise errors.NoSuchRevision(self, revid) | ||
115 | 1123 | revs[revid] = rev | ||
116 | 1124 | return [revs[revid] for revid in revision_ids] | ||
117 | 1125 | |||
118 | 1126 | def _iter_revisions(self, revision_ids): | ||
122 | 1127 | """Iterate over revision objects. | 1108 | """Iterate over revision objects. |
123 | 1128 | 1109 | ||
124 | 1129 | :param revision_ids: An iterable of revisions to examine. None may be | 1110 | :param revision_ids: An iterable of revisions to examine. None may be |
125 | @@ -1133,19 +1114,23 @@ | |||
126 | 1133 | :return: An iterator of (revid, revision) tuples. Absent revisions ( | 1114 | :return: An iterator of (revid, revision) tuples. Absent revisions ( |
127 | 1134 | those asked for but not available) are returned as (revid, None). | 1115 | those asked for but not available) are returned as (revid, None). |
128 | 1135 | """ | 1116 | """ |
142 | 1136 | for rev_id in revision_ids: | 1117 | self.lock_read() |
143 | 1137 | if not rev_id or not isinstance(rev_id, bytes): | 1118 | try: |
144 | 1138 | raise errors.InvalidRevisionId(revision_id=rev_id, branch=self) | 1119 | for rev_id in revision_ids: |
145 | 1139 | keys = [(key,) for key in revision_ids] | 1120 | if not rev_id or not isinstance(rev_id, bytes): |
146 | 1140 | stream = self.revisions.get_record_stream(keys, 'unordered', True) | 1121 | raise errors.InvalidRevisionId(revision_id=rev_id, branch=self) |
147 | 1141 | for record in stream: | 1122 | keys = [(key,) for key in revision_ids] |
148 | 1142 | revid = record.key[0] | 1123 | stream = self.revisions.get_record_stream(keys, 'unordered', True) |
149 | 1143 | if record.storage_kind == 'absent': | 1124 | for record in stream: |
150 | 1144 | yield (revid, None) | 1125 | revid = record.key[0] |
151 | 1145 | else: | 1126 | if record.storage_kind == 'absent': |
152 | 1146 | text = record.get_bytes_as('fulltext') | 1127 | yield (revid, None) |
153 | 1147 | rev = self._serializer.read_revision_from_string(text) | 1128 | else: |
154 | 1148 | yield (revid, rev) | 1129 | text = record.get_bytes_as('fulltext') |
155 | 1130 | rev = self._serializer.read_revision_from_string(text) | ||
156 | 1131 | yield (revid, rev) | ||
157 | 1132 | finally: | ||
158 | 1133 | self.unlock() | ||
159 | 1149 | 1134 | ||
160 | 1150 | @needs_write_lock | 1135 | @needs_write_lock |
161 | 1151 | def add_signature_text(self, revision_id, signature): | 1136 | def add_signature_text(self, revision_id, signature): |
162 | @@ -1677,7 +1662,7 @@ | |||
163 | 1677 | raise AssertionError() | 1662 | raise AssertionError() |
164 | 1678 | vf = self.revisions | 1663 | vf = self.revisions |
165 | 1679 | if revisions_iterator is None: | 1664 | if revisions_iterator is None: |
167 | 1680 | revisions_iterator = self._iter_revisions(self.all_revision_ids()) | 1665 | revisions_iterator = self.iter_revisions(self.all_revision_ids()) |
168 | 1681 | for revid, revision in revisions_iterator: | 1666 | for revid, revision in revisions_iterator: |
169 | 1682 | if revision is None: | 1667 | if revision is None: |
170 | 1683 | pass | 1668 | pass |
171 | 1684 | 1669 | ||
172 | === modified file 'breezy/check.py' | |||
173 | --- breezy/check.py 2017-06-22 00:21:13 +0000 | |||
174 | +++ breezy/check.py 2017-06-22 22:20:42 +0000 | |||
175 | @@ -181,7 +181,7 @@ | |||
176 | 181 | 181 | ||
177 | 182 | def check_revisions(self): | 182 | def check_revisions(self): |
178 | 183 | """Scan revisions, checking data directly available as we go.""" | 183 | """Scan revisions, checking data directly available as we go.""" |
180 | 184 | revision_iterator = self.repository._iter_revisions( | 184 | revision_iterator = self.repository.iter_revisions( |
181 | 185 | self.repository.all_revision_ids()) | 185 | self.repository.all_revision_ids()) |
182 | 186 | revision_iterator = self._check_revisions(revision_iterator) | 186 | revision_iterator = self._check_revisions(revision_iterator) |
183 | 187 | # We read the all revisions here: | 187 | # We read the all revisions here: |
184 | 188 | 188 | ||
185 | === modified file 'breezy/plugins/stats/cmds.py' | |||
186 | --- breezy/plugins/stats/cmds.py 2017-06-05 21:24:34 +0000 | |||
187 | +++ breezy/plugins/stats/cmds.py 2017-06-22 22:20:42 +0000 | |||
188 | @@ -148,8 +148,8 @@ | |||
189 | 148 | pb = ui.ui_factory.nested_progress_bar() | 148 | pb = ui.ui_factory.nested_progress_bar() |
190 | 149 | try: | 149 | try: |
191 | 150 | trace.note('getting revisions') | 150 | trace.note('getting revisions') |
194 | 151 | revisions = a_repo.get_revisions(revids) | 151 | revisions = a_repo.iter_revisions(revids) |
195 | 152 | for count, rev in enumerate(revisions): | 152 | for count, (revid, rev) in enumerate(revisions): |
196 | 153 | pb.update('checking', count, len(revids)) | 153 | pb.update('checking', count, len(revids)) |
197 | 154 | for author in rev.get_apparent_authors(): | 154 | for author in rev.get_apparent_authors(): |
198 | 155 | # XXX: There is a chance sometimes with svn imports that the | 155 | # XXX: There is a chance sometimes with svn imports that the |
199 | 156 | 156 | ||
200 | === modified file 'breezy/plugins/weave_fmt/repository.py' | |||
201 | --- breezy/plugins/weave_fmt/repository.py 2017-06-14 23:29:06 +0000 | |||
202 | +++ breezy/plugins/weave_fmt/repository.py 2017-06-22 22:20:42 +0000 | |||
203 | @@ -166,11 +166,6 @@ | |||
204 | 166 | self.start_write_group() | 166 | self.start_write_group() |
205 | 167 | return result | 167 | return result |
206 | 168 | 168 | ||
207 | 169 | @needs_read_lock | ||
208 | 170 | def get_revisions(self, revision_ids): | ||
209 | 171 | revs = self._get_revisions(revision_ids) | ||
210 | 172 | return revs | ||
211 | 173 | |||
212 | 174 | def _inventory_add_lines(self, revision_id, parents, lines, | 169 | def _inventory_add_lines(self, revision_id, parents, lines, |
213 | 175 | check_content=True): | 170 | check_content=True): |
214 | 176 | """Store lines in inv_vf and return the sha1 of the inventory.""" | 171 | """Store lines in inv_vf and return the sha1 of the inventory.""" |
215 | 177 | 172 | ||
216 | === modified file 'breezy/repository.py' | |||
217 | --- breezy/repository.py 2017-06-20 01:35:59 +0000 | |||
218 | +++ breezy/repository.py 2017-06-22 22:20:42 +0000 | |||
219 | @@ -822,11 +822,29 @@ | |||
220 | 822 | 822 | ||
221 | 823 | def get_revisions(self, revision_ids): | 823 | def get_revisions(self, revision_ids): |
222 | 824 | """Get many revisions at once. | 824 | """Get many revisions at once. |
225 | 825 | 825 | ||
226 | 826 | Repositories that need to check data on every revision read should | 826 | Repositories that need to check data on every revision read should |
227 | 827 | subclass this method. | 827 | subclass this method. |
228 | 828 | """ | 828 | """ |
230 | 829 | raise NotImplementedError(self.get_revisions) | 829 | revs = {} |
231 | 830 | for revid, rev in self.iter_revisions(revision_ids): | ||
232 | 831 | if rev is None: | ||
233 | 832 | raise errors.NoSuchRevision(self, revid) | ||
234 | 833 | revs[revid] = rev | ||
235 | 834 | return [revs[revid] for revid in revision_ids] | ||
236 | 835 | |||
237 | 836 | def iter_revisions(self, revision_ids): | ||
238 | 837 | """Iterate over revision objects. | ||
239 | 838 | |||
240 | 839 | :param revision_ids: An iterable of revisions to examine. None may be | ||
241 | 840 | passed to request all revisions known to the repository. Note that | ||
242 | 841 | not all repositories can find unreferenced revisions; for those | ||
243 | 842 | repositories only referenced ones will be returned. | ||
244 | 843 | :return: An iterator of (revid, revision) tuples. Absent revisions ( | ||
245 | 844 | those asked for but not available) are returned as (revid, None). | ||
246 | 845 | N.B.: Revisions are not necessarily yielded in order. | ||
247 | 846 | """ | ||
248 | 847 | raise NotImplementedError(self.iter_revisions) | ||
249 | 830 | 848 | ||
250 | 831 | def get_deltas_for_revisions(self, revisions, specific_fileids=None): | 849 | def get_deltas_for_revisions(self, revisions, specific_fileids=None): |
251 | 832 | """Produce a generator of revision deltas. | 850 | """Produce a generator of revision deltas. |
252 | 833 | 851 | ||
253 | === modified file 'breezy/status.py' | |||
254 | --- breezy/status.py 2017-05-25 01:35:55 +0000 | |||
255 | +++ breezy/status.py 2017-06-22 22:20:42 +0000 | |||
256 | @@ -297,7 +297,7 @@ | |||
257 | 297 | log_formatter = log.LineLogFormatter(to_file) | 297 | log_formatter = log.LineLogFormatter(to_file) |
258 | 298 | for merge in pending: | 298 | for merge in pending: |
259 | 299 | try: | 299 | try: |
261 | 300 | rev = branch.repository.get_revisions([merge])[0] | 300 | rev = branch.repository.get_revision(merge) |
262 | 301 | except errors.NoSuchRevision: | 301 | except errors.NoSuchRevision: |
263 | 302 | # If we are missing a revision, just print out the revision id | 302 | # If we are missing a revision, just print out the revision id |
264 | 303 | to_file.write(first_prefix + '(ghost) ' + merge + '\n') | 303 | to_file.write(first_prefix + '(ghost) ' + merge + '\n') |
265 | @@ -316,19 +316,7 @@ | |||
266 | 316 | merge_extra.discard(_mod_revision.NULL_REVISION) | 316 | merge_extra.discard(_mod_revision.NULL_REVISION) |
267 | 317 | 317 | ||
268 | 318 | # Get a handle to all of the revisions we will need | 318 | # Get a handle to all of the revisions we will need |
282 | 319 | try: | 319 | revisions = dict(branch.repository.iter_revisions(merge_extra)) |
270 | 320 | revisions = dict((rev.revision_id, rev) for rev in | ||
271 | 321 | branch.repository.get_revisions(merge_extra)) | ||
272 | 322 | except errors.NoSuchRevision: | ||
273 | 323 | # One of the sub nodes is a ghost, check each one | ||
274 | 324 | revisions = {} | ||
275 | 325 | for revision_id in merge_extra: | ||
276 | 326 | try: | ||
277 | 327 | rev = branch.repository.get_revisions([revision_id])[0] | ||
278 | 328 | except errors.NoSuchRevision: | ||
279 | 329 | revisions[revision_id] = None | ||
280 | 330 | else: | ||
281 | 331 | revisions[revision_id] = rev | ||
283 | 332 | 320 | ||
284 | 333 | # Display the revisions brought in by this merge. | 321 | # Display the revisions brought in by this merge. |
285 | 334 | rev_id_iterator = _get_sorted_revisions(merge, merge_extra, | 322 | rev_id_iterator = _get_sorted_revisions(merge, merge_extra, |
286 | 335 | 323 | ||
287 | === modified file 'breezy/tests/per_repository/test_repository.py' | |||
288 | --- breezy/tests/per_repository/test_repository.py 2017-06-11 14:07:05 +0000 | |||
289 | +++ breezy/tests/per_repository/test_repository.py 2017-06-22 22:20:42 +0000 | |||
290 | @@ -424,6 +424,25 @@ | |||
291 | 424 | self.assertEqual(revision.revision_id, revision_id) | 424 | self.assertEqual(revision.revision_id, revision_id) |
292 | 425 | self.assertEqual(revision, repo.get_revision(revision_id)) | 425 | self.assertEqual(revision, repo.get_revision(revision_id)) |
293 | 426 | 426 | ||
294 | 427 | def test_iter_revisions(self): | ||
295 | 428 | tree = self.make_branch_and_tree('.') | ||
296 | 429 | tree.commit('initial empty commit', rev_id='a-rev', | ||
297 | 430 | allow_pointless=True) | ||
298 | 431 | tree.commit('second empty commit', rev_id='b-rev', | ||
299 | 432 | allow_pointless=True) | ||
300 | 433 | tree.commit('third empty commit', rev_id='c-rev', | ||
301 | 434 | allow_pointless=True) | ||
302 | 435 | repo = tree.branch.repository | ||
303 | 436 | revision_ids = ['a-rev', 'c-rev', 'b-rev', 'd-rev'] | ||
304 | 437 | revid_with_rev = repo.iter_revisions(revision_ids) | ||
305 | 438 | self.assertEqual( | ||
306 | 439 | set((revid, rev.revision_id if rev is not None else None) | ||
307 | 440 | for (revid, rev) in revid_with_rev), | ||
308 | 441 | {('a-rev', 'a-rev'), | ||
309 | 442 | ('b-rev', 'b-rev'), | ||
310 | 443 | ('c-rev', 'c-rev'), | ||
311 | 444 | ('d-rev', None)}) | ||
312 | 445 | |||
313 | 427 | def test_root_entry_has_revision(self): | 446 | def test_root_entry_has_revision(self): |
314 | 428 | tree = self.make_branch_and_tree('.') | 447 | tree = self.make_branch_and_tree('.') |
315 | 429 | tree.commit('message', rev_id='rev_id') | 448 | tree.commit('message', rev_id='rev_id') |
316 | 430 | 449 | ||
317 | === modified file 'doc/en/release-notes/brz-3.0.txt' | |||
318 | --- doc/en/release-notes/brz-3.0.txt 2017-06-22 00:21:13 +0000 | |||
319 | +++ doc/en/release-notes/brz-3.0.txt 2017-06-22 22:20:42 +0000 | |||
320 | @@ -151,6 +151,9 @@ | |||
321 | 151 | * ``Repository.get_revisions`` no longer accepts ``None`` as | 151 | * ``Repository.get_revisions`` no longer accepts ``None`` as |
322 | 152 | argument. (Jelmer Vernooij) | 152 | argument. (Jelmer Vernooij) |
323 | 153 | 153 | ||
324 | 154 | * A new ``Repository.iter_revisions`` method has been added. | ||
325 | 155 | (Jelmer Vernooij) | ||
326 | 156 | |||
327 | 154 | Internals | 157 | Internals |
328 | 155 | ********* | 158 | ********* |
329 | 156 | 159 |
I'm missing some of the subtleties here, but the changes look okay to me. We're currently forcing passed revision_ids to be lists everywhere, right? That could be loosened later maybe.