launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #18611
[Merge] lp:~blr/turnip/repack-api into lp:turnip
Bayard 'kit' Randel has proposed merging lp:~blr/turnip/repack-api into lp:turnip with lp:~blr/turnip/api-init-with-alternates as a prerequisite.
Commit message:
Provides API for git repack, and per-repository configuration.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~blr/turnip/repack-api/+merge/257312
Provides API for git repack, and per-repository configuration.
Per-repository config defaults are read from git.config.yaml.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~blr/turnip/repack-api into lp:turnip.
=== modified file '.bzrignore'
--- .bzrignore 2015-02-17 21:32:29 +0000
+++ .bzrignore 2015-05-21 04:31:32 +0000
@@ -1,13 +1,13 @@
bin
+build
develop-eggs
+dist
download-cache
eggs
+*.egg*
+*.egg-info
.installed.cfg
+*.log
parts
-*.egg-info
tags
-TAGS
-build
-*.egg
-dist
-*.log
\ No newline at end of file
+TAGS
\ No newline at end of file
=== modified file 'turnip/api/store.py'
--- turnip/api/store.py 2015-05-19 12:55:00 +0000
+++ turnip/api/store.py 2015-05-21 04:31:32 +0000
@@ -7,6 +7,7 @@
import itertools
import os
import shutil
+import subprocess
import uuid
from pygit2 import (
@@ -22,6 +23,8 @@
Repository,
)
+from turnip.pack.helpers import ensure_config
+
REF_TYPE_NAME = {
GIT_OBJ_COMMIT: 'commit',
@@ -127,6 +130,7 @@
if alternate_repo_paths:
write_alternates(repo_path, alternate_repo_paths)
+ ensure_config(repo_path) # set repository configuration defaults
return repo_path
@@ -172,6 +176,29 @@
shutil.rmtree(repo_path)
+def repack(repo_path, ignore_alternates=False, single=False,
+ prune=False, no_reuse_delta=False):
+ """Repack a repository with git-repack.
+
+ :param ignore_alternates: Only repack local refs (git repack --local).
+ :param single: Create a single packfile (git repack -a).
+ :param prune: Remove redundant packs. (git repack -d)
+ :param no_reuse_delta: Force delta recalculation.
+ """
+ repack_args = ['git', 'repack']
+ if ignore_alternates:
+ repack_args.append('-l')
+ if no_reuse_delta:
+ repack_args.append('-f')
+ if prune:
+ repack_args.append('-d')
+ if single:
+ repack_args.append('-a')
+ return subprocess.check_call(
+ repack_args, cwd=repo_path,
+ stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+
+
def get_refs(repo_store, repo_name):
"""Return all refs for a git repository."""
with open_repo(repo_store, repo_name) as repo:
=== modified file 'turnip/api/tests/test_api.py'
--- turnip/api/tests/test_api.py 2015-05-19 12:55:00 +0000
+++ turnip/api/tests/test_api.py 2015-05-21 04:31:32 +0000
@@ -2,8 +2,9 @@
# -*- coding: utf-8 -*-
from __future__ import print_function
+import fnmatch
import os
-from textwrap import dedent
+import subprocess
import unittest
import uuid
@@ -12,6 +13,7 @@
TempDir,
)
from testtools import TestCase
+from textwrap import dedent
from webtest import TestApp
from turnip import api
@@ -510,6 +512,20 @@
self.assertEqual(5, len(resp.json))
self.assertNotIn(excluded_commit, resp.json)
+ def test_repo_repack_verify_pack(self):
+ """Ensure commit exists in pack."""
+ factory = RepoFactory(self.repo_store)
+ oid = factory.add_commit('foo', 'foobar.txt')
+ factory.set_head(oid)
+ resp = self.app.post_json('/repo/{}/repack'.format(self.repo_path),
+ {'prune': True, 'single': True})
+ for root, dirnames, filenames in os.walk(factory.repo_path):
+ for filename in fnmatch.filter(filenames, '*.pack'):
+ pack = os.path.join(root, filename)
+ out = subprocess.check_output(['git', 'verify-pack', pack, '-v'])
+ self.assertEqual(200, resp.status_code)
+ self.assertIn(oid.hex, out)
+
if __name__ == '__main__':
unittest.main()
=== modified file 'turnip/api/tests/test_store.py'
--- turnip/api/tests/test_store.py 2015-04-29 02:43:28 +0000
+++ turnip/api/tests/test_store.py 2015-05-21 04:31:32 +0000
@@ -16,6 +16,7 @@
)
import pygit2
from testtools import TestCase
+import yaml
from turnip.api import store
from turnip.api.tests.test_helpers import (
@@ -74,6 +75,17 @@
r = pygit2.Repository(path)
self.assertEqual([], r.listall_references())
+ def test_repo_config(self):
+ """Assert repository is initialised with correct config defaults."""
+ repo_path = store.init_repo(self.repo_path)
+ repo_config = pygit2.Repository(repo_path).config
+ yaml_config = yaml.load(open('git.config.yaml'))
+
+ self.assertEqual(bool(yaml_config['core.logallrefupdates']),
+ bool(repo_config['core.logallrefupdates']))
+ self.assertEqual(str(yaml_config['pack.depth']),
+ repo_config['pack.depth'])
+
def test_open_ephemeral_repo(self):
"""Opening a repo where a repo name contains ':' should return
a new ephemeral repo.
=== modified file 'turnip/api/views.py'
--- turnip/api/views.py 2015-05-19 12:55:00 +0000
+++ turnip/api/views.py 2015-05-21 04:31:32 +0000
@@ -2,6 +2,7 @@
import os
import re
+from subprocess import CalledProcessError
from cornice.resource import resource
from cornice.util import extract_json_data
@@ -123,6 +124,33 @@
return exc.HTTPNotFound() # 404
+@resource(path='/repo/{name}/repack')
+class RepackAPI(BaseAPI):
+ """Provides HTTP API for repository repacking."""
+
+ def __init__(self, request):
+ super(RepackAPI, self).__init__()
+ self.request = request
+
+ @validate_path
+ def post(self, repo_store, repo_name):
+ repo_path = os.path.join(repo_store, repo_name)
+
+ ignore_alternates = extract_json_data(self.request).get(
+ 'ignore_alternates')
+ no_reuse_delta = extract_json_data(self.request).get('no_reuse_delta')
+ prune = extract_json_data(self.request).get('prune')
+ single = extract_json_data(self.request).get('single')
+
+ try:
+ store.repack(repo_path, single=single, prune=prune,
+ no_reuse_delta=no_reuse_delta,
+ ignore_alternates=ignore_alternates)
+ except (CalledProcessError):
+ return exc.HTTPInternalServerError()
+ return
+
+
@resource(collection_path='/repo/{name}/refs',
path='/repo/{name}/refs/{ref:.*}')
class RefAPI(BaseAPI):
=== modified file 'turnip/pack/helpers.py'
--- turnip/pack/helpers.py 2015-05-06 11:46:43 +0000
+++ turnip/pack/helpers.py 2015-05-21 04:31:32 +0000
@@ -14,6 +14,7 @@
)
from pygit2 import Repository
+import yaml
import turnip.pack.hooks
@@ -104,10 +105,11 @@
pygit2.Config handles locking itself, so we don't need to think too hard
about concurrency.
"""
-
+ config_file = open('git.config.yaml')
+ git_config_defaults = yaml.load(config_file)
config = Repository(repo_root).config
- config['core.logallrefupdates'] = True
- config['repack.writeBitmaps'] = True
+ for key, val in git_config_defaults.iteritems():
+ config[key] = val
def ensure_hooks(repo_root):
Follow ups