summaryrefslogtreecommitdiff
path: root/morphcacheserver
diff options
context:
space:
mode:
authorJannis Pohlmann <jannis.pohlmann@codethink.co.uk>2012-04-17 15:29:51 +0100
committerJannis Pohlmann <jannis.pohlmann@codethink.co.uk>2012-04-17 15:29:51 +0100
commit9ba282863b41bea8d9fe990a9aba92677e2f4501 (patch)
treec2067aed613ee82879179483f421c37f64188715 /morphcacheserver
downloadmorph-9ba282863b41bea8d9fe990a9aba92677e2f4501.tar.gz
Initial import implementing /files and /sha1s.
Diffstat (limited to 'morphcacheserver')
-rw-r--r--morphcacheserver/__init__.py17
-rw-r--r--morphcacheserver/repocache.py92
2 files changed, 109 insertions, 0 deletions
diff --git a/morphcacheserver/__init__.py b/morphcacheserver/__init__.py
new file mode 100644
index 00000000..9ad5a305
--- /dev/null
+++ b/morphcacheserver/__init__.py
@@ -0,0 +1,17 @@
+# 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 repocache
diff --git a/morphcacheserver/repocache.py b/morphcacheserver/repocache.py
new file mode 100644
index 00000000..49b82001
--- /dev/null
+++ b/morphcacheserver/repocache.py
@@ -0,0 +1,92 @@
+# 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 os
+import string
+
+
+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 RepoCache(object):
+
+ def __init__(self, app, dirname):
+ self.app = app
+ self.dirname = dirname
+
+ def resolve_ref(self, repo_url, ref):
+ quoted_url = self._quote_url(repo_url)
+ repo_dir = os.path.join(self.dirname, quoted_url)
+ try:
+ refs = self._show_ref(repo_dir, ref).split('\n')
+ refs = [x.split() for x in refs if 'origin' in x]
+ return refs[0][0]
+ except cliapp.AppException:
+ pass
+ if not self._is_valid_sha1(ref):
+ raise InvalidReferenceError(repo_url, ref)
+ try:
+ return self._rev_list(ref).strip()
+ except:
+ raise InvalidReferenceError(repo_url, ref)
+
+ def cat_file(self, repo_url, ref, filename):
+ quoted_url = self._quote_url(repo_url)
+ repo_dir = os.path.join(self.dirname, quoted_url)
+
+ if not self._is_valid_sha1(ref):
+ raise UnresolvedNamedReferenceError(repo_url, ref)
+ try:
+ sha1 = self._rev_list(repo_dir, ref).strip()
+ except:
+ raise InvalidReferenceError(repo_url, ref)
+
+ return self._cat_file(repo_dir, sha1, filename)
+
+ def _quote_url(self, url):
+ valid_chars = string.digits + string.letters + '%_'
+ transl = lambda x: x if x in valid_chars else '_'
+ return ''.join([transl(x) for x in url])
+
+ def _show_ref(self, repo_dir, ref):
+ return self.app.runcmd(['git', 'show-ref', ref], cwd=repo_dir)
+
+ def _rev_list(self, repo_dir, ref):
+ return self.app.runcmd(
+ ['git', 'rev-list', '--no-walk', ref], cwd=repo_dir)
+
+ def _cat_file(self, repo_dir, sha1, filename):
+ return self.app.runcmd(
+ ['git', 'cat-file', 'blob', '%s:%s' % (sha1, filename)],
+ cwd=repo_dir)
+
+ def _is_valid_sha1(self, ref):
+ valid_chars = 'abcdefABCDEF0123456789'
+ return len(ref) == 40 and all([x in valid_chars for x in ref])