| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import json | 5 import json |
| 6 import os | 6 import os |
| 7 | 7 |
| 8 import appengine_blobstore as blobstore | 8 import appengine_blobstore as blobstore |
| 9 import object_store | 9 import object_store |
| 10 from file_system import FileSystem, StatInfo | 10 from file_system import FileSystem, StatInfo |
| 11 from StringIO import StringIO | 11 from StringIO import StringIO |
| 12 from future import Future | 12 from future import Future |
| 13 from zipfile import ZipFile | 13 from zipfile import ZipFile |
| 14 | 14 |
| 15 ZIP_KEY = 'zipball' | 15 ZIP_KEY = 'zipball' |
| 16 | 16 |
| 17 def _MakeKey(version): | 17 def _MakeKey(version): |
| 18 return ZIP_KEY + '.' + str(version) | 18 return ZIP_KEY + '.' + str(version) |
| 19 | 19 |
| 20 class _AsyncFetchFutureZip(object): | 20 class _AsyncFetchFutureZip(object): |
| 21 def __init__(self, fetcher, blobstore, new_version, old_version): | 21 def __init__(self, fetcher, blobstore, key_to_set, key_to_delete=None): |
| 22 self._fetch = fetcher.FetchAsync(ZIP_KEY) | 22 self._fetch = fetcher.FetchAsync(ZIP_KEY) |
| 23 self._blobstore = blobstore | 23 self._blobstore = blobstore |
| 24 self._new_version = new_version | 24 self._key_to_set = key_to_set |
| 25 self._old_version = old_version | 25 self._key_to_delete = key_to_delete |
| 26 | 26 |
| 27 def Get(self): | 27 def Get(self): |
| 28 blob = self._fetch.Get().content | 28 blob = self._fetch.Get().content |
| 29 self._blobstore.Set(_MakeKey(self._new_version), | 29 self._blobstore.Set(_MakeKey(self._key_to_set), |
| 30 blob, | 30 blob, |
| 31 blobstore.BLOBSTORE_GITHUB) | 31 blobstore.BLOBSTORE_GITHUB) |
| 32 self._blobstore.Delete(_MakeKey(self._old_version), | 32 if self._key_to_delete is not None: |
| 33 blobstore.BLOBSTORE_GITHUB) | 33 self._blobstore.Delete(_MakeKey(self._key_to_delete), |
| 34 blobstore.BLOBSTORE_GITHUB) |
| 34 return ZipFile(StringIO(blob)) | 35 return ZipFile(StringIO(blob)) |
| 35 | 36 |
| 36 class GithubFileSystem(FileSystem): | 37 class GithubFileSystem(FileSystem): |
| 37 """FileSystem implementation which fetches resources from github. | 38 """FileSystem implementation which fetches resources from github. |
| 38 """ | 39 """ |
| 39 def __init__(self, fetcher, object_store, blobstore): | 40 def __init__(self, fetcher, object_store, blobstore): |
| 40 self._fetcher = fetcher | 41 self._fetcher = fetcher |
| 41 self._object_store = object_store | 42 self._object_store = object_store |
| 42 self._blobstore = blobstore | 43 self._blobstore = blobstore |
| 43 self._version = self.Stat(ZIP_KEY).version | 44 self._version = None |
| 44 self._GetZip(self._version) | 45 self._GetZip(self.Stat(ZIP_KEY).version) |
| 45 | 46 |
| 46 def _GetZip(self, version): | 47 def _GetZip(self, version): |
| 47 blob = self._blobstore.Get(_MakeKey(version), blobstore.BLOBSTORE_GITHUB) | 48 blob = self._blobstore.Get(_MakeKey(version), blobstore.BLOBSTORE_GITHUB) |
| 48 if blob is not None: | 49 if blob is not None: |
| 49 self._zip_file = Future(value=ZipFile(BytesIO(blob))) | 50 self._zip_file = Future(value=ZipFile(StringIO(blob))) |
| 50 else: | 51 else: |
| 51 self._zip_file = Future(delegate=_AsyncFetchFutureZip(self._fetcher, | 52 self._zip_file = Future( |
| 52 self._blobstore, | 53 delegate=_AsyncFetchFutureZip(self._fetcher, |
| 53 version, | 54 self._blobstore, |
| 54 self._version)) | 55 version, |
| 56 key_to_delete=self._version)) |
| 55 self._version = version | 57 self._version = version |
| 56 | 58 |
| 57 def _ReadFile(self, path): | 59 def _ReadFile(self, path): |
| 58 zip_file = self._zip_file.Get() | 60 zip_file = self._zip_file.Get() |
| 59 prefix = zip_file.namelist()[0][:-1] | 61 prefix = zip_file.namelist()[0][:-1] |
| 60 return zip_file.read(prefix + path) | 62 return zip_file.read(prefix + path) |
| 61 | 63 |
| 62 def _ListDir(self, path): | 64 def _ListDir(self, path): |
| 63 filenames = self._zip_file.Get().namelist() | 65 filenames = self._zip_file.Get().namelist() |
| 64 # Take out parent directory name (GoogleChrome-chrome-app-samples-c78a30f) | 66 # Take out parent directory name (GoogleChrome-chrome-app-samples-c78a30f) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 75 self._GetZip(version) | 77 self._GetZip(version) |
| 76 result = {} | 78 result = {} |
| 77 for path in paths: | 79 for path in paths: |
| 78 if path.endswith('/'): | 80 if path.endswith('/'): |
| 79 result[path] = self._ListDir(path) | 81 result[path] = self._ListDir(path) |
| 80 else: | 82 else: |
| 81 result[path] = self._ReadFile(path) | 83 result[path] = self._ReadFile(path) |
| 82 return Future(value=result) | 84 return Future(value=result) |
| 83 | 85 |
| 84 def Stat(self, path): | 86 def Stat(self, path): |
| 85 version = self._object_store.Get(path, object_store.GITHUB_STAT) | 87 version = self._object_store.Get(path, object_store.GITHUB_STAT).Get() |
| 86 if version is not None: | 88 if version is not None: |
| 87 return StatInfo(version) | 89 return StatInfo(version) |
| 88 version = json.loads( | 90 version = json.loads( |
| 89 self._fetcher.Fetch('commits/HEAD').content)['commit']['tree']['sha'] | 91 self._fetcher.Fetch('commits/HEAD').content)['commit']['tree']['sha'] |
| 90 self._object_store.Set(path, version, object_store.GITHUB_STAT) | 92 self._object_store.Set(path, version, object_store.GITHUB_STAT) |
| 91 return StatInfo(version) | 93 return StatInfo(version) |
| OLD | NEW |