Track depth.
authorJelmer Vernooij <jelmer@jelmer.uk>
Sun, 4 Nov 2018 16:46:24 +0000 (16:46 +0000)
committerJelmer Vernooij <jelmer@jelmer.uk>
Sun, 4 Nov 2018 19:15:02 +0000 (19:15 +0000)
dulwich/client.py
dulwich/object_store.py
dulwich/repo.py
dulwich/tests/test_client.py

index b13427a6ac985f2d042087390fca1955af79100b..2c8b6aaf2b03d5d2ad27d9e2cd18ca5a586f94b3 100644 (file)
@@ -385,7 +385,7 @@ class GitClient(object):
         return result
 
     def fetch_pack(self, path, determine_wants, graph_walker, pack_data,
-                   progress=None):
+                   progress=None, depth=None):
         """Retrieve a pack from a git smart server.
 
         :param path: Remote path to fetch from
@@ -395,6 +395,7 @@ class GitClient(object):
         :param graph_walker: Object with next() and ack().
         :param pack_data: Callback called for each bit of data in the pack
         :param progress: Callback for progress reports (strings)
+        :param depth: Shallow fetch depth
         :return: FetchPackResult object
         """
         raise NotImplementedError(self.fetch_pack)
@@ -571,6 +572,13 @@ class GitClient(object):
                              b' '.join(capabilities) + b'\n')
         for want in wants[1:]:
             proto.write_pkt_line(COMMAND_WANT + b' ' + want + b'\n')
+        if getattr(graph_walker, 'shallow', None):
+            if not CAPABILITY_SHALLOW in capabilities:
+                raise GitProtocolError(
+                    "server does not support shallow capability required for "
+                    "shallow")
+            for obj_id in graph_walker.shallow:
+                proto.write_pkt_line(COMMAND_SHALLOW + b' ' + shallow + b'\n')
         if depth not in (0, None):
             if not CAPABILITY_SHALLOW in capabilities:
                 raise GitProtocolError(
@@ -763,7 +771,7 @@ class TraditionalGitClient(GitClient):
             return new_refs
 
     def fetch_pack(self, path, determine_wants, graph_walker, pack_data,
-                   depth=None, progress=None):
+                   progress=None, depth=None):
         """Retrieve a pack from a git smart server.
 
         :param path: Remote path to fetch from
@@ -772,8 +780,8 @@ class TraditionalGitClient(GitClient):
             list of shas to fetch.
         :param graph_walker: Object with next() and ack().
         :param pack_data: Callback called for each bit of data in the pack
-        :param depth: Depth for request
         :param progress: Callback for progress reports (strings)
+        :param depth: Shallow fetch depth
         :return: FetchPackResult object
         """
         proto, can_read, stderr = self._connect(b'upload-pack', path)
@@ -1071,7 +1079,8 @@ class LocalGitClient(GitClient):
 
         return new_refs
 
-    def fetch(self, path, target, determine_wants=None, progress=None):
+    def fetch(self, path, target, determine_wants=None, progress=None,
+              depth=None):
         """Fetch into a target repository.
 
         :param path: Path to fetch from (as bytestring)
@@ -1080,16 +1089,17 @@ class LocalGitClient(GitClient):
             to fetch. Receives dictionary of name->sha, should return
             list of shas to fetch. Defaults to all shas.
         :param progress: Optional progress function
+        :param depth: Shallow fetch depth
         :return: FetchPackResult object
         """
         with self._open_repo(path) as r:
             refs = r.fetch(target, determine_wants=determine_wants,
-                           progress=progress)
+                           progress=progress, depth=depth)
             return FetchPackResult(refs, r.refs.get_symrefs(),
                                    agent_string())
 
     def fetch_pack(self, path, determine_wants, graph_walker, pack_data,
-                   progress=None):
+                   progress=None, depth=None):
         """Retrieve a pack from a git smart server.
 
         :param path: Remote path to fetch from
@@ -1099,11 +1109,12 @@ class LocalGitClient(GitClient):
         :param graph_walker: Object with next() and ack().
         :param pack_data: Callback called for each bit of data in the pack
         :param progress: Callback for progress reports (strings)
+        :param depth: Shallow fetch depth
         :return: FetchPackResult object
         """
         with self._open_repo(path) as r:
             objects_iter = r.fetch_objects(
-                determine_wants, graph_walker, progress)
+                determine_wants, graph_walker, progress=progress, depth=depth)
             symrefs = r.refs.get_symrefs()
             agent = agent_string()
 
@@ -1588,7 +1599,7 @@ class HttpGitClient(GitClient):
             resp.close()
 
     def fetch_pack(self, path, determine_wants, graph_walker, pack_data,
-                   depth=None, progress=None):
+                   progress=None, depth=None):
         """Retrieve a pack from a git smart server.
 
         :param determine_wants: Callback that returns list of commits to fetch
index d77f5ac065afcb0252626a80d3e73d4433202731..8534d6212b3b365137005c2882471095eb06cddf 100644 (file)
@@ -194,7 +194,8 @@ class BaseObjectStore(object):
 
     def find_missing_objects(self, haves, wants, progress=None,
                              get_tagged=None,
-                             get_parents=lambda commit: commit.parents):
+                             get_parents=lambda commit: commit.parents,
+                             depth=None):
         """Find the missing objects required for a set of revisions.
 
         :param haves: Iterable over SHAs already in common.
@@ -1165,7 +1166,7 @@ class ObjectStoreGraphWalker(object):
     :ivar get_parents: Function to retrieve parents in the local repo
     """
 
-    def __init__(self, local_heads, get_parents):
+    def __init__(self, local_heads, get_parents, shallow=None):
         """Create a new instance.
 
         :param local_heads: Heads to start search with
@@ -1174,6 +1175,9 @@ class ObjectStoreGraphWalker(object):
         self.heads = set(local_heads)
         self.get_parents = get_parents
         self.parents = {}
+        if shallow is None:
+            shallow = set()
+        self.shallow = shallow
 
     def ack(self, sha):
         """Ack that a revision and its ancestors are present in the source."""
index cd992aeb59abefb2a273bc860f54b8487a7ea2fa..b964ef0bf3bba6c4ce63deb38e1b2c3b07c3b62f 100644 (file)
@@ -259,24 +259,26 @@ class BaseRepo(object):
         """
         raise NotImplementedError(self.open_index)
 
-    def fetch(self, target, determine_wants=None, progress=None):
+    def fetch(self, target, determine_wants=None, progress=None, depth=None):
         """Fetch objects into another repository.
 
         :param target: The target repository
         :param determine_wants: Optional function to determine what refs to
             fetch.
         :param progress: Optional progress function
+        :param depth: Optional shallow fetch depth
         :return: The local refs
         """
         if determine_wants is None:
             determine_wants = target.object_store.determine_wants_all
         count, pack_data = self.fetch_pack_data(
-                determine_wants, target.get_graph_walker(), progress)
+                determine_wants, target.get_graph_walker(), progress=progress,
+                depth=depth)
         target.object_store.add_pack_data(count, pack_data, progress)
         return self.get_refs()
 
     def fetch_pack_data(self, determine_wants, graph_walker, progress,
-                        get_tagged=None):
+                        get_tagged=None, depth=None):
         """Fetch the pack data required for a set of revisions.
 
         :param determine_wants: Function that takes a dictionary with heads
@@ -288,15 +290,16 @@ class BaseRepo(object):
             updated progress strings.
         :param get_tagged: Function that returns a dict of pointed-to sha ->
             tag sha for including tags.
+        :param depth: Shallow fetch depth
         :return: count and iterator over pack data
         """
         # TODO(jelmer): Fetch pack data directly, don't create objects first.
         objects = self.fetch_objects(determine_wants, graph_walker, progress,
-                                     get_tagged)
+                                     get_tagged, depth=depth)
         return pack_objects_to_data(objects)
 
     def fetch_objects(self, determine_wants, graph_walker, progress,
-                      get_tagged=None):
+                      get_tagged=None, depth=None):
         """Fetch the missing objects required for a set of revisions.
 
         :param determine_wants: Function that takes a dictionary with heads
@@ -308,8 +311,12 @@ class BaseRepo(object):
             updated progress strings.
         :param get_tagged: Function that returns a dict of pointed-to sha ->
             tag sha for including tags.
+        :param depth: Shallow fetch depth
         :return: iterator over objects, with __len__ implemented
         """
+        if depth not in (None, 0):
+            raise NotImplementedError("depth not supported yet")
+
         wants = determine_wants(self.get_refs())
         if not isinstance(wants, list):
             raise TypeError("determine_wants() did not return a list")
@@ -361,7 +368,8 @@ class BaseRepo(object):
         """
         if heads is None:
             heads = self.refs.as_dict(b'refs/heads').values()
-        return ObjectStoreGraphWalker(heads, self.get_parents)
+        return ObjectStoreGraphWalker(
+            heads, self.get_parents, shallow=self.get_shallow())
 
     def get_refs(self):
         """Get dictionary with all refs.
index e5b707780797ef3e4f42dca4f9e233dc5d0b23cf..e9fa573be750eb92fb69809d88be50468e78ae8a 100644 (file)
@@ -134,7 +134,7 @@ class GitClientTests(TestCase):
         agent_cap = (
             'agent=dulwich/%d.%d.%d' % dulwich.__version__).encode('ascii')
         self.assertEqual(set([b'multi_ack', b'side-band-64k', b'ofs-delta',
-                              b'thin-pack', b'multi_ack_detailed',
+                              b'thin-pack', b'multi_ack_detailed', b'shallow',
                               agent_cap]),
                          set(self.client._fetch_capabilities))
         self.assertEqual(set([b'ofs-delta', b'report-status', b'side-band-64k',