summaryrefslogtreecommitdiff
path: root/morphlib/remoterepocache.py
diff options
context:
space:
mode:
authorJannis Pohlmann <jannis.pohlmann@codethink.co.uk>2012-04-18 13:29:17 +0100
committerJannis Pohlmann <jannis.pohlmann@codethink.co.uk>2012-04-18 13:34:25 +0100
commit5eb0ee253316dc930a4f53a8366764c280ae8fe5 (patch)
treecb82a6bb54eb4d3bdff1f1a8c82f6af60ee820f8 /morphlib/remoterepocache.py
parentad31f7608febab04157e015a90f5047a6f0d8d83 (diff)
downloadmorph-5eb0ee253316dc930a4f53a8366764c280ae8fe5.tar.gz
Add RemoteRepoCache and integrate it into _create_source_pool().
This adds a new setting called 'cache-server' to morph. It is None by default and should be set to the HTTP URL of a morph cache server to be used. The RemoteRepoCache object provides two methods: resolve_ref() and cat_file(), both of which wrap the communication with the cache server and return a SHA1 string and file contents, respectively. The _create_source_pool() method now takes a local and an optional remote repo cache and tries to do whatever is best to resolve refs and load morphologies for the Source objects it creates.
Diffstat (limited to 'morphlib/remoterepocache.py')
-rw-r--r--morphlib/remoterepocache.py84
1 files changed, 84 insertions, 0 deletions
diff --git a/morphlib/remoterepocache.py b/morphlib/remoterepocache.py
new file mode 100644
index 00000000..fd843682
--- /dev/null
+++ b/morphlib/remoterepocache.py
@@ -0,0 +1,84 @@
+# Copyright (C) 2012 Codethink Limited
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+import cliapp
+import json
+import urllib2
+import urlparse
+
+
+class ResolveRefError(cliapp.AppException):
+
+ def __init__(self, repo_name, ref):
+ cliapp.AppException.__init__(
+ self, 'Failed to resolve ref %s for repo %s' %
+ (ref, repo_name))
+
+
+class CatFileError(cliapp.AppException):
+
+ def __init__(self, repo_name, ref, filename):
+ cliapp.AppException.__init__(
+ self, 'Failed to cat file %s in ref %s of repo %s' %
+ (filename, ref, repo_name))
+
+
+class RemoteRepoCache(object):
+
+ def __init__(self, server_url, base_urls):
+ self.server_url = server_url
+ self._base_urls = base_urls
+
+ def _base_iterate(self, repo_name):
+ for base_url in self._base_urls:
+ if not base_url.endswith('/'):
+ base_url += '/'
+ repo_url = urlparse.urljoin(base_url, repo_name)
+ yield repo_url
+
+ def resolve_ref(self, repo_name, ref):
+ for repo_url in self._base_iterate(repo_name):
+ try:
+ return self._resolve_ref_for_repo_url(repo_url, ref)
+ except:
+ pass
+ raise ResolveRefError(repo_name, ref)
+
+ def cat_file(self, repo_name, ref, filename):
+ for repo_url in self._base_iterate(repo_name):
+ try:
+ return self._cat_file_for_repo_url(repo_url, ref, filename)
+ except:
+ pass
+ raise CatFileError(repo_name, ref, filename)
+
+ 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)
+ return info['sha1']
+
+ def _cat_file_for_repo_url(self, repo_url, ref,
+ filename): # pragma: no cover
+ return self._make_request(
+ 'files?repo=%s&ref=%s&filename=%s' % (repo_url, ref, filename))
+
+ def _make_request(self, path):
+ server_url = self.server_url
+ if not server_url.endswith('/'):
+ server_url += '/'
+ url = urlparse.urljoin(server_url, '/1.0/%s' % path)
+ handle = urllib2.urlopen(url)
+ return handle.read()