diff options
author | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2012-04-09 18:15:27 +0100 |
---|---|---|
committer | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2012-04-09 18:15:27 +0100 |
commit | cc9d92874c159b65b248f8f8f7e164aa32416836 (patch) | |
tree | dd9f29865d4f8d65e1c1290145c6f7d9c9ce3b57 /morphlib/localrepocache.py | |
parent | eb362413076846559ac1c22a32e2e29174055fcb (diff) | |
download | morph-cc9d92874c159b65b248f8f8f7e164aa32416836.tar.gz |
Add bundle support to LocalRepoCache
Diffstat (limited to 'morphlib/localrepocache.py')
-rw-r--r-- | morphlib/localrepocache.py | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/morphlib/localrepocache.py b/morphlib/localrepocache.py index 673f9854..9beba4af 100644 --- a/morphlib/localrepocache.py +++ b/morphlib/localrepocache.py @@ -66,11 +66,17 @@ class LocalRepoCache(object): is prepended. The base urls are given to the class when it is created. + Instead of cloning via a normal 'git clone' directly from the + git server, we first try to download a bundle from a url, and + if that works, we clone from the bundle. + ''' - def __init__(self, cachedir, baseurls): + def __init__(self, cachedir, baseurls, bundle_base_url): + assert bundle_base_url.endswith('/') self._cachedir = cachedir self._baseurls = baseurls + self._bundle_base_url = bundle_base_url self._ex = morphlib.execute.Execute(cachedir, logging.debug) def _exists(self, filename): # pragma: no cover @@ -93,9 +99,34 @@ class LocalRepoCache(object): self._ex.runv(['git'] + args) + def _fetch(self, url, filename): # pragma: no cover + '''Fetch contents of url into a file. + + This method is meant to be overridden by unit tests. + + ''' + + 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) + + source_handle.close() + target_handle.close() + def _escape(self, url): '''Escape a URL so it can be used as a basename in a file.''' - return urllib.quote(url, safe='') + + # FIXME: The following is a nicer way than what source manager does. + # However, for compatibility, we need to use the same as the source + # manager uses, since that's what the bundle server (set up by + # Lorry) uses. + # return urllib.quote(url, safe='') + + return morphlib.sourcemanager.quote_url(url) def _cache_name(self, url): basename = self._escape(url) @@ -115,6 +146,16 @@ class LocalRepoCache(object): return True return False + def _clone_with_bundle(self, repourl, path): + escaped = self._escape(repourl) + bundle_url = urlparse.urljoin(self._bundle_base_url, escaped) + bundle_path = path + '.bundle' + if self._fetch(bundle_url, bundle_path): + self._git(['clone', bundle_path, path]) + return True + else: + return False + def cache_repo(self, reponame): '''Clone the given repo into the cache. @@ -125,6 +166,10 @@ class LocalRepoCache(object): for repourl, path in self._base_iterate(reponame): if self._exists(path): break + + if self._clone_with_bundle(repourl, path): + break + try: self._git(['clone', reponame, path]) except morphlib.execute.CommandFailure: |