← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~jugmac00/turnip:retrieve-launchpad-yaml-more-efficiently into turnip:master

 

Jürgen Gmach has proposed merging ~jugmac00/turnip:retrieve-launchpad-yaml-more-efficiently into turnip:master.

Commit message:
commit API now can filter by blob paths

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~jugmac00/turnip/+git/turnip/+merge/414251
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~jugmac00/turnip:retrieve-launchpad-yaml-more-efficiently into turnip:master.
diff --git a/turnip/api/tests/test_api.py b/turnip/api/tests/test_api.py
index ca47021..b1dc14d 100644
--- a/turnip/api/tests/test_api.py
+++ b/turnip/api/tests/test_api.py
@@ -773,6 +773,57 @@ class ApiTestCase(TestCase, ApiRepoStoreMixin):
         self.assertEqual(1, len(resp.json))
         self.assertEqual(bulk_commits['commits'][0], resp.json[0]['sha1'])
 
+    def test_repo_get_launchpad_yaml_from_commit_collection(self):
+        factory = RepoFactory(self.repo_store, num_commits=10)
+        factory.build()
+
+        # standard configuration file name
+        c1 = factory.add_commit('bar', '.launchpad.yaml')
+        # commit which must not be returned
+        c2 = factory.commits[0]
+
+        payload = {
+            'blob_paths': [".launchpad.yaml", "debian/.launchpad.yaml"],
+            "commits": [c1.hex, c2.hex]
+        }
+
+        resp = self.app.post_json(
+            '/repo/{}/commits'.format(self.repo_path), payload
+        )
+
+        self.assertEqual(1, len(resp.json))
+        self.assertIn("blobs", resp.json[0])
+        self.assertEqual(
+             {'.launchpad.yaml': {'size': 3, 'data': 'YmFy'}},
+            resp.json[0]["blobs"]
+        )
+
+    def test_repo_get_launchpad_yaml_from_commit_collection_debian_edition(self):
+        factory = RepoFactory(self.repo_store, num_commits=10)
+        factory.build()
+
+        # debian packaging: typical random files are added under `debian/...`
+        c1 = factory.add_commit('bar', 'debian/.launchpad.yaml')
+        # commit which must not be returned
+        c2 = factory.commits[0]
+
+        payload = {
+            'blob_paths': [".launchpad.yaml", "debian/.launchpad.yaml"],
+            "commits": [c1.hex, c2.hex]
+        }
+
+        resp = self.app.post_json(
+            '/repo/{}/commits'.format(self.repo_path), payload
+        )
+
+        self.assertEqual(1, len(resp.json))
+        self.assertIn("blobs", resp.json[0])
+        self.assertEqual(
+            {'debian/.launchpad.yaml': {'size': 3, 'data': 'YmFy'}},
+            resp.json[0]["blobs"]
+        )
+
+
     def test_repo_get_log_signatures(self):
         """Ensure signatures are correct."""
         factory = RepoFactory(self.repo_store)
diff --git a/turnip/api/views.py b/turnip/api/views.py
index d5cf3d7..d5d64a4 100644
--- a/turnip/api/views.py
+++ b/turnip/api/views.py
@@ -11,7 +11,7 @@ import pyramid.httpexceptions as exc
 from pyramid.response import Response
 
 from turnip.api import store
-from turnip.api.formatter import format_commit
+from turnip.api.formatter import format_blob, format_commit
 from turnip.config import config
 
 
@@ -357,12 +357,29 @@ class CommitAPI(BaseAPI):
     @validate_path
     def collection_post(self, repo_store, repo_name):
         """Get commits in bulk."""
-        commits = extract_cstruct(self.request)['body'].get('commits')
+        payload = extract_cstruct(self.request)["body"]
+        commits = payload.get("commits")
+        blob_paths = payload.get("blob_paths")
         try:
             commits = store.get_commits(repo_store, repo_name, commits)
         except GitError:
             return exc.HTTPNotFound()
-        return [format_commit(commit) for commit in commits]
+        if not blob_paths:
+            return [format_commit(commit) for commit in commits]
+
+        # filter commits (we only want those with blob paths)
+        rv = []
+        for commit in commits:
+            d = dict()
+            for path in blob_paths:
+                if path in commit.tree:
+                    if not d.get("blobs"):
+                        d["blobs"] = dict()
+                    d["blobs"][path] = format_blob(commit.tree[path])
+            if bool(d):  # the commit contains the desired blobs
+                d.update(format_commit(commit))
+                rv.append(d)
+        return rv
 
 
 @resource(path='/repo/{name}/log/{sha1}')