Merge lp:~jelmer/brz/iter-revisions 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/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
Reviewer Review Type Date Requested Status
Martin Packman Approve
Review via email: mp+326118@code.launchpad.net

Commit message

Add Repository.iter_revisions.

Description of the change

Add Repository.iter_revisions.

This functionality already existed, but was mostly private. It's like Repository.get_revisions, but it can cope with missing revisions and doesn't necessarily yield revisions in order.

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

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.

review: Approve

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 revision_id_to_revno[CURRENT_REVISION] = (
6 "%d?" % (branch.revno() + 1),)
7 revisions[CURRENT_REVISION] = current_rev
8- revision_ids = [o for o in revision_ids if
9- repository.has_revision(o)]
10- revisions.update((r.revision_id, r) for r in
11- repository.get_revisions(revision_ids))
12+ revisions.update(
13+ entry for entry in
14+ repository.iter_revisions(revision_ids)
15+ if entry[1] is not None)
16 for origin, text in annotations:
17 text = text.rstrip('\r\n')
18 if origin == last_origin:
19
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 raise AssertionError()
25 vf = self.revisions
26 if revisions_iterator is None:
27- revisions_iterator = self._iter_revisions(self.all_revision_ids())
28+ revisions_iterator = self.iter_revisions(self.all_revision_ids())
29 for revid, revision in revisions_iterator:
30 if revision is None:
31 pass
32
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 yield serializer.read_revision_from_string("".join(chunks))
38
39 @needs_read_lock
40- def get_revisions(self, revision_ids):
41+ def iter_revisions(self, revision_ids):
42 for rev_id in revision_ids:
43 if not rev_id or not isinstance(rev_id, bytes):
44 raise errors.InvalidRevisionId(
45 revision_id=rev_id, branch=self)
46 try:
47 missing = set(revision_ids)
48- revs = {}
49 for rev in self._iter_revisions_rpc(revision_ids):
50 missing.remove(rev.revision_id)
51- revs[rev.revision_id] = rev
52+ yield rev.revision_id, rev
53+ for fallback in self._fallback_repositories:
54+ if not missing:
55+ break
56+ for revid, rev in fallback.iter_revisions(missing):
57+ if rev is not None:
58+ yield revid, rev
59+ missing.remove(revid)
60+ for revid in missing:
61+ yield revid, None
62 except errors.UnknownSmartMethod:
63 self._ensure_real()
64- return self._real_repository.get_revisions(revision_ids)
65- for fallback in self._fallback_repositories:
66- if not missing:
67- break
68- for revid in list(missing):
69- # XXX JRV 2011-11-20: It would be nice if there was a
70- # public method on Repository that could be used to query
71- # for revision objects *without* failing completely if one
72- # was missing. There is VersionedFileRepository._iter_revisions,
73- # but unfortunately that's private and not provided by
74- # all repository implementations.
75- try:
76- revs[revid] = fallback.get_revision(revid)
77- except errors.NoSuchRevision:
78- pass
79- else:
80- missing.remove(revid)
81- if missing:
82- raise errors.NoSuchRevision(self, list(missing)[0])
83- return [revs[revid] for revid in revision_ids]
84+ for entry in self._real_repository.iter_revisions(revision_ids):
85+ yield entry
86
87 def supports_rich_root(self):
88 return self._format.rich_root_data
89
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 be used by reconcile, or reconcile-alike commands that are correcting
95 or testing the revision graph.
96 """
97- return self._get_revisions([revision_id])[0]
98-
99- @needs_read_lock
100- def get_revisions(self, revision_ids):
101- """Get many revisions at once.
102-
103- Repositories that need to check data on every revision read should
104- subclass this method.
105- """
106- return self._get_revisions(revision_ids)
107-
108- @needs_read_lock
109- def _get_revisions(self, revision_ids):
110- """Core work logic to get many revisions without sanity checks."""
111- revs = {}
112- for revid, rev in self._iter_revisions(revision_ids):
113- if rev is None:
114- raise errors.NoSuchRevision(self, revid)
115- revs[revid] = rev
116- return [revs[revid] for revid in revision_ids]
117-
118- def _iter_revisions(self, revision_ids):
119+ return self.get_revisions([revision_id])[0]
120+
121+ def iter_revisions(self, revision_ids):
122 """Iterate over revision objects.
123
124 :param revision_ids: An iterable of revisions to examine. None may be
125@@ -1133,19 +1114,23 @@
126 :return: An iterator of (revid, revision) tuples. Absent revisions (
127 those asked for but not available) are returned as (revid, None).
128 """
129- for rev_id in revision_ids:
130- if not rev_id or not isinstance(rev_id, bytes):
131- raise errors.InvalidRevisionId(revision_id=rev_id, branch=self)
132- keys = [(key,) for key in revision_ids]
133- stream = self.revisions.get_record_stream(keys, 'unordered', True)
134- for record in stream:
135- revid = record.key[0]
136- if record.storage_kind == 'absent':
137- yield (revid, None)
138- else:
139- text = record.get_bytes_as('fulltext')
140- rev = self._serializer.read_revision_from_string(text)
141- yield (revid, rev)
142+ self.lock_read()
143+ try:
144+ for rev_id in revision_ids:
145+ if not rev_id or not isinstance(rev_id, bytes):
146+ raise errors.InvalidRevisionId(revision_id=rev_id, branch=self)
147+ keys = [(key,) for key in revision_ids]
148+ stream = self.revisions.get_record_stream(keys, 'unordered', True)
149+ for record in stream:
150+ revid = record.key[0]
151+ if record.storage_kind == 'absent':
152+ yield (revid, None)
153+ else:
154+ text = record.get_bytes_as('fulltext')
155+ rev = self._serializer.read_revision_from_string(text)
156+ yield (revid, rev)
157+ finally:
158+ self.unlock()
159
160 @needs_write_lock
161 def add_signature_text(self, revision_id, signature):
162@@ -1677,7 +1662,7 @@
163 raise AssertionError()
164 vf = self.revisions
165 if revisions_iterator is None:
166- revisions_iterator = self._iter_revisions(self.all_revision_ids())
167+ revisions_iterator = self.iter_revisions(self.all_revision_ids())
168 for revid, revision in revisions_iterator:
169 if revision is None:
170 pass
171
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
177 def check_revisions(self):
178 """Scan revisions, checking data directly available as we go."""
179- revision_iterator = self.repository._iter_revisions(
180+ revision_iterator = self.repository.iter_revisions(
181 self.repository.all_revision_ids())
182 revision_iterator = self._check_revisions(revision_iterator)
183 # We read the all revisions here:
184
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 pb = ui.ui_factory.nested_progress_bar()
190 try:
191 trace.note('getting revisions')
192- revisions = a_repo.get_revisions(revids)
193- for count, rev in enumerate(revisions):
194+ revisions = a_repo.iter_revisions(revids)
195+ for count, (revid, rev) in enumerate(revisions):
196 pb.update('checking', count, len(revids))
197 for author in rev.get_apparent_authors():
198 # XXX: There is a chance sometimes with svn imports that the
199
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 self.start_write_group()
205 return result
206
207- @needs_read_lock
208- def get_revisions(self, revision_ids):
209- revs = self._get_revisions(revision_ids)
210- return revs
211-
212 def _inventory_add_lines(self, revision_id, parents, lines,
213 check_content=True):
214 """Store lines in inv_vf and return the sha1 of the inventory."""
215
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
221 def get_revisions(self, revision_ids):
222 """Get many revisions at once.
223-
224- Repositories that need to check data on every revision read should
225+
226+ Repositories that need to check data on every revision read should
227 subclass this method.
228 """
229- raise NotImplementedError(self.get_revisions)
230+ revs = {}
231+ for revid, rev in self.iter_revisions(revision_ids):
232+ if rev is None:
233+ raise errors.NoSuchRevision(self, revid)
234+ revs[revid] = rev
235+ return [revs[revid] for revid in revision_ids]
236+
237+ def iter_revisions(self, revision_ids):
238+ """Iterate over revision objects.
239+
240+ :param revision_ids: An iterable of revisions to examine. None may be
241+ passed to request all revisions known to the repository. Note that
242+ not all repositories can find unreferenced revisions; for those
243+ repositories only referenced ones will be returned.
244+ :return: An iterator of (revid, revision) tuples. Absent revisions (
245+ those asked for but not available) are returned as (revid, None).
246+ N.B.: Revisions are not necessarily yielded in order.
247+ """
248+ raise NotImplementedError(self.iter_revisions)
249
250 def get_deltas_for_revisions(self, revisions, specific_fileids=None):
251 """Produce a generator of revision deltas.
252
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 log_formatter = log.LineLogFormatter(to_file)
258 for merge in pending:
259 try:
260- rev = branch.repository.get_revisions([merge])[0]
261+ rev = branch.repository.get_revision(merge)
262 except errors.NoSuchRevision:
263 # If we are missing a revision, just print out the revision id
264 to_file.write(first_prefix + '(ghost) ' + merge + '\n')
265@@ -316,19 +316,7 @@
266 merge_extra.discard(_mod_revision.NULL_REVISION)
267
268 # Get a handle to all of the revisions we will need
269- try:
270- revisions = dict((rev.revision_id, rev) for rev in
271- branch.repository.get_revisions(merge_extra))
272- except errors.NoSuchRevision:
273- # One of the sub nodes is a ghost, check each one
274- revisions = {}
275- for revision_id in merge_extra:
276- try:
277- rev = branch.repository.get_revisions([revision_id])[0]
278- except errors.NoSuchRevision:
279- revisions[revision_id] = None
280- else:
281- revisions[revision_id] = rev
282+ revisions = dict(branch.repository.iter_revisions(merge_extra))
283
284 # Display the revisions brought in by this merge.
285 rev_id_iterator = _get_sorted_revisions(merge, merge_extra,
286
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 self.assertEqual(revision.revision_id, revision_id)
292 self.assertEqual(revision, repo.get_revision(revision_id))
293
294+ def test_iter_revisions(self):
295+ tree = self.make_branch_and_tree('.')
296+ tree.commit('initial empty commit', rev_id='a-rev',
297+ allow_pointless=True)
298+ tree.commit('second empty commit', rev_id='b-rev',
299+ allow_pointless=True)
300+ tree.commit('third empty commit', rev_id='c-rev',
301+ allow_pointless=True)
302+ repo = tree.branch.repository
303+ revision_ids = ['a-rev', 'c-rev', 'b-rev', 'd-rev']
304+ revid_with_rev = repo.iter_revisions(revision_ids)
305+ self.assertEqual(
306+ set((revid, rev.revision_id if rev is not None else None)
307+ for (revid, rev) in revid_with_rev),
308+ {('a-rev', 'a-rev'),
309+ ('b-rev', 'b-rev'),
310+ ('c-rev', 'c-rev'),
311+ ('d-rev', None)})
312+
313 def test_root_entry_has_revision(self):
314 tree = self.make_branch_and_tree('.')
315 tree.commit('message', rev_id='rev_id')
316
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 * ``Repository.get_revisions`` no longer accepts ``None`` as
322 argument. (Jelmer Vernooij)
323
324+ * A new ``Repository.iter_revisions`` method has been added.
325+ (Jelmer Vernooij)
326+
327 Internals
328 *********
329

Subscribers

People subscribed via source and target branches