Index: chrome/common/extensions/docs/server2/github_file_system.py |
diff --git a/chrome/common/extensions/docs/server2/github_file_system.py b/chrome/common/extensions/docs/server2/github_file_system.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ccb51c44185f7f9b428f70eeadb145e063fc0d69 |
--- /dev/null |
+++ b/chrome/common/extensions/docs/server2/github_file_system.py |
@@ -0,0 +1,91 @@ |
+# Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+import json |
+import os |
+ |
+import appengine_blobstore as blobstore |
+import appengine_memcache as memcache |
+import file_system |
+from io import BytesIO |
+from future import Future |
+from zipfile import ZipFile |
+ |
+ZIP_KEY = 'zipball' |
+ |
+def _MakeKey(version): |
+ return ZIP_KEY + '.' + str(version) |
+ |
+class _AsyncFetchFutureZip(object): |
+ def __init__(self, fetcher, blobstore, new_version, old_version): |
+ self._fetch = fetcher.FetchAsync(ZIP_KEY) |
+ self._blobstore = blobstore |
+ self._new_version = new_version |
+ self._old_version = old_version |
+ |
+ def Get(self): |
+ blob = self._fetch.Get().content |
+ self._blobstore.Set(_MakeKey(self._new_version), |
+ blob, |
+ blobstore.BLOBSTORE_GITHUB) |
+ self._blobstore.Delete(_MakeKey(self._old_version), |
+ blobstore.BLOBSTORE_GITHUB) |
+ return ZipFile(BytesIO(blob)) |
+ |
+class GithubFileSystem(file_system.FileSystem): |
+ """FileSystem implementation which fetches resources from github. |
+ """ |
+ def __init__(self, fetcher, memcache, blobstore): |
+ self._fetcher = fetcher |
+ self._memcache = memcache |
+ self._blobstore = blobstore |
+ self._version = self.Stat(ZIP_KEY).version |
+ self._GetZip(self._version) |
+ |
+ def _GetZip(self, version): |
+ blob = self._blobstore.Get(_MakeKey(version), blobstore.BLOBSTORE_GITHUB) |
+ if blob is not None: |
+ self._zip_file = Future(value=ZipFile(BytesIO(blob))) |
+ else: |
+ self._zip_file = Future(delegate=_AsyncFetchFutureZip(self._fetcher, |
+ self._blobstore, |
+ version, |
+ self._version)) |
+ self._version = version |
+ |
+ def _ReadFile(self, path): |
+ zip_file = self._zip_file.Get() |
+ prefix = zip_file.namelist()[0][:-1] |
+ return zip_file.read(prefix + path) |
+ |
+ def _ListDir(self, path): |
+ filenames = self._zip_file.Get().namelist() |
+ # Take out parent directory name (GoogleChrome-chrome-app-samples-c78a30f) |
+ filenames = [f[len(filenames[0]) - 1:] for f in filenames] |
+ # Remove the path of the directory we're listing from the filenames. |
+ filenames = [f[len(path):] for f in filenames |
+ if f != path and f.startswith(path)] |
+ # Remove all files not directly in this directory. |
+ return [f for f in filenames if f[:-1].count('/') == 0] |
+ |
+ def Read(self, paths, binary=False): |
+ version = self.Stat(ZIP_KEY).version |
+ if version != self._version: |
+ self._GetZip(version) |
+ result = {} |
+ for path in paths: |
+ if path.endswith('/'): |
+ result[path] = self._ListDir(path) |
+ else: |
+ result[path] = self._ReadFile(path) |
+ return Future(value=result) |
+ |
+ def Stat(self, path): |
+ version = self._memcache.Get(path, memcache.MEMCACHE_GITHUB_STAT) |
+ if version is not None: |
+ return self.StatInfo(version) |
+ version = json.loads( |
+ self._fetcher.Fetch('commits/HEAD').content)['commit']['tree']['sha'] |
+ self._memcache.Set(path, version, memcache.MEMCACHE_GITHUB_STAT) |
+ return self.StatInfo(version) |