Changes to 5 files · Browse files at b32d76dc0dc1 Showing diff from parent 9f16fe75dfb8 Diff from another changeset...
@@ -195,16 +195,20 @@ else:
yield path, mode, hexsha
- def find_missing_objects(self, haves, wants, progress=None):
+ def find_missing_objects(self, haves, wants, progress=None,
+ get_tagged=None):
"""Find the missing objects required for a set of revisions.
:param haves: Iterable over SHAs already in common.
:param wants: Iterable over SHAs of objects to fetch.
:param progress: Simple progress function that will be called with
updated progress strings.
+ :param get_tagged: Function that returns a dict of pointed-to sha -> tag
+ sha for including tags.
:return: Iterator over (sha, path) pairs.
"""
- return iter(MissingObjectFinder(self, haves, wants, progress).next, None)
+ finder = MissingObjectFinder(self, haves, wants, progress, get_tagged)
+ return iter(finder.next, None)
def find_common_revisions(self, graphwalker):
"""Find which revisions this store has in common using graphwalker.
@@ -637,9 +641,13 @@ :param haves: SHA1s of commits not to send (already present in target)
:param wants: SHA1s of commits to send
:param progress: Optional function to report progress to.
+ :param get_tagged: Function that returns a dict of pointed-to sha -> tag
+ sha for including tags.
+ :param tagged: dict of pointed-to sha -> tag sha for including tags
"""
- def __init__(self, object_store, haves, wants, progress=None):
+ def __init__(self, object_store, haves, wants, progress=None,
+ get_tagged=None):
self.sha_done = set(haves)
self.objects_to_send = set([(w, None, False) for w in wants if w not in haves])
self.object_store = object_store
@@ -647,6 +655,7 @@ self.progress = lambda x: None
else:
self.progress = progress
+ self._tagged = get_tagged and get_tagged() or {}
def add_todo(self, entries):
self.objects_to_send.update([e for e in entries if not e[0] in self.sha_done])
@@ -673,6 +682,8 @@ self.parse_tree(o)
elif isinstance(o, Tag):
self.parse_tag(o)
+ if sha in self._tagged:
+ self.add_todo([(self._tagged[sha], None, True)])
self.sha_done.add(sha)
self.progress("counting objects: %d\r" % len(self.sha_done))
return (sha, name)
|
@@ -648,7 +648,8 @@ progress))
return self.get_refs()
- def fetch_objects(self, determine_wants, graph_walker, progress):
+ def fetch_objects(self, determine_wants, graph_walker, progress,
+ get_tagged=None):
"""Fetch the missing objects required for a set of revisions.
:param determine_wants: Function that takes a dictionary with heads
@@ -658,12 +659,15 @@ that a revision is present.
:param progress: Simple progress function that will be called with
updated progress strings.
+ :param get_tagged: Function that returns a dict of pointed-to sha -> tag
+ sha for including tags.
:return: iterator over objects, with __len__ implemented
"""
wants = determine_wants(self.get_refs())
haves = self.object_store.find_common_revisions(graph_walker)
return self.object_store.iter_shas(
- self.object_store.find_missing_objects(haves, wants, progress))
+ self.object_store.find_missing_objects(haves, wants, progress,
+ get_tagged))
def get_graph_walker(self, heads=None):
if heads is None:
|
@@ -76,11 +76,14 @@ """
raise NotImplementedError
- def fetch_objects(self, determine_wants, graph_walker, progress):
+ def fetch_objects(self, determine_wants, graph_walker, progress,
+ get_tagged=None):
"""
Yield the objects required for a list of commits.
:param progress: is a callback to send progress messages to the client
+ :param get_tagged: Function that returns a dict of pointed-to sha -> tag
+ sha for including tags.
"""
raise NotImplementedError
@@ -91,6 +94,7 @@ if repo is None:
repo = Repo(tmpfile.mkdtemp())
self.repo = repo
+ self.refs = self.repo.refs
self.object_store = self.repo.object_store
self.fetch_objects = self.repo.fetch_objects
self.get_refs = self.repo.get_refs
@@ -204,7 +208,7 @@
def capabilities(self):
return ("multi_ack_detailed", "multi_ack", "side-band-64k", "thin-pack",
- "ofs-delta", "no-progress")
+ "ofs-delta", "no-progress", "include-tag")
def required_capabilities(self):
return ("side-band-64k", "thin-pack", "ofs-delta")
@@ -214,12 +218,42 @@ return
self.proto.write_sideband(2, message)
+ def get_tagged(self, refs=None, repo=None):
+ """Get a dict of peeled values of tags to their original tag shas.
+
+ :param refs: dict of refname -> sha of possible tags; defaults to all of
+ the backend's refs.
+ :param repo: optional Repo instance for getting peeled refs; defaults to
+ the backend's repo, if available
+ :return: dict of peeled_sha -> tag_sha, where tag_sha is the sha of a
+ tag whose peeled value is peeled_sha.
+ """
+ if not self.has_capability("include-tag"):
+ return {}
+ if refs is None:
+ refs = self.backend.get_refs()
+ if repo is None:
+ repo = getattr(self.backend, "repo", None)
+ if repo is None:
+ # Bail if we don't have a Repo available; this is ok since
+ # clients must be able to handle if the server doesn't include
+ # all relevant tags.
+ # TODO: either guarantee a Repo, or fix behavior when missing
+ return {}
+ tagged = {}
+ for name, sha in refs.iteritems():
+ peeled_sha = repo.get_peeled(name)
+ if peeled_sha != sha:
+ tagged[peeled_sha] = sha
+ return tagged
+
def handle(self):
write = lambda x: self.proto.write_sideband(1, x)
graph_walker = ProtocolGraphWalker(self)
objects_iter = self.backend.fetch_objects(
- graph_walker.determine_wants, graph_walker, self.progress)
+ graph_walker.determine_wants, graph_walker, self.progress,
+ get_tagged=self.get_tagged)
# Do they want any objects?
if len(objects_iter) == 0:
|
@@ -99,3 +99,6 @@ shutil.rmtree("foo")
os.makedirs(os.path.join("foo", "pack"))
self.store = DiskObjectStore("foo")
+
+
+# TODO: MissingObjectFinderTests
|
@@ -142,6 +142,31 @@ self._handler.progress('second message')
self.assertEqual(None, self._handler.proto.get_received_line(2))
+ def test_get_tagged(self):
+ refs = {
+ 'refs/tags/tag1': ONE,
+ 'refs/tags/tag2': TWO,
+ 'refs/heads/master': FOUR, # not a tag, no peeled value
+ }
+ peeled = {
+ 'refs/tags/tag1': '1234',
+ 'refs/tags/tag2': '5678',
+ }
+
+ class TestRepo(object):
+ def get_peeled(self, ref):
+ return peeled.get(ref, refs[ref])
+
+ caps = list(self._handler.required_capabilities()) + ['include-tag']
+ self._handler.set_client_capabilities(caps)
+ self.assertEquals({'1234': ONE, '5678': TWO},
+ self._handler.get_tagged(refs, repo=TestRepo()))
+
+ # non-include-tag case
+ caps = self._handler.required_capabilities()
+ self._handler.set_client_capabilities(caps)
+ self.assertEquals({}, self._handler.get_tagged(refs, repo=TestRepo()))
+
class TestCommit(object):
def __init__(self, sha, parents, commit_time):
|
Loading...