summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam.thursfield@codethink.co.uk>2012-08-24 17:57:49 +0100
committerSam Thursfield <sam.thursfield@codethink.co.uk>2012-08-24 17:57:49 +0100
commit975b3f30605c36a714bf5b9619817a897cb6a4a3 (patch)
tree5564243efa6a55dc49ed05c2455e70b32598c6bf
parent6c13c2ebdea1da19bf359fef9a9e0b08e5491a4a (diff)
downloadmorph-975b3f30605c36a714bf5b9619817a897cb6a4a3.tar.gz
Support 'git ls-tree' in local and remote repos
-rw-r--r--morphlib/cachedrepo.py22
-rw-r--r--morphlib/cachedrepo_tests.py23
-rw-r--r--morphlib/remoterepocache.py18
-rw-r--r--morphlib/remoterepocache_tests.py28
4 files changed, 91 insertions, 0 deletions
diff --git a/morphlib/cachedrepo.py b/morphlib/cachedrepo.py
index d7f22400..f647102f 100644
--- a/morphlib/cachedrepo.py
+++ b/morphlib/cachedrepo.py
@@ -158,6 +158,24 @@ class CachedRepo(object):
except cliapp.AppException:
raise CheckoutError(self, ref, target_dir)
+ def ls_tree(self, ref):
+ '''Return file names found in root tree. Does not recurse to subtrees.
+
+ Raises an UnresolvedNamedReferenceError if the ref is not a SHA1
+ ref. Raises an InvalidReferenceError if the SHA1 ref is not found
+ in the repository.
+
+ '''
+
+ if not self.is_valid_sha1(ref):
+ raise UnresolvedNamedReferenceError(self, ref)
+ try:
+ sha1 = self._rev_list(ref).strip()
+ except cliapp.AppException:
+ raise InvalidReferenceError(self, ref)
+
+ return self._ls_tree(sha1)
+
def update(self):
'''Updates the cached repository using its origin remote.
@@ -182,6 +200,10 @@ class CachedRepo(object):
def _rev_list(self, ref): # pragma: no cover
return self._runcmd(['git', 'rev-list', '--no-walk', ref])
+ def _ls_tree(self, ref): # pragma: no cover
+ result = self._runcmd(['git', 'ls-tree', '--name-only', ref])
+ return result.split('\n')
+
def _cat_file(self, ref, filename): # pragma: no cover
return self._runcmd(['git', 'cat-file', 'blob',
'%s:%s' % (ref, filename)])
diff --git a/morphlib/cachedrepo_tests.py b/morphlib/cachedrepo_tests.py
index 2a0c2c4b..fa660010 100644
--- a/morphlib/cachedrepo_tests.py
+++ b/morphlib/cachedrepo_tests.py
@@ -79,6 +79,16 @@ class CachedRepoTests(unittest.TestCase):
with open(os.path.join(target_dir, 'foo.morph'), 'w') as f:
f.write('contents of foo.morph')
+ def ls_tree(self, ref):
+ output = {
+ 'e28a23812eadf2fce6583b8819b9c5dbd36b9fb9':
+ ['foo.morph']
+ }
+ try:
+ return output[ref]
+ except:
+ raise cliapp.AppException('git ls-tree --name-only %s' % (ref))
+
def update_successfully(self):
pass
@@ -96,6 +106,7 @@ class CachedRepoTests(unittest.TestCase):
self.repo._cat_file = self.cat_file
self.repo._copy_repository = self.copy_repository
self.repo._checkout_ref = self.checkout_ref
+ self.repo._ls_tree = self.ls_tree
self.tempdir = morphlib.tempdir.Tempdir()
def tearDown(self):
@@ -177,6 +188,18 @@ class CachedRepoTests(unittest.TestCase):
'a4da32f5a81c8bc6d660404724cedc3bc0914a75',
self.tempdir.join('failed-checkout'))
+ def test_ls_tree_in_existing_ref(self):
+ data = self.repo.ls_tree('e28a23812eadf2fce6583b8819b9c5dbd36b9fb9')
+ self.assertEqual(data, ['foo.morph'])
+
+ def test_fail_ls_tree_in_invalid_ref(self):
+ self.assertRaises(cachedrepo.InvalidReferenceError, self.repo.ls_tree,
+ '079bbfd447c8534e464ce5d40b80114c2022ebf4')
+
+ def test_fail_because_ls_tree_in_named_ref_is_not_allowed(self):
+ self.assertRaises(cachedrepo.UnresolvedNamedReferenceError,
+ self.repo.ls_tree, 'master')
+
def test_successful_update(self):
self.repo._update = self.update_successfully
self.repo.update()
diff --git a/morphlib/remoterepocache.py b/morphlib/remoterepocache.py
index d8526562..c40057b1 100644
--- a/morphlib/remoterepocache.py
+++ b/morphlib/remoterepocache.py
@@ -35,6 +35,13 @@ class CatFileError(cliapp.AppException):
self, 'Failed to cat file %s in ref %s of repo %s' %
(filename, ref, repo_name))
+class LsTreeError(cliapp.AppException):
+
+ def __init__(self, repo_name, ref):
+ cliapp.AppException.__init__(
+ self, 'Failed to list tree in ref %s of repo %s' %
+ (ref, repo_name))
+
class RemoteRepoCache(object):
@@ -56,6 +63,14 @@ class RemoteRepoCache(object):
except:
raise CatFileError(repo_name, ref, filename)
+ def ls_tree(self, repo_name, ref):
+ repo_url = self._resolver.pull_url(repo_name)
+ try:
+ info = json.loads(self._ls_tree_for_repo_url(repo_url, ref))
+ return info['tree'].keys()
+ except:
+ raise LsTreeError(repo_name, ref)
+
def _resolve_ref_for_repo_url(self, repo_url, ref): # pragma: no cover
data = self._make_request('sha1s?repo=%s&ref=%s' % (repo_url, ref))
info = json.loads(data)
@@ -66,6 +81,9 @@ class RemoteRepoCache(object):
return self._make_request(
'files?repo=%s&ref=%s&filename=%s' % (repo_url, ref, filename))
+ def _ls_tree_for_repo_url(self, repo_url, ref): # pragma: no cover
+ return self._make_request('trees?repo=%s&ref=%s' % (repo_url, ref))
+
def _make_request(self, path): # pragma: no cover
server_url = self.server_url
if not server_url.endswith('/'):
diff --git a/morphlib/remoterepocache_tests.py b/morphlib/remoterepocache_tests.py
index 6f162f7d..5ef61f48 100644
--- a/morphlib/remoterepocache_tests.py
+++ b/morphlib/remoterepocache_tests.py
@@ -14,6 +14,7 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+import json
import unittest
import morphlib
@@ -27,6 +28,13 @@ class RemoteRepoCacheTests(unittest.TestCase):
def _cat_file_for_repo_url(self, repo_url, sha1, filename):
return self.files[repo_url][sha1][filename]
+ def _ls_tree_for_repo_url(self, repo_url, sha1):
+ return json.dumps({
+ 'repo': repo_url,
+ 'ref': sha1,
+ 'tree': self.files[repo_url][sha1]
+ })
+
def setUp(self):
self.sha1s = {
'git://gitorious.org/baserock/morph': {
@@ -50,6 +58,7 @@ class RemoteRepoCacheTests(unittest.TestCase):
self.server_url, resolver)
self.cache._resolve_ref_for_repo_url = self._resolve_ref_for_repo_url
self.cache._cat_file_for_repo_url = self._cat_file_for_repo_url
+ self.cache._ls_tree_for_repo_url = self._ls_tree_for_repo_url
def test_sets_server_url(self):
self.assertEqual(self.cache.server_url, self.server_url)
@@ -103,3 +112,22 @@ class RemoteRepoCacheTests(unittest.TestCase):
self.cache.cat_file, 'non-existent-repo',
'e28a23812eadf2fce6583b8819b9c5dbd36b9fb9',
'some-file')
+
+ def test_ls_tree_in_existing_repo_and_ref(self):
+ content = self.cache.ls_tree(
+ 'upstream:linux', 'e28a23812eadf2fce6583b8819b9c5dbd36b9fb9')
+ self.assertEqual(content, ['linux.morph'])
+
+ def test_fail_ls_tree_using_invalid_sha1(self):
+ self.assertRaises(morphlib.remoterepocache.LsTreeError,
+ self.cache.ls_tree, 'upstream:linux', 'blablabla')
+
+ def test_fail_ls_file_in_non_existent_ref_in_existing_repo(self):
+ self.assertRaises(morphlib.remoterepocache.LsTreeError,
+ self.cache.ls_tree, 'upstream:linux',
+ 'ecd7a325095a0d19b8c3d76f578d85b979461d41')
+
+ def test_fail_ls_tree_in_non_existent_repo(self):
+ self.assertRaises(morphlib.remoterepocache.LsTreeError,
+ self.cache.ls_tree, 'non-existent-repo',
+ 'e28a23812eadf2fce6583b8819b9c5dbd36b9fb9')