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
=== modified file 'breezy/annotate.py'
--- breezy/annotate.py 2017-06-04 18:09:30 +0000
+++ breezy/annotate.py 2017-06-22 22:20:42 +0000
@@ -188,10 +188,10 @@
188 revision_id_to_revno[CURRENT_REVISION] = (188 revision_id_to_revno[CURRENT_REVISION] = (
189 "%d?" % (branch.revno() + 1),)189 "%d?" % (branch.revno() + 1),)
190 revisions[CURRENT_REVISION] = current_rev190 revisions[CURRENT_REVISION] = current_rev
191 revision_ids = [o for o in revision_ids if191 revisions.update(
192 repository.has_revision(o)]192 entry for entry in
193 revisions.update((r.revision_id, r) for r in193 repository.iter_revisions(revision_ids)
194 repository.get_revisions(revision_ids))194 if entry[1] is not None)
195 for origin, text in annotations:195 for origin, text in annotations:
196 text = text.rstrip('\r\n')196 text = text.rstrip('\r\n')
197 if origin == last_origin:197 if origin == last_origin:
198198
=== modified file 'breezy/bzr/groupcompress_repo.py'
--- breezy/bzr/groupcompress_repo.py 2017-06-22 00:21:13 +0000
+++ breezy/bzr/groupcompress_repo.py 2017-06-22 22:20:42 +0000
@@ -1136,7 +1136,7 @@
1136 raise AssertionError()1136 raise AssertionError()
1137 vf = self.revisions1137 vf = self.revisions
1138 if revisions_iterator is None:1138 if revisions_iterator is None:
1139 revisions_iterator = self._iter_revisions(self.all_revision_ids())1139 revisions_iterator = self.iter_revisions(self.all_revision_ids())
1140 for revid, revision in revisions_iterator:1140 for revid, revision in revisions_iterator:
1141 if revision is None:1141 if revision is None:
1142 pass1142 pass
11431143
=== modified file 'breezy/bzr/remote.py'
--- breezy/bzr/remote.py 2017-06-22 00:23:56 +0000
+++ breezy/bzr/remote.py 2017-06-22 22:20:42 +0000
@@ -2658,39 +2658,29 @@
2658 yield serializer.read_revision_from_string("".join(chunks))2658 yield serializer.read_revision_from_string("".join(chunks))
26592659
2660 @needs_read_lock2660 @needs_read_lock
2661 def get_revisions(self, revision_ids):2661 def iter_revisions(self, revision_ids):
2662 for rev_id in revision_ids:2662 for rev_id in revision_ids:
2663 if not rev_id or not isinstance(rev_id, bytes):2663 if not rev_id or not isinstance(rev_id, bytes):
2664 raise errors.InvalidRevisionId(2664 raise errors.InvalidRevisionId(
2665 revision_id=rev_id, branch=self)2665 revision_id=rev_id, branch=self)
2666 try:2666 try:
2667 missing = set(revision_ids)2667 missing = set(revision_ids)
2668 revs = {}
2669 for rev in self._iter_revisions_rpc(revision_ids):2668 for rev in self._iter_revisions_rpc(revision_ids):
2670 missing.remove(rev.revision_id)2669 missing.remove(rev.revision_id)
2671 revs[rev.revision_id] = rev2670 yield rev.revision_id, rev
2671 for fallback in self._fallback_repositories:
2672 if not missing:
2673 break
2674 for revid, rev in fallback.iter_revisions(missing):
2675 if rev is not None:
2676 yield revid, rev
2677 missing.remove(revid)
2678 for revid in missing:
2679 yield revid, None
2672 except errors.UnknownSmartMethod:2680 except errors.UnknownSmartMethod:
2673 self._ensure_real()2681 self._ensure_real()
2674 return self._real_repository.get_revisions(revision_ids)2682 for entry in self._real_repository.iter_revisions(revision_ids):
2675 for fallback in self._fallback_repositories:2683 yield entry
2676 if not missing:
2677 break
2678 for revid in list(missing):
2679 # XXX JRV 2011-11-20: It would be nice if there was a
2680 # public method on Repository that could be used to query
2681 # for revision objects *without* failing completely if one
2682 # was missing. There is VersionedFileRepository._iter_revisions,
2683 # but unfortunately that's private and not provided by
2684 # all repository implementations.
2685 try:
2686 revs[revid] = fallback.get_revision(revid)
2687 except errors.NoSuchRevision:
2688 pass
2689 else:
2690 missing.remove(revid)
2691 if missing:
2692 raise errors.NoSuchRevision(self, list(missing)[0])
2693 return [revs[revid] for revid in revision_ids]
26942684
2695 def supports_rich_root(self):2685 def supports_rich_root(self):
2696 return self._format.rich_root_data2686 return self._format.rich_root_data
26972687
=== modified file 'breezy/bzr/vf_repository.py'
--- breezy/bzr/vf_repository.py 2017-06-22 00:21:13 +0000
+++ breezy/bzr/vf_repository.py 2017-06-22 22:20:42 +0000
@@ -1102,28 +1102,9 @@
1102 be used by reconcile, or reconcile-alike commands that are correcting1102 be used by reconcile, or reconcile-alike commands that are correcting
1103 or testing the revision graph.1103 or testing the revision graph.
1104 """1104 """
1105 return self._get_revisions([revision_id])[0]1105 return self.get_revisions([revision_id])[0]
11061106
1107 @needs_read_lock1107 def iter_revisions(self, revision_ids):
1108 def get_revisions(self, revision_ids):
1109 """Get many revisions at once.
1110
1111 Repositories that need to check data on every revision read should
1112 subclass this method.
1113 """
1114 return self._get_revisions(revision_ids)
1115
1116 @needs_read_lock
1117 def _get_revisions(self, revision_ids):
1118 """Core work logic to get many revisions without sanity checks."""
1119 revs = {}
1120 for revid, rev in self._iter_revisions(revision_ids):
1121 if rev is None:
1122 raise errors.NoSuchRevision(self, revid)
1123 revs[revid] = rev
1124 return [revs[revid] for revid in revision_ids]
1125
1126 def _iter_revisions(self, revision_ids):
1127 """Iterate over revision objects.1108 """Iterate over revision objects.
11281109
1129 :param revision_ids: An iterable of revisions to examine. None may be1110 :param revision_ids: An iterable of revisions to examine. None may be
@@ -1133,19 +1114,23 @@
1133 :return: An iterator of (revid, revision) tuples. Absent revisions (1114 :return: An iterator of (revid, revision) tuples. Absent revisions (
1134 those asked for but not available) are returned as (revid, None).1115 those asked for but not available) are returned as (revid, None).
1135 """1116 """
1136 for rev_id in revision_ids:1117 self.lock_read()
1137 if not rev_id or not isinstance(rev_id, bytes):1118 try:
1138 raise errors.InvalidRevisionId(revision_id=rev_id, branch=self)1119 for rev_id in revision_ids:
1139 keys = [(key,) for key in revision_ids]1120 if not rev_id or not isinstance(rev_id, bytes):
1140 stream = self.revisions.get_record_stream(keys, 'unordered', True)1121 raise errors.InvalidRevisionId(revision_id=rev_id, branch=self)
1141 for record in stream:1122 keys = [(key,) for key in revision_ids]
1142 revid = record.key[0]1123 stream = self.revisions.get_record_stream(keys, 'unordered', True)
1143 if record.storage_kind == 'absent':1124 for record in stream:
1144 yield (revid, None)1125 revid = record.key[0]
1145 else:1126 if record.storage_kind == 'absent':
1146 text = record.get_bytes_as('fulltext')1127 yield (revid, None)
1147 rev = self._serializer.read_revision_from_string(text)1128 else:
1148 yield (revid, rev)1129 text = record.get_bytes_as('fulltext')
1130 rev = self._serializer.read_revision_from_string(text)
1131 yield (revid, rev)
1132 finally:
1133 self.unlock()
11491134
1150 @needs_write_lock1135 @needs_write_lock
1151 def add_signature_text(self, revision_id, signature):1136 def add_signature_text(self, revision_id, signature):
@@ -1677,7 +1662,7 @@
1677 raise AssertionError()1662 raise AssertionError()
1678 vf = self.revisions1663 vf = self.revisions
1679 if revisions_iterator is None:1664 if revisions_iterator is None:
1680 revisions_iterator = self._iter_revisions(self.all_revision_ids())1665 revisions_iterator = self.iter_revisions(self.all_revision_ids())
1681 for revid, revision in revisions_iterator:1666 for revid, revision in revisions_iterator:
1682 if revision is None:1667 if revision is None:
1683 pass1668 pass
16841669
=== modified file 'breezy/check.py'
--- breezy/check.py 2017-06-22 00:21:13 +0000
+++ breezy/check.py 2017-06-22 22:20:42 +0000
@@ -181,7 +181,7 @@
181181
182 def check_revisions(self):182 def check_revisions(self):
183 """Scan revisions, checking data directly available as we go."""183 """Scan revisions, checking data directly available as we go."""
184 revision_iterator = self.repository._iter_revisions(184 revision_iterator = self.repository.iter_revisions(
185 self.repository.all_revision_ids())185 self.repository.all_revision_ids())
186 revision_iterator = self._check_revisions(revision_iterator)186 revision_iterator = self._check_revisions(revision_iterator)
187 # We read the all revisions here:187 # We read the all revisions here:
188188
=== modified file 'breezy/plugins/stats/cmds.py'
--- breezy/plugins/stats/cmds.py 2017-06-05 21:24:34 +0000
+++ breezy/plugins/stats/cmds.py 2017-06-22 22:20:42 +0000
@@ -148,8 +148,8 @@
148 pb = ui.ui_factory.nested_progress_bar()148 pb = ui.ui_factory.nested_progress_bar()
149 try:149 try:
150 trace.note('getting revisions')150 trace.note('getting revisions')
151 revisions = a_repo.get_revisions(revids)151 revisions = a_repo.iter_revisions(revids)
152 for count, rev in enumerate(revisions):152 for count, (revid, rev) in enumerate(revisions):
153 pb.update('checking', count, len(revids))153 pb.update('checking', count, len(revids))
154 for author in rev.get_apparent_authors():154 for author in rev.get_apparent_authors():
155 # XXX: There is a chance sometimes with svn imports that the155 # XXX: There is a chance sometimes with svn imports that the
156156
=== modified file 'breezy/plugins/weave_fmt/repository.py'
--- breezy/plugins/weave_fmt/repository.py 2017-06-14 23:29:06 +0000
+++ breezy/plugins/weave_fmt/repository.py 2017-06-22 22:20:42 +0000
@@ -166,11 +166,6 @@
166 self.start_write_group()166 self.start_write_group()
167 return result167 return result
168168
169 @needs_read_lock
170 def get_revisions(self, revision_ids):
171 revs = self._get_revisions(revision_ids)
172 return revs
173
174 def _inventory_add_lines(self, revision_id, parents, lines,169 def _inventory_add_lines(self, revision_id, parents, lines,
175 check_content=True):170 check_content=True):
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."""
177172
=== modified file 'breezy/repository.py'
--- breezy/repository.py 2017-06-20 01:35:59 +0000
+++ breezy/repository.py 2017-06-22 22:20:42 +0000
@@ -822,11 +822,29 @@
822822
823 def get_revisions(self, revision_ids):823 def get_revisions(self, revision_ids):
824 """Get many revisions at once.824 """Get many revisions at once.
825 825
826 Repositories that need to check data on every revision read should 826 Repositories that need to check data on every revision read should
827 subclass this method.827 subclass this method.
828 """828 """
829 raise NotImplementedError(self.get_revisions)829 revs = {}
830 for revid, rev in self.iter_revisions(revision_ids):
831 if rev is None:
832 raise errors.NoSuchRevision(self, revid)
833 revs[revid] = rev
834 return [revs[revid] for revid in revision_ids]
835
836 def iter_revisions(self, revision_ids):
837 """Iterate over revision objects.
838
839 :param revision_ids: An iterable of revisions to examine. None may be
840 passed to request all revisions known to the repository. Note that
841 not all repositories can find unreferenced revisions; for those
842 repositories only referenced ones will be returned.
843 :return: An iterator of (revid, revision) tuples. Absent revisions (
844 those asked for but not available) are returned as (revid, None).
845 N.B.: Revisions are not necessarily yielded in order.
846 """
847 raise NotImplementedError(self.iter_revisions)
830848
831 def get_deltas_for_revisions(self, revisions, specific_fileids=None):849 def get_deltas_for_revisions(self, revisions, specific_fileids=None):
832 """Produce a generator of revision deltas.850 """Produce a generator of revision deltas.
833851
=== modified file 'breezy/status.py'
--- breezy/status.py 2017-05-25 01:35:55 +0000
+++ breezy/status.py 2017-06-22 22:20:42 +0000
@@ -297,7 +297,7 @@
297 log_formatter = log.LineLogFormatter(to_file)297 log_formatter = log.LineLogFormatter(to_file)
298 for merge in pending:298 for merge in pending:
299 try:299 try:
300 rev = branch.repository.get_revisions([merge])[0]300 rev = branch.repository.get_revision(merge)
301 except errors.NoSuchRevision:301 except errors.NoSuchRevision:
302 # If we are missing a revision, just print out the revision id302 # If we are missing a revision, just print out the revision id
303 to_file.write(first_prefix + '(ghost) ' + merge + '\n')303 to_file.write(first_prefix + '(ghost) ' + merge + '\n')
@@ -316,19 +316,7 @@
316 merge_extra.discard(_mod_revision.NULL_REVISION)316 merge_extra.discard(_mod_revision.NULL_REVISION)
317317
318 # Get a handle to all of the revisions we will need318 # Get a handle to all of the revisions we will need
319 try:319 revisions = dict(branch.repository.iter_revisions(merge_extra))
320 revisions = dict((rev.revision_id, rev) for rev in
321 branch.repository.get_revisions(merge_extra))
322 except errors.NoSuchRevision:
323 # One of the sub nodes is a ghost, check each one
324 revisions = {}
325 for revision_id in merge_extra:
326 try:
327 rev = branch.repository.get_revisions([revision_id])[0]
328 except errors.NoSuchRevision:
329 revisions[revision_id] = None
330 else:
331 revisions[revision_id] = rev
332320
333 # Display the revisions brought in by this merge.321 # Display the revisions brought in by this merge.
334 rev_id_iterator = _get_sorted_revisions(merge, merge_extra,322 rev_id_iterator = _get_sorted_revisions(merge, merge_extra,
335323
=== modified file 'breezy/tests/per_repository/test_repository.py'
--- breezy/tests/per_repository/test_repository.py 2017-06-11 14:07:05 +0000
+++ breezy/tests/per_repository/test_repository.py 2017-06-22 22:20:42 +0000
@@ -424,6 +424,25 @@
424 self.assertEqual(revision.revision_id, revision_id)424 self.assertEqual(revision.revision_id, revision_id)
425 self.assertEqual(revision, repo.get_revision(revision_id))425 self.assertEqual(revision, repo.get_revision(revision_id))
426426
427 def test_iter_revisions(self):
428 tree = self.make_branch_and_tree('.')
429 tree.commit('initial empty commit', rev_id='a-rev',
430 allow_pointless=True)
431 tree.commit('second empty commit', rev_id='b-rev',
432 allow_pointless=True)
433 tree.commit('third empty commit', rev_id='c-rev',
434 allow_pointless=True)
435 repo = tree.branch.repository
436 revision_ids = ['a-rev', 'c-rev', 'b-rev', 'd-rev']
437 revid_with_rev = repo.iter_revisions(revision_ids)
438 self.assertEqual(
439 set((revid, rev.revision_id if rev is not None else None)
440 for (revid, rev) in revid_with_rev),
441 {('a-rev', 'a-rev'),
442 ('b-rev', 'b-rev'),
443 ('c-rev', 'c-rev'),
444 ('d-rev', None)})
445
427 def test_root_entry_has_revision(self):446 def test_root_entry_has_revision(self):
428 tree = self.make_branch_and_tree('.')447 tree = self.make_branch_and_tree('.')
429 tree.commit('message', rev_id='rev_id')448 tree.commit('message', rev_id='rev_id')
430449
=== modified file 'doc/en/release-notes/brz-3.0.txt'
--- doc/en/release-notes/brz-3.0.txt 2017-06-22 00:21:13 +0000
+++ doc/en/release-notes/brz-3.0.txt 2017-06-22 22:20:42 +0000
@@ -151,6 +151,9 @@
151 * ``Repository.get_revisions`` no longer accepts ``None`` as151 * ``Repository.get_revisions`` no longer accepts ``None`` as
152 argument. (Jelmer Vernooij)152 argument. (Jelmer Vernooij)
153153
154 * A new ``Repository.iter_revisions`` method has been added.
155 (Jelmer Vernooij)
156
154Internals157Internals
155*********158*********
156159

Subscribers

People subscribed via source and target branches