← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~ilasc/turnip:add-git-gc-api into turnip:master

 

Ioana Lasc has proposed merging ~ilasc/turnip:add-git-gc-api into turnip:master.

Commit message:
Add a Git GC api

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~ilasc/turnip/+git/turnip/+merge/401220

Add an async endpoint to enable us to run a Git GC on a repository ourselves.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~ilasc/turnip:add-git-gc-api into turnip:master.
diff --git a/turnip/api/store.py b/turnip/api/store.py
index f2719a7..f1e4664 100644
--- a/turnip/api/store.py
+++ b/turnip/api/store.py
@@ -498,6 +498,32 @@ def repack(repo_path):
         raise
 
 
+@app.task
+def gc(repo_path):
+    """Run as git gc for repository."""
+    logger = tasks_logger
+    logger.info(
+        "Asynchronous GC run triggered for repository: "
+        "%s", repo_path)
+
+    ensure_config(repo_path)
+
+    gc_args = ['git', 'gc']
+
+    try:
+        subprocess.check_call(
+            gc_args, cwd=repo_path,
+            stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+        logger.info(
+            "GC completed for repository: "
+            "%s", repo_path)
+    except subprocess.CalledProcessError:
+        logger.info(
+            "GC failed for repository: "
+            "%s", repo_path)
+        raise
+
+
 def get_refs(repo_store, repo_name, exclude_prefixes=None):
     """Return all refs for a git repository."""
     with open_repo(repo_store, repo_name) as repo:
diff --git a/turnip/api/tests/test_api.py b/turnip/api/tests/test_api.py
index b3d0fb6..85683b1 100644
--- a/turnip/api/tests/test_api.py
+++ b/turnip/api/tests/test_api.py
@@ -837,6 +837,10 @@ class ApiTestCase(TestCase, ApiRepoStoreMixin):
         resp = self.app.post_json('/repo/{}/repack'.format(self.repo_path))
         self.assertEqual(200, resp.status_code)
 
+    def test_repo_gc(self):
+        resp = self.app.post_json('/repo/{}/gc'.format(self.repo_path))
+        self.assertEqual(200, resp.status_code)
+
     def test_repo_detect_merges_missing_target(self):
         """A non-existent target OID returns HTTP 404."""
         factory = RepoFactory(self.repo_store)
diff --git a/turnip/api/tests/test_store.py b/turnip/api/tests/test_store.py
index 24cdced..e54c127 100644
--- a/turnip/api/tests/test_store.py
+++ b/turnip/api/tests/test_store.py
@@ -475,3 +475,20 @@ class InitTestCase(TestCase):
         # Assert we have 0 loose objects after repack job ran
         celery_fixture.waitUntil(
             5, lambda: self.hasZeroLooseObjects(orig_path))
+
+    def test_gc(self):
+        celery_fixture = CeleryWorkerFixture()
+        self.useFixture(celery_fixture)
+
+        self.makeOrig()
+        orig_path = self.orig_path
+
+        # First assert we have loose objects for this repo
+        self.assertFalse(self.hasZeroLooseObjects(orig_path))
+
+        # Trigger the GC job
+        store.gc.apply_async((orig_path, ))
+
+        # Assert we have 0 loose objects after a gc job ran
+        celery_fixture.waitUntil(
+            5, lambda: self.hasZeroLooseObjects(orig_path))
diff --git a/turnip/api/views.py b/turnip/api/views.py
index cda3a00..09a9a92 100644
--- a/turnip/api/views.py
+++ b/turnip/api/views.py
@@ -148,6 +148,22 @@ class RepackAPI(BaseAPI):
         return Response(status=200)
 
 
+@resource(path='/repo/{name}/gc')
+class GitGCAPI(BaseAPI):
+    """Provides HTTP API for running gc for repository."""
+
+    def __init__(self, request, context=None):
+        super(GitGCAPI, self).__init__()
+        self.request = request
+
+    @validate_path
+    def post(self, repo_store, repo_name):
+        repo_path = os.path.join(repo_store, repo_name)
+        kwargs = dict(repo_path=repo_path)
+        store.gc.apply_async(kwargs=kwargs)
+        return Response(status=200)
+
+
 @resource(path='/repo/{name}/refs-copy')
 class RefCopyAPI(BaseAPI):
     """Provides HTTP API for git references copy operations."""