diff options
-rw-r--r-- | morphlib/localrepocache.py | 65 | ||||
-rw-r--r-- | morphlib/localrepocache_tests.py | 5 |
2 files changed, 46 insertions, 24 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.''' diff --git a/morphlib/localrepocache_tests.py b/morphlib/localrepocache_tests.py index 72f000f9..49dc021f 100644 --- a/morphlib/localrepocache_tests.py +++ b/morphlib/localrepocache_tests.py @@ -15,6 +15,7 @@ import unittest +import urllib2 import morphlib @@ -65,7 +66,7 @@ class LocalRepoCacheTests(unittest.TestCase): self.removed.append(filename) def not_found(self, url, path): - return False + raise urllib2.URLError('Not found') def fake_fetch(self, url, path): self.fetched.append(url) @@ -135,6 +136,6 @@ class LocalRepoCacheTests(unittest.TestCase): self.assertFalse('/' in escaped) def test_noremote_error_message_contains_repo_name(self): - e = morphlib.localrepocache.NoRemote(self.repourl) + e = morphlib.localrepocache.NoRemote(self.repourl, []) self.assertTrue(self.repourl in str(e)) |