summaryrefslogtreecommitdiff
path: root/morphlib/cachedrepo.py
diff options
context:
space:
mode:
authorSam Thursfield <sam.thursfield@codethink.co.uk>2014-10-23 17:33:49 +0100
committerSam Thursfield <sam.thursfield@codethink.co.uk>2014-12-03 10:23:27 +0000
commit2dc11594d5b95d876c9997ca40dfb08bf06c830b (patch)
treec2752f38b17e765416dad9ea64688aad0e60d60a /morphlib/cachedrepo.py
parentbb1960c7711a8a48bbaabd188158a3c5d7f0ff04 (diff)
downloadmorph-2dc11594d5b95d876c9997ca40dfb08bf06c830b.tar.gz
Rework CachedRepo to use the GitDirectory class where possible
This consolidates a bunch of code paths that were previously duplicated. This also changes the API for local cached repos to match the function names GitDirectory uses. Note that the remote repo cache still uses the old names, and should be fixed when time permits. Some unit tests that use the CachedRepo module required a bit of inelegant monkey-patching in order that they continue to work. A better way to do this would be with the 'mock' library (which would need to be added to Baserock 'build' and 'devel' systems before we could use it).
Diffstat (limited to 'morphlib/cachedrepo.py')
-rw-r--r--morphlib/cachedrepo.py150
1 files changed, 45 insertions, 105 deletions
diff --git a/morphlib/cachedrepo.py b/morphlib/cachedrepo.py
index aad3d84e..aa2b5af1 100644
--- a/morphlib/cachedrepo.py
+++ b/morphlib/cachedrepo.py
@@ -15,26 +15,11 @@
import cliapp
-import logging
import os
import morphlib
-class InvalidReferenceError(cliapp.AppException):
-
- def __init__(self, repo, ref):
- cliapp.AppException.__init__(
- self, 'Ref %s is an invalid reference for repo %s' % (ref, repo))
-
-
-class UnresolvedNamedReferenceError(cliapp.AppException):
-
- def __init__(self, repo, ref):
- cliapp.AppException.__init__(
- self, 'Ref %s is not a SHA1 ref for repo %s' % (ref, repo))
-
-
class CheckoutDirectoryExistsError(cliapp.AppException):
def __init__(self, repo, target_dir):
@@ -105,63 +90,52 @@ class CachedRepo(object):
self.is_mirror = not url.startswith('file://')
self.already_updated = False
- def ref_exists(self, ref):
- '''Returns True if the given ref exists in the repo'''
+ self._gitdir = morphlib.gitdir.GitDirectory(path)
- try:
- self._rev_parse(ref)
- except cliapp.AppException:
- return False
- return True
+ def ref_exists(self, ref): # pragma: no cover
+ '''Returns True if the given ref exists in the repo'''
+ return self._gitdir.ref_exists(ref)
- def resolve_ref(self, ref):
- '''Attempts to resolve a ref into its SHA1 and tree SHA1.
+ def resolve_ref_to_commit(self, ref): # pragma: no cover
+ '''Resolve a named ref to a commit SHA1.
- Raises an InvalidReferenceError if the ref is not found in the
- repository.
+ Raises gitdir.InvalidRefError if the ref does not exist.
'''
+ return self._gitdir.resolve_ref_to_commit(ref)
- try:
- absref = self._rev_parse(ref)
- except cliapp.AppException:
- raise InvalidReferenceError(self, ref)
+ def resolve_ref_to_tree(self, ref): # pragma: no cover
+ '''Resolve a named ref to a tree SHA1.
- try:
- tree = self._show_tree_hash(absref)
- except cliapp.AppException:
- raise InvalidReferenceError(self, ref)
+ Raises gitdir.InvalidRefError if the ref does not exist.
- return absref, tree
+ '''
+ return self._gitdir.resolve_ref_to_tree(ref)
- def cat(self, ref, filename):
- '''Attempts to read a file given a SHA1 ref.
+ def read_file(self, filename, ref): # pragma: no cover
+ '''Attempts to read a file from a given ref.
- Raises an UnresolvedNamedReferenceError if the ref is not a SHA1
- ref. Raises an InvalidReferenceError if the SHA1 ref is not found
- in the repository. Raises an IOError if the requested file is not
- found in the ref.
+ Raises a gitdir.InvalidRefError if the ref is not found in the
+ repository. Raises an IOError if the requested file is not found in
+ the ref.
'''
+ return self._gitdir.read_file(filename, ref)
- if not morphlib.git.is_valid_sha1(ref):
- raise UnresolvedNamedReferenceError(self, ref)
- try:
- sha1 = self._rev_parse(ref)
- except cliapp.AppException:
- raise InvalidReferenceError(self, ref)
+ def list_files(self, ref, recurse=True): # pragma: no cover
+ '''Return filenames found in the tree pointed to by the given ref.
- try:
- return self._cat_file(sha1, filename)
- except cliapp.AppException:
- raise IOError('File %s does not exist in ref %s of repo %s' %
- (filename, ref, self))
+ Returns a gitdir.InvalidRefError if the ref is not found in the
+ repository.
+
+ '''
+ return self._gitdir.list_files(ref, recurse)
def clone_checkout(self, ref, target_dir):
'''Clone from the cache into the target path and check out a given ref.
Raises a CheckoutDirectoryExistsError if the target
- directory already exists. Raises an InvalidReferenceError if the
+ directory already exists. Raises a gitdir.InvalidRefError if the
ref is not found in the repository. Raises a CheckoutError if
something else goes wrong while copying the repository or checking
out the SHA1 ref.
@@ -171,14 +145,14 @@ class CachedRepo(object):
if os.path.exists(target_dir):
raise CheckoutDirectoryExistsError(self, target_dir)
- self.resolve_ref(ref)
+ self._gitdir.resolve_ref_to_commit(ref)
self._clone_into(target_dir, ref)
def checkout(self, ref, target_dir):
'''Unpacks the repository in a directory and checks out a commit ref.
- Raises an InvalidReferenceError if the ref is not found in the
+ Raises an gitdir.InvalidRefError if the ref is not found in the
repository. Raises a CopyError if something goes wrong with the copy
of the repository. Raises a CheckoutError if something else goes wrong
while copying the repository or checking out the SHA1 ref.
@@ -193,25 +167,7 @@ class CachedRepo(object):
# take care to turn the copy into something as good as a real clone.
self._copy_repository(self.path, target_dir)
- self._checkout_ref(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 morphlib.git.is_valid_sha1(ref):
- raise UnresolvedNamedReferenceError(self, ref)
- try:
- sha1 = self._rev_parse(ref)
- except cliapp.AppException:
- raise InvalidReferenceError(self, ref)
-
- return self._ls_tree(sha1)
+ self._checkout_ref_in_clone(ref, target_dir)
def requires_update_for_ref(self, ref):
'''Returns False if there's no need to update this cached repo.
@@ -232,7 +188,7 @@ class CachedRepo(object):
# Named refs that are valid SHA1s will confuse this code.
ref_can_change = not morphlib.git.is_valid_sha1(ref)
- if ref_can_change or not self.ref_exists(ref):
+ if ref_can_change or not self._gitdir.ref_exists(ref):
return True
else:
return False
@@ -249,9 +205,10 @@ class CachedRepo(object):
return
try:
- self._update()
+ self._gitdir.update_remotes(
+ echo_stderr=self.app.settings['verbose'])
self.already_updated = True
- except cliapp.AppException, e:
+ except cliapp.AppException:
raise UpdateError(self)
def _runcmd(self, *args, **kwargs): # pragma: no cover
@@ -259,27 +216,11 @@ class CachedRepo(object):
kwargs['cwd'] = self.path
return self.app.runcmd(*args, **kwargs)
- def _rev_parse(self, ref): # pragma: no cover
- return morphlib.git.gitcmd(self._runcmd, 'rev-parse', '--verify',
- '%s^{commit}' % ref)[0:40]
-
- def _show_tree_hash(self, absref): # pragma: no cover
- return morphlib.git.gitcmd(self._runcmd, 'rev-parse', '--verify',
- '%s^{tree}' % absref).strip()
-
- def _ls_tree(self, ref): # pragma: no cover
- result = morphlib.git.gitcmd(self._runcmd, 'ls-tree',
- '--name-only', ref)
- return result.split('\n')
-
- def _cat_file(self, ref, filename): # pragma: no cover
- return morphlib.git.gitcmd(self._runcmd, 'cat-file', 'blob',
- '%s:%s' % (ref, filename))
-
- def _clone_into(self, target_dir, ref): #pragma: no cover
+ def _clone_into(self, target_dir, ref): # pragma: no cover
'''Actually perform the clone'''
try:
- morphlib.git.clone_into(self._runcmd, self.path, target_dir, ref)
+ morphlib.git.clone_into(self._runcmd, self.path, target_dir,
+ ref)
except cliapp.AppException:
raise CloneError(self, target_dir)
@@ -290,16 +231,15 @@ class CachedRepo(object):
except cliapp.AppException:
raise CopyError(self, target_dir)
- def _checkout_ref(self, ref, target_dir): # pragma: no cover
+ def _checkout_ref_in_clone(self, ref, clone_dir): # pragma: no cover
+ # This is a separate GitDirectory instance. Don't confuse it with the
+ # internal ._gitdir attribute!
+ working_gitdir = morphlib.gitdir.GitDirectory(clone_dir)
try:
- morphlib.git.checkout_ref(self._runcmd, target_dir, ref)
- except cliapp.AppException:
- raise CheckoutError(self, ref, target_dir)
-
- def _update(self): # pragma: no cover
- morphlib.git.gitcmd(self._runcmd, 'remote', 'update',
- 'origin', '--prune',
- echo_stderr=self.app.settings['verbose'])
+ working_gitdir.checkout(ref)
+ except cliapp.AppException as e:
+ raise CheckoutError(self, ref, clone_dir)
+ return working_gitdir
def __str__(self): # pragma: no cover
return self.url