[MERGE] Repository.get_parent_map
Robert Collins
robertc at robertcollins.net
Mon Jan 14 22:48:18 GMT 2008
On Mon, 2008-01-14 at 17:30 +1100, Andrew Bennetts wrote:
> bb:tweak
>
> > === modified file 'bzrlib/remote.py'
> [...]
> > + def _get_parent_map(self, keys):
> > + """Helper for get_parent_map that performs the RPC."""
> > + keys = set(keys)
> > + if NULL_REVISION in keys:
> > + keys.discard(NULL_REVISION)
> > + found_parents = {NULL_REVISION:()}
> > + if not keys:
> > + return found_parents
> > + else:
> > + found_parents = {}
> > + path = self.bzrdir._path_for_remote_call(self._client)
> > + for key in keys:
> > + assert type(key) is str
> > + response = self._client.call_expecting_body(
> > + 'Repository.get_parent_map', path, *keys)
> > + if response[0][0] not in ['ok']:
> > + raise errors.UnexpectedSmartServerResponse(response[0])
> > + if response[0][0] == 'ok':
> > + coded = response[1].read_body_bytes()
> > + if coded == '':
> > + # no revisions found
> > + return {}
> > + lines = coded.split('\n')
> > + revision_graph = {}
> > + for line in lines:
> > + d = tuple(line.split())
> > + if len(d) > 1:
> > + revision_graph[d[0]] = d[1:]
> > + else:
> > + # No parents - so give the Graph result (NULL_REVISION,).
> > + revision_graph[d[0]] = (NULL_REVISION,)
> > + return revision_graph
>
> There's no good infrastructure for this at the moment, but you need to handle
> talking to older servers that won't recognise this verb.
Do we? I thought our policy was 'newest server everywhere'
> For now, the way to do it is:
>
> verb = 'Repository.get_parent_map'
> if (response == ('error', "Generic bzr smart protocol error: "
> "bad request '%s'" % verb) or
> response == ('error', "Generic bzr smart protocol error: "
> "bad request u'%s'" % verb)):
> response.cancel_read_body()
> # Fallback code goes here
>
> For that matter, I think you need a cancel_read_body() in the not-ok
> case too.
ok, I'll add something for this.
> > + size_so_far += 2 + len(revision_id) + sum(map(len, parents))
>
> The arithmetic here deserves a comment. Is the 2 there to compensate for the
> “ ” and “\n” delimiters? Is that right when there's more than one parent for a
> revision?
its close enough ;). Comment added.
> > + # get all the directly asked for parents, and then flesh out to
> > + # 64K or so.
> > + if first_loop_done and size_so_far > 65000:
> > + next_revs = set()
> > + break
> > + # don't query things we've already queried
> > + next_revs.difference_update(queried_revs)
> > + first_loop_done = True
>
> I think there's a minor bug here: if after the first time through the while loop
> size_so_far > 65000, then it will still add a little bit more to result, even
> though both first_loop_done and size_so_far are true. One fix for this would be
> to put:
>
> if size_so_far > 65000:
> break
>
> at the very end of the loop.
I'm not worried about any single revision being added. However I don't
want to add (say) 2MB of data in pathological cases of wide graphs.
> > === modified file 'bzrlib/tests/test_remote.py'
> [...]
> > +class TestRepositoryGetGraph(TestRemoteRepository):
> > +
> > + def test_get_graph(self):
> > + # get_graph returns a graph with get_parent_map as the repository.
> > + responses = []
> > + transport_path = 'quack'
> > + repo, client = self.setup_fake_client_and_repository(
> > + responses, transport_path)
> > + graph = repo.get_graph()
> > + self.assertEqual(graph._parents_provider, repo)
>
> The code in the test method doesn't seem to verify the statement in the comment
> describing the test.
Tweaked.
-Rob
--
GPG key available at: <http://www.robertcollins.net/keys.txt>.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20080115/b96cb3fe/attachment-0001.pgp
More information about the bazaar
mailing list