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

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

Issue 498503002: Docserver: Fixes for GitilesFileSystem (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 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
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 base64 import b64decode 5 from base64 import b64decode
6 from itertools import izip 6 from itertools import izip
7 import json 7 import json
8 import posixpath 8 import posixpath
9 import traceback 9 import traceback
10 10
11 from appengine_url_fetcher import AppEngineUrlFetcher 11 from appengine_url_fetcher import AppEngineUrlFetcher
12 from appengine_wrappers import IsDownloadError 12 from appengine_wrappers import IsDownloadError
13 from docs_server_utils import StringIdentity 13 from docs_server_utils import StringIdentity
14 from file_system import (FileNotFoundError, 14 from file_system import (FileNotFoundError,
15 FileSystem, 15 FileSystem,
16 FileSystemError, 16 FileSystemError,
17 StatInfo) 17 StatInfo)
18 from future import All, Future 18 from future import All, Future
19 from path_util import AssertIsValid, IsDirectory, SplitParent, ToDirectory 19 from path_util import AssertIsValid, IsDirectory, ToDirectory
20 from third_party.json_schema_compiler.memoize import memoize 20 from third_party.json_schema_compiler.memoize import memoize
21 from url_constants import GITILES_BASE, GITILES_BRANCH_BASE 21 from url_constants import GITILES_BASE, GITILES_BRANCH_BASE
22 22
23 23
24 _JSON_FORMAT = '?format=JSON' 24 _JSON_FORMAT = '?format=JSON'
25 _TEXT_FORMAT = '?format=TEXT' 25 _TEXT_FORMAT = '?format=TEXT'
26 26
27 27
28 def _ParseGitilesJson(json_data): 28 def _ParseGitilesJson(json_data):
29 '''json.loads with fix-up for non-executable JSON. Use this to parse any JSON 29 '''json.loads with fix-up for non-executable JSON. Use this to parse any JSON
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 # { 97 # {
98 # "id": "12a5464de48d2c46bc0b2dc78fafed75aab554fa", # The tree ID. 98 # "id": "12a5464de48d2c46bc0b2dc78fafed75aab554fa", # The tree ID.
99 # "entries": [ 99 # "entries": [
100 # { 100 # {
101 # "mode": 33188, 101 # "mode": 33188,
102 # "type": "blob", 102 # "type": "blob",
103 # "id": "ab971ca447bc4bce415ed4498369e00164d91cb6", # File ID. 103 # "id": "ab971ca447bc4bce415ed4498369e00164d91cb6", # File ID.
104 # "name": ".gitignore" 104 # "name": ".gitignore"
105 # }, 105 # },
106 # ... 106 # ...
107 # ]
107 # } 108 # }
108 def list_dir(json_data): 109 def list_dir(json_data):
109 return [e['name'] for e in _ParseGitilesJson(json_data)['entries']] 110 entries = _ParseGitilesJson(json_data).get('entries', [])
111 return [e['name'] + ('/' if e['type'] == 'tree' else '') for e in entries]
110 112
111 def fixup_url_format(path): 113 def fixup_url_format(path):
112 # By default, Gitiles URLs display resources in HTML. To get resources 114 # By default, Gitiles URLs display resources in HTML. To get resources
113 # suitable for our consumption, a '?format=' string must be appended to 115 # suitable for our consumption, a '?format=' string must be appended to
114 # the URL. The format may be one of 'JSON' or 'TEXT' for directory or 116 # the URL. The format may be one of 'JSON' or 'TEXT' for directory or
115 # text resources, respectively. 117 # text resources, respectively.
116 return path + (_JSON_FORMAT if IsDirectory(path) else _TEXT_FORMAT) 118 return path + (_JSON_FORMAT if IsDirectory(path) else _TEXT_FORMAT)
117 119
118 # A list of tuples of the form (path, Future). 120 # A list of tuples of the form (path, Future).
119 fetches = ((path, self._FetchAsync(fixup_url_format(path))) 121 fetches = ((path, self._FetchAsync(fixup_url_format(path)))
120 for path in paths) 122 for path in paths)
121 123
122 def parse_contents(results): 124 def parse_contents(results):
123 value = {} 125 value = {}
124 for path, content in izip(paths, results): 126 for path, content in izip(paths, results):
125 if content is None: 127 if content is None:
126 continue 128 continue
127 # Gitiles encodes text content in base64 (see 129 # Gitiles encodes text content in base64 (see
128 # http://tools.ietf.org/html/rfc4648 for info about base64). 130 # http://tools.ietf.org/html/rfc4648 for info about base64).
129 value[path] = (list_dir if IsDirectory(path) else b64decode)(content) 131 value[path] = (list_dir if IsDirectory(path) else b64decode)(content)
130 return value 132 return value
131 return All(self._ResolveFetchContent(path, future, skip_not_found) 133 return All(self._ResolveFetchContent(path, future, skip_not_found)
132 for path, future in fetches).Then(parse_contents) 134 for path, future in fetches).Then(parse_contents)
133 135
134 def Refresh(self): 136 def Refresh(self):
135 return Future(value=()) 137 return Future(value=())
136 138
137 @memoize 139 @memoize
138 def GetCommitID(self): 140 def _GetCommitInfo(self, key):
139 '''Returns a future that resolves to the commit ID for this branch. 141 '''Gets the commit information specified by |key|.
142
143 The JSON view for commit info looks like:
144 {
145 "commit": "8fd578e1a7b142cd10a4387861f05fb9459b69e2", # Commit ID.
146 "tree": "3ade65d8a91eadd009a6c9feea8f87db2c528a53", # Tree ID.
147 "parents": [
148 "a477c787fe847ae0482329f69b39ce0fde047359" # Previous commit ID.
149 ],
150 "author": {
151 "name": "...",
152 "email": "...",
153 "time": "Tue Aug 12 17:17:21 2014"
154 },
155 "committer": {
156 "name": "...",
157 "email": "...",
158 "time": "Tue Aug 12 17:18:28 2014"
159 },
160 "message": "...",
161 "tree_diff": [...]
162 }
140 ''' 163 '''
141 # Commit information for a branch is obtained by appending '?format=JSON' 164 # Commit information for a branch is obtained by appending '?format=JSON'
142 # to the branch URL. Note that '<gitiles_url>/<branch>?format=JSON' is 165 # to the branch URL. Note that '<gitiles_url>/<branch>?format=JSON' is
143 # different from '<gitiles_url>/<branch>/?format=JSON': the latter serves 166 # different from '<gitiles_url>/<branch>/?format=JSON': the latter serves
144 # the root directory JSON content, whereas the former serves the branch 167 # the root directory JSON content, whereas the former serves the branch
145 # commit info JSON content. 168 # commit info JSON content.
146 fetch_future = self._fetcher.FetchAsync(self._base_url + _JSON_FORMAT) 169 fetch_future = self._fetcher.FetchAsync(self._base_url + _JSON_FORMAT)
147 content_future = self._ResolveFetchContent(self._base_url, fetch_future) 170 content_future = self._ResolveFetchContent(self._base_url, fetch_future)
148 # The commit info JSON looks like: 171 return content_future.Then(lambda json: _ParseGitilesJson(json)[key])
149 # 172
150 # { 173 def GetCommitID(self):
151 # "commit": "8fd578e1a7b142cd10a4387861f05fb9459b69e2", # Commit ID. 174 '''Returns a future that resolves to the commit ID for this branch.
152 # "tree": "3ade65d8a91eadd009a6c9feea8f87db2c528a53", # Tree ID. 175 '''
153 # "author": {...}, 176 return self._GetCommitInfo('commit')
154 # "committer": {...},
155 # "message": <codereview message>,
156 # ...
157 # }
158 return content_future.Then(lambda json: _ParseGitilesJson(json)['commit'])
159 177
160 def Stat(self, path): 178 def Stat(self, path):
161 return self.StatAsync(path).Get() 179 return self.StatAsync(path).Get()
162 180
163 def StatAsync(self, path): 181 def StatAsync(self, path):
164 dir_, filename = posixpath.split(path) 182 dir_, filename = posixpath.split(path)
165 def stat(content): 183 def stat(content):
166 stat_info = _CreateStatInfo(content) 184 stat_info = _CreateStatInfo(content)
167 if stat_info.version is None: 185 if stat_info.version is None:
168 raise FileSystemError('Failed to find version of dir %s' % dir_) 186 raise FileSystemError('Failed to find version of dir %s' % dir_)
169 if IsDirectory(path): 187 if IsDirectory(path):
170 return stat_info 188 return stat_info
171 if filename not in stat_info.child_versions: 189 if filename not in stat_info.child_versions:
172 raise FileNotFoundError( 190 raise FileNotFoundError(
173 '%s from %s was not in child versions for Stat' % (filename, path)) 191 '%s from %s was not in child versions for Stat' % (filename, path))
174 return StatInfo(stat_info.child_versions[filename]) 192 return StatInfo(stat_info.child_versions[filename])
175 fetch_future = self._FetchAsync(ToDirectory(dir_) + _JSON_FORMAT) 193 fetch_future = self._FetchAsync(ToDirectory(dir_) + _JSON_FORMAT)
176 return self._ResolveFetchContent(path, fetch_future).Then(stat) 194 return self._ResolveFetchContent(path, fetch_future).Then(stat)
177 195
178 def GetIdentity(self): 196 def GetIdentity(self):
179 return '@'.join((self.__class__.__name__, 197 # NOTE: Do not use commit information to create the string identity.
180 StringIdentity(self._commit or self._branch))) 198 # Doing so will mess up caching.
199 if self._commit is None and self._branch != 'master':
200 str_id = GITILES_BRANCH_BASE
201 else:
202 str_id = GITILES_BASE
203 return '@'.join((self.__class__.__name__, StringIdentity(str_id)))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698