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

Side by Side Diff: chrome/common/extensions/docs/server2/gcs_file_system.py

Issue 165353004: Docserver: Fix invalid path usage in CloudStorageFileSystem. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 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 from third_party.cloudstorage import cloudstorage_api 5 from third_party.cloudstorage import cloudstorage_api
6 from third_party.cloudstorage import common 6 from third_party.cloudstorage import common
7 from third_party.cloudstorage import errors 7 from third_party.cloudstorage import errors
8 8
9 from docs_server_utils import StringIdentity 9 from docs_server_utils import StringIdentity
10 from file_system import FileSystem, FileNotFoundError, StatInfo 10 from file_system import FileSystem, FileNotFoundError, StatInfo
11 from future import Gettable, Future 11 from future import Gettable, Future
12 from path_util import (
13 AssertIsDirectory, AssertIsFile, AssertIsValid, IsDirectory, Join)
12 14
13 import logging 15 import logging
14 import traceback 16 import traceback
15 17
18
19 # See gcs_file_system_provider.py for documentation on using Google Cloud
20 # Storage as a filesystem.
21 #
22 # Note that the path requirements for GCS are different for the docserver;
23 # GCS requires that paths start with a /, we require that they don't.
24
25
16 # Name of the file containing the Git hash of the latest commit sync'ed 26 # Name of the file containing the Git hash of the latest commit sync'ed
17 # to Cloud Storage. This file is generated by the Github->GCS sync script 27 # to Cloud Storage. This file is generated by the Github->GCS sync script
18 LAST_COMMIT_HASH_FILENAME='.__lastcommit.txt' 28 LAST_COMMIT_HASH_FILENAME = '.__lastcommit.txt'
19 29
20 '''See gcs_file_system_provider.py for documentation on using Google Cloud
21 Storage as a filesystem.
22 '''
23 def _ReadFile(filename): 30 def _ReadFile(filename):
31 AssertIsFile(filename)
24 try: 32 try:
25 with cloudstorage_api.open(filename, 'r') as f: 33 with cloudstorage_api.open('/' + filename, 'r') as f:
26 return f.read() 34 return f.read()
27 except errors.Error: 35 except errors.Error:
28 raise FileNotFoundError('Read failed for %s: %s' % (filename, 36 raise FileNotFoundError('Read failed for %s: %s' % (filename,
29 traceback.format_exc())) 37 traceback.format_exc()))
30 38
31 def _ListDir(dir_name): 39 def _ListDir(dir_name):
40 AssertIsDirectory(dir_name)
32 try: 41 try:
33 files = cloudstorage_api.listbucket(dir_name) 42 files = cloudstorage_api.listbucket('/' + dir_name)
34 return [os_path.filename for os_path in files] 43 return [os_path.filename.lstrip('/') for os_path in files]
35 except errors.Error: 44 except errors.Error:
36 raise FileNotFoundError('cloudstorage.listbucket failed for %s: %s' % 45 raise FileNotFoundError('cloudstorage.listbucket failed for %s: %s' %
37 (dir_name, traceback.format_exc())) 46 (dir_name, traceback.format_exc()))
38 47
39 def _CreateStatInfo(bucket, path): 48 def _CreateStatInfo(bucket, path):
40 bucket = '/%s' % bucket 49 full_path = Join(bucket, path)
41 full_path = '/'.join( (bucket, path.lstrip('/')) ) 50 last_commit_file = Join(bucket, LAST_COMMIT_HASH_FILENAME)
42 last_commit_file = '%s/%s' % (bucket, LAST_COMMIT_HASH_FILENAME)
43 try: 51 try:
44 last_commit = _ReadFile(last_commit_file) 52 last_commit = _ReadFile(last_commit_file)
45 if full_path.endswith('/'): 53 if IsDirectory(full_path):
46 child_versions = dict() 54 child_versions = dict()
47 # Fetching stats for all files under full_path, recursively. The 55 # Fetching stats for all files under full_path, recursively. The
48 # listbucket method uses a prefix approach to simulate hierarchy, 56 # listbucket method uses a prefix approach to simulate hierarchy,
49 # but calling it without the "delimiter" argument searches for prefix, 57 # but calling it without the "delimiter" argument searches for prefix,
50 # which means, for directories, everything beneath it. 58 # which means, for directories, everything beneath it.
51 for _file in cloudstorage_api.listbucket(full_path): 59 for _file in cloudstorage_api.listbucket('/' + full_path):
52 filename = _file.filename[len(full_path):] 60 filename = _file.filename.lstrip('/')[len(full_path):]
53 child_versions[filename] = last_commit 61 child_versions[filename] = last_commit
54 else: 62 else:
55 child_versions = None 63 child_versions = None
56 return StatInfo(last_commit, child_versions) 64 return StatInfo(last_commit, child_versions)
57 except (TypeError, errors.Error): 65 except (TypeError, errors.Error):
58 raise FileNotFoundError('cloudstorage.stat failed for %s: %s' % (path, 66 raise FileNotFoundError('cloudstorage.stat failed for %s: %s' % (path,
59 traceback.format_exc())) 67 traceback.format_exc()))
60 68
61 class CloudStorageFileSystem(FileSystem): 69 class CloudStorageFileSystem(FileSystem):
62 '''FileSystem implementation which fetches resources from Google Cloud 70 '''FileSystem implementation which fetches resources from Google Cloud
63 Storage. 71 Storage.
64 ''' 72 '''
65 def __init__(self, bucket, debug_access_token=None, debug_bucket_prefix=None): 73 def __init__(self, bucket, debug_access_token=None, debug_bucket_prefix=None):
66 self._bucket = bucket 74 self._bucket = bucket
67 if debug_access_token: 75 if debug_access_token:
68 logging.debug('gcs: using debug access token: %s' % debug_access_token) 76 logging.debug('gcs: using debug access token: %s' % debug_access_token)
69 common.set_access_token(debug_access_token) 77 common.set_access_token(debug_access_token)
70 if debug_bucket_prefix: 78 if debug_bucket_prefix:
71 logging.debug('gcs: prefixing all bucket names with %s' % 79 logging.debug('gcs: prefixing all bucket names with %s' %
72 debug_bucket_prefix) 80 debug_bucket_prefix)
73 self._bucket = debug_bucket_prefix + self._bucket 81 self._bucket = debug_bucket_prefix + self._bucket
82 AssertIsValid(self._bucket)
74 83
75 def Read(self, paths): 84 def Read(self, paths):
76 def resolve(): 85 def resolve():
77 try: 86 try:
78 result = {} 87 result = {}
79 for path in paths: 88 for path in paths:
80 full_path = '/%s/%s' % (self._bucket, path.lstrip('/')) 89 full_path = Join(self._bucket, path)
81 logging.debug('gcs: requested path %s, reading %s' % 90 logging.debug('gcs: requested path "%s", reading "%s"' %
82 (path, full_path)) 91 (path, full_path))
83 if path == '' or path.endswith('/'): 92 if IsDirectory(path):
84 result[path] = _ListDir(full_path) 93 result[path] = _ListDir(full_path)
85 else: 94 else:
86 result[path] = _ReadFile(full_path) 95 result[path] = _ReadFile(full_path)
87 return result 96 return result
88 except errors.AuthorizationError: 97 except errors.AuthorizationError:
89 self._warnAboutAuthError() 98 self._warnAboutAuthError()
90 raise 99 raise
91 100
92 return Future(delegate=Gettable(resolve)) 101 return Future(delegate=Gettable(resolve))
93 102
94 def Refresh(self): 103 def Refresh(self):
95 return Future(value=()) 104 return Future(value=())
96 105
97 def Stat(self, path): 106 def Stat(self, path):
107 AssertIsValid(path)
98 try: 108 try:
99 return _CreateStatInfo(self._bucket, path) 109 return _CreateStatInfo(self._bucket, path)
100 except errors.AuthorizationError: 110 except errors.AuthorizationError:
101 self._warnAboutAuthError() 111 self._warnAboutAuthError()
102 raise 112 raise
103 113
104 def GetIdentity(self): 114 def GetIdentity(self):
105 return '@'.join((self.__class__.__name__, StringIdentity(self._bucket))) 115 return '@'.join((self.__class__.__name__, StringIdentity(self._bucket)))
106 116
107 def __repr__(self): 117 def __repr__(self):
108 return 'LocalFileSystem(%s)' % self._bucket 118 return 'LocalFileSystem(%s)' % self._bucket
109 119
110 def _warnAboutAuthError(self): 120 def _warnAboutAuthError(self):
111 logging.warn(('Authentication error on Cloud Storage. Check if your' 121 logging.warn(('Authentication error on Cloud Storage. Check if your'
112 ' appengine project has permissions to Read the GCS' 122 ' appengine project has permissions to Read the GCS'
113 ' buckets. If you are running a local appengine server,' 123 ' buckets. If you are running a local appengine server,'
114 ' you need to set an access_token in' 124 ' you need to set an access_token in'
115 ' local_debug/gcs_debug.conf.' 125 ' local_debug/gcs_debug.conf.'
116 ' Remember that this token expires in less than 10' 126 ' Remember that this token expires in less than 10'
117 ' minutes, so keep it updated. See' 127 ' minutes, so keep it updated. See'
118 ' gcs_file_system_provider.py for instructions.')); 128 ' gcs_file_system_provider.py for instructions.'));
119 logging.debug(traceback.format_exc()) 129 logging.debug(traceback.format_exc())
OLDNEW
« no previous file with comments | « chrome/common/extensions/docs/server2/file_system.py ('k') | chrome/common/extensions/docs/server2/path_util.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698