Chromium Code Reviews| 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..9c6a963630448ee2c5082918fbb15c6d667468ec |
| --- /dev/null |
| +++ b/chrome/common/extensions/docs/server2/github_file_system.py |
| @@ -0,0 +1,84 @@ |
| +# 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_memcache as memcache |
| +import file_system |
| +from io import BytesIO |
| +from future import Future |
| +from zipfile import ZipFile |
| + |
| +ZIP_KEY = 'zipball' |
| + |
| +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): |
| + self._blobstore.Delete(ZIP_KEY, self._old_version) |
|
not at google - send to devlin
2012/08/07 01:35:38
Won't blobstore also need to be namespaced (like A
cduvall
2012/08/08 19:27:25
I think the version functions as a namespace for t
not at google - send to devlin
2012/08/09 07:52:36
sgtm. I don't know so much about the versions thou
|
| + blob = self._fetch.Get().content |
| + self._blobstore.Set(blob, ZIP_KEY, self._new_version) |
|
not at google - send to devlin
2012/08/07 01:35:38
Why are you versioning the zip files? Just curious
cduvall
2012/08/08 19:27:25
I versioned them so if there's an old zip hanging
not at google - send to devlin
2012/08/09 07:52:36
I made comment in the new version of the code.
|
| + 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._zip_file = None |
| + self._version = 0 |
| + |
| + def _GetZip(self, version): |
| + blob = self._blobstore.Get(ZIP_KEY, version) |
| + 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)) |
|
not at google - send to devlin
2012/08/07 01:35:38
Nice, doing this asynchronously is the way to go.
cduvall
2012/08/08 19:27:25
I'm starting the fetch when the GithubFileSystem i
not at google - send to devlin
2012/08/09 07:52:36
Well... I realised there actually isn't much advan
|
| + 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 True:#self._zip_file is None or version != self._version: |
|
not at google - send to devlin
2012/08/07 01:35:38
?
cduvall
2012/08/08 19:27:25
oops :)
|
| + 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) |