summaryrefslogtreecommitdiff
path: root/morphlib/localrepocache.py
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2012-04-10 16:51:37 +0100
committerRichard Maw <richard.maw@codethink.co.uk>2012-04-11 13:10:27 +0100
commit48671d75ae47cd133ecf58cc476cd18ea9afd469 (patch)
treee2a59253cd2571fc1ac4d5e37be385ca91f9711b /morphlib/localrepocache.py
parentbb4c7432261aafc8682ffdcb49b76e44e9079501 (diff)
downloadmorph-48671d75ae47cd133ecf58cc476cd18ea9afd469.tar.gz
localrepocache: return error description
Also change _fetch to throw its exception as since it is more pythonic to throw exceptions than return exit status, other error handling needed to be caught, so it hsa been kept consistent. This required the tests to throw an exception as well
Diffstat (limited to 'morphlib/localrepocache.py')
-rw-r--r--morphlib/localrepocache.py65
1 files changed, 43 insertions, 22 deletions
diff --git a/morphlib/localrepocache.py b/morphlib/localrepocache.py
index 1be14555..f2fdc3e9 100644
--- a/morphlib/localrepocache.py
+++ b/morphlib/localrepocache.py
@@ -35,11 +35,13 @@ urlparse.uses_fragment.extend(gitscheme)
class NoRemote(Exception):
- def __init__(self, reponame):
+ def __init__(self, reponame, errors):
self.reponame = reponame
+ self.errors = errors
def __str__(self):
- return 'Cannot find remote git repository: %s' % self.reponame
+ return '\n\t'.join(['Cannot find remote git repository: %s' %
+ self.reponame] + self.errors)
class LocalRepoCache(object):
@@ -99,19 +101,16 @@ class LocalRepoCache(object):
'''
- try:
- source_handle = urllib2.urlopen(url)
- target_handle = open(filename, 'wb')
+ source_handle = urllib2.urlopen(url)
+ target_handle = open(filename, 'wb')
+ data = source_handle.read(4096)
+ while data:
+ target_handle.write(data)
data = source_handle.read(4096)
- while data:
- target_handle.write(data)
- data = source_handle.read(4096)
- source_handle.close()
- target_handle.close()
- except urllib2.URLError:
- return False
+ source_handle.close()
+ target_handle.close()
def _mkdir(self, dirname): # pragma: no cover
'''Create a directory.
@@ -131,6 +130,15 @@ class LocalRepoCache(object):
os.remove(filename)
+ def _rmtree(self, dirname): # pragma: no cover
+ '''Remove given directory tree.
+
+ This method is meant to be overridden by unit tests.
+
+ '''
+
+ shutil.rmtree(dirname)
+
def _escape(self, url):
'''Escape a URL so it can be used as a basename in a file.'''
@@ -166,12 +174,21 @@ class LocalRepoCache(object):
escaped = self._escape(repourl)
bundle_url = urlparse.urljoin(self._bundle_base_url, escaped)
bundle_path = path + '.bundle'
- success = self._fetch(bundle_url, bundle_path)
- if success:
+ try:
+ self._fetch(bundle_url, bundle_path)
+ except urllib2.URLError, e:
+ return False, 'Unable to fetch bundle %s: %s' % (bundle_url, e)
+ try:
self._git(['clone', bundle_path, path])
- if self._exists(bundle_path):
- self._remove(bundle_path)
- return success
+ except morphlib.execute.CommandFailure, e: # pragma: no cover
+ if self._exists(path):
+ shutil.rmtree(path)
+ return False, 'Unable to extract bundle %s: %s' % (bundle_path, e)
+ finally:
+ if self._exists(bundle_path):
+ self._remove(bundle_path)
+
+ return True, None
def cache_repo(self, reponame):
'''Clone the given repo into the cache.
@@ -179,7 +196,7 @@ class LocalRepoCache(object):
If the repo is already cloned, do nothing.
'''
-
+ errors = []
if not self._exists(self._cachedir):
self._mkdir(self._cachedir)
@@ -189,18 +206,22 @@ class LocalRepoCache(object):
if self._bundle_base_url:
for repourl, path in self._base_iterate(reponame):
- if self._clone_with_bundle(repourl, path):
+ ok, error = self._clone_with_bundle(repourl, path)
+ if ok:
return
+ else:
+ errors.append(error)
for repourl, path in self._base_iterate(reponame):
try:
self._git(['clone', repourl, path])
- except morphlib.execute.CommandFailure:
- pass
+ except morphlib.execute.CommandFailure, e:
+ errors.append('Unable to clone from %s to %s: %s' %
+ (repourl, path, e))
else:
break
else:
- raise NoRemote(reponame)
+ raise NoRemote(reponame, errors)
def get_repo(self, reponame):
'''Return an object representing a cached repository.'''