Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Unified Diff: chrome/common/extensions/docs/server2/gcs_file_system.py

Issue 1151283007: Docserver overhaul: Gitiles away from me. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/common/extensions/docs/server2/gcs_file_system.py
diff --git a/chrome/common/extensions/docs/server2/gcs_file_system.py b/chrome/common/extensions/docs/server2/gcs_file_system.py
index 36f28fa08f33f2d3ce73cfa4a2f0d86fa0bc7ee3..62c21be73faed035957416a6a90c843c7d79e39c 100644
--- a/chrome/common/extensions/docs/server2/gcs_file_system.py
+++ b/chrome/common/extensions/docs/server2/gcs_file_system.py
@@ -2,19 +2,19 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-from third_party.cloudstorage import cloudstorage_api
-from third_party.cloudstorage import common
-from third_party.cloudstorage import errors
+import json
+import logging
+import posixpath
+import traceback
+import urllib
from docs_server_utils import StringIdentity
+from environment_wrappers import CreateUrlFetcher
Ken Rockot(use gerrit already) 2015/05/26 00:26:24 Unfortunately cloudstorage_api only works from App
from file_system import FileSystem, FileNotFoundError, StatInfo
from future import Future
from path_util import (
AssertIsDirectory, AssertIsFile, AssertIsValid, IsDirectory, Join)
-import logging
-import traceback
-
# See gcs_file_system_provider.py for documentation on using Google Cloud
# Storage as a filesystem.
@@ -25,76 +25,32 @@ import traceback
# Name of the file containing the Git hash of the latest commit sync'ed
# to Cloud Storage. This file is generated by the Github->GCS sync script
-LAST_COMMIT_HASH_FILENAME = '.__lastcommit.txt'
-
-def _ReadFile(filename):
- AssertIsFile(filename)
- try:
- with cloudstorage_api.open('/' + filename, 'r') as f:
- return f.read()
- except errors.Error:
- raise FileNotFoundError('Read failed for %s: %s' % (filename,
- traceback.format_exc()))
-
-def _ListDir(dir_name, recursive=False):
- AssertIsDirectory(dir_name)
- try:
- # The listbucket method uses a prefix approach to simulate hierarchy.
- # Calling it with the "delimiter" argument set to '/' gets only files
- # directly inside the directory, not all recursive content.
- delimiter = None if recursive else '/'
- files = cloudstorage_api.listbucket('/' + dir_name, delimiter=delimiter)
- return [os_path.filename.lstrip('/')[len(dir_name):] for os_path in files]
- except errors.Error:
- raise FileNotFoundError('cloudstorage.listbucket failed for %s: %s' %
- (dir_name, traceback.format_exc()))
-
-def _CreateStatInfo(bucket, path):
- full_path = Join(bucket, path)
- last_commit_file = Join(bucket, LAST_COMMIT_HASH_FILENAME)
- try:
- last_commit = _ReadFile(last_commit_file)
- if IsDirectory(full_path):
- child_versions = dict((filename, last_commit)
- for filename in _ListDir(full_path))
- else:
- child_versions = None
- return StatInfo(last_commit, child_versions)
- except (TypeError, errors.Error):
- raise FileNotFoundError('cloudstorage.stat failed for %s: %s' % (path,
- traceback.format_exc()))
+_LAST_COMMIT_HASH_FILENAME = '.__lastcommit.txt'
+
+
+# Base URL for GCS requests.
+_STORAGE_API_BASE = 'https://www.googleapis.com/storage/v1'
+
class CloudStorageFileSystem(FileSystem):
'''FileSystem implementation which fetches resources from Google Cloud
Storage.
'''
- def __init__(self, bucket, debug_access_token=None, debug_bucket_prefix=None):
+ def __init__(self, bucket, debug_bucket_prefix=None):
self._bucket = bucket
- if debug_access_token:
- logging.debug('gcs: using debug access token: %s' % debug_access_token)
- common.set_access_token(debug_access_token)
- if debug_bucket_prefix:
- logging.debug('gcs: prefixing all bucket names with %s' %
- debug_bucket_prefix)
- self._bucket = debug_bucket_prefix + self._bucket
+ self._access_token = None
+ self._last_commit_hash = None
AssertIsValid(self._bucket)
def Read(self, paths, skip_not_found=False):
def resolve():
- try:
- result = {}
- for path in paths:
- full_path = Join(self._bucket, path)
- logging.debug('gcs: requested path "%s", reading "%s"' %
- (path, full_path))
- if IsDirectory(path):
- result[path] = _ListDir(full_path)
- else:
- result[path] = _ReadFile(full_path)
- return result
- except errors.AuthorizationError:
- self._warnAboutAuthError()
- raise
+ result = {}
+ for path in paths:
+ if IsDirectory(path):
+ result[path] = self._ListDir(path)
+ else:
+ result[path] = self._ReadFile(path)
+ return result
return Future(callback=resolve)
@@ -103,25 +59,62 @@ class CloudStorageFileSystem(FileSystem):
def Stat(self, path):
AssertIsValid(path)
- try:
- return _CreateStatInfo(self._bucket, path)
- except errors.AuthorizationError:
- self._warnAboutAuthError()
- raise
+ return self._CreateStatInfo(path)
def GetIdentity(self):
return '@'.join((self.__class__.__name__, StringIdentity(self._bucket)))
+ def _CreateStatInfo(self, path):
+ if not self._last_commit_hash:
+ self._last_commit_hash = self._ReadFile(_LAST_COMMIT_HASH_FILENAME)
+ if IsDirectory(path):
+ child_versions = dict((filename, self._last_commit_hash)
+ for filename in self._ListDir(path))
+ else:
+ child_versions = None
+ return StatInfo(self._last_commit_hash, child_versions)
+
+ def _ReadFile(self, path):
+ AssertIsFile(path)
+ return self._FetchObjectData(path)
+
+ def _ListDir(self, path, recursive=False):
+ AssertIsDirectory(path)
+ # The listbucket method uses a prefix approach to simulate hierarchy.
+ # Calling it with the "delimiter" argument set to '/' gets only files
+ # directly inside the directory, not all recursive content.
+
+ # Subdirectories are returned in the 'prefixes' property, but they are
+ # full paths from the root. This plucks off the name of the leaf with a
+ # trailing slash.
+ def path_from_prefix(prefix):
+ return posixpath.split(posixpath.split(prefix)[0])[1] + '/'
+
+ query = { 'prefix': path }
+ if not recursive:
+ query['delimiter'] = '/'
+ root_object = json.loads(self._FetchObject('', query=query))
+ files = [posixpath.basename(o['name'])
+ for o in root_object.get('items', [])]
+ dirs = [path_from_prefix(prefix)
+ for prefix in root_object.get('prefixes', [])]
+ return files + dirs
+
+ def _FetchObject(self, path, query={}):
+ # Escape the path, including slashes.
+ url_path = urllib.quote(path.lstrip('/'), safe='')
+ fetcher = CreateUrlFetcher()
+ object_url = '%s/b/%s/o/%s' % (_STORAGE_API_BASE, self._bucket, url_path)
+ response = fetcher.Fetch(object_url, query=query)
+ if response.status_code != 200:
+ raise FileNotFoundError(
+ 'Path %s not found in GCS bucket %s' % (path, self._bucket))
+ return response.content
+
+ def _FetchObjectData(self, path, query={}):
+ q = query.copy()
+ q.update({ 'alt': 'media' })
+ return self._FetchObject(path, query=q)
+
def __repr__(self):
return 'CloudStorageFileSystem(%s)' % self._bucket
-
- def _warnAboutAuthError(self):
Ken Rockot(use gerrit already) 2015/05/26 00:26:24 Auth is no longer required. The github repos are p
- logging.warn(('Authentication error on Cloud Storage. Check if your'
- ' appengine project has permissions to Read the GCS'
- ' buckets. If you are running a local appengine server,'
- ' you need to set an access_token in'
- ' local_debug/gcs_debug.conf.'
- ' Remember that this token expires in less than 10'
- ' minutes, so keep it updated. See'
- ' gcs_file_system_provider.py for instructions.'));
- logging.debug(traceback.format_exc())

Powered by Google App Engine
This is Rietveld 408576698