OLD | NEW |
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 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 def list_dir(json_data): | 108 def list_dir(json_data): |
109 return [e['name'] for e in _ParseGitilesJson(json_data)['entries']] | 109 entries = _ParseGitilesJson(json_data)['entries'] |
| 110 return [e['name'] + ('/' if e['type'] == 'tree' else '') for e in entries] |
110 | 111 |
111 def fixup_url_format(path): | 112 def fixup_url_format(path): |
112 # By default, Gitiles URLs display resources in HTML. To get resources | 113 # By default, Gitiles URLs display resources in HTML. To get resources |
113 # suitable for our consumption, a '?format=' string must be appended to | 114 # 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 | 115 # the URL. The format may be one of 'JSON' or 'TEXT' for directory or |
115 # text resources, respectively. | 116 # text resources, respectively. |
116 return path + (_JSON_FORMAT if IsDirectory(path) else _TEXT_FORMAT) | 117 return path + (_JSON_FORMAT if IsDirectory(path) else _TEXT_FORMAT) |
117 | 118 |
118 # A list of tuples of the form (path, Future). | 119 # A list of tuples of the form (path, Future). |
119 fetches = ((path, self._FetchAsync(fixup_url_format(path))) | 120 fetches = ((path, self._FetchAsync(fixup_url_format(path))) |
120 for path in paths) | 121 for path in paths) |
121 | 122 |
122 def parse_contents(results): | 123 def parse_contents(results): |
123 value = {} | 124 value = {} |
124 for path, content in izip(paths, results): | 125 for path, content in izip(paths, results): |
125 if content is None: | 126 if content is None: |
126 continue | 127 continue |
127 # Gitiles encodes text content in base64 (see | 128 # Gitiles encodes text content in base64 (see |
128 # http://tools.ietf.org/html/rfc4648 for info about base64). | 129 # http://tools.ietf.org/html/rfc4648 for info about base64). |
129 value[path] = (list_dir if IsDirectory(path) else b64decode)(content) | 130 value[path] = (list_dir if IsDirectory(path) else b64decode)(content) |
130 return value | 131 return value |
131 return All(self._ResolveFetchContent(path, future, skip_not_found) | 132 return All(self._ResolveFetchContent(path, future, skip_not_found) |
132 for path, future in fetches).Then(parse_contents) | 133 for path, future in fetches).Then(parse_contents) |
133 | 134 |
134 def Refresh(self): | 135 def Refresh(self): |
135 return Future(value=()) | 136 return Future(value=()) |
136 | 137 |
137 @memoize | 138 @memoize |
138 def GetCommitID(self): | 139 def _GetCommitInfo(self, key): |
139 '''Returns a future that resolves to the commit ID for this branch. | 140 '''Retrieves a value from the Gitiles JSON commit view. |
140 ''' | 141 ''' |
141 # Commit information for a branch is obtained by appending '?format=JSON' | 142 # Commit information for a branch is obtained by appending '?format=JSON' |
142 # to the branch URL. Note that '<gitiles_url>/<branch>?format=JSON' is | 143 # to the branch URL. Note that '<gitiles_url>/<branch>?format=JSON' is |
143 # different from '<gitiles_url>/<branch>/?format=JSON': the latter serves | 144 # different from '<gitiles_url>/<branch>/?format=JSON': the latter serves |
144 # the root directory JSON content, whereas the former serves the branch | 145 # the root directory JSON content, whereas the former serves the branch |
145 # commit info JSON content. | 146 # commit info JSON content. |
146 fetch_future = self._fetcher.FetchAsync(self._base_url + _JSON_FORMAT) | 147 fetch_future = self._fetcher.FetchAsync(self._base_url + _JSON_FORMAT) |
147 content_future = self._ResolveFetchContent(self._base_url, fetch_future) | 148 content_future = self._ResolveFetchContent(self._base_url, fetch_future) |
148 # The commit info JSON looks like: | 149 # The commit info JSON looks like: |
149 # | 150 # |
150 # { | 151 # { |
151 # "commit": "8fd578e1a7b142cd10a4387861f05fb9459b69e2", # Commit ID. | 152 # "commit": "8fd578e1a7b142cd10a4387861f05fb9459b69e2", # Commit ID. |
152 # "tree": "3ade65d8a91eadd009a6c9feea8f87db2c528a53", # Tree ID. | 153 # "tree": "3ade65d8a91eadd009a6c9feea8f87db2c528a53", # Tree ID. |
| 154 # # Previous Commit ID. |
| 155 # "parents": ["a477c787fe847ae0482329f69b39ce0fde047359"], |
153 # "author": {...}, | 156 # "author": {...}, |
154 # "committer": {...}, | 157 # "committer": {...}, |
155 # "message": <codereview message>, | 158 # "message": <codereview message>, |
156 # ... | 159 # ... |
157 # } | 160 # } |
158 return content_future.Then(lambda json: _ParseGitilesJson(json)['commit']) | 161 return content_future.Then(lambda json: _ParseGitilesJson(json)[key]) |
| 162 |
| 163 def GetCommitID(self): |
| 164 '''Returns a future that resolves to the commit ID for this branch. |
| 165 ''' |
| 166 return self._GetCommitInfo('commit') |
| 167 |
| 168 def GetPreviousCommitID(self): |
| 169 '''Returns a future that resolves to the previous commit ID for this branch. |
| 170 ''' |
| 171 return self._GetCommitInfo('parents').Then(lambda parents: parents[0]) |
159 | 172 |
160 def Stat(self, path): | 173 def Stat(self, path): |
161 return self.StatAsync(path).Get() | 174 return self.StatAsync(path).Get() |
162 | 175 |
163 def StatAsync(self, path): | 176 def StatAsync(self, path): |
164 dir_, filename = posixpath.split(path) | 177 dir_, filename = posixpath.split(path) |
165 def stat(content): | 178 def stat(content): |
166 stat_info = _CreateStatInfo(content) | 179 stat_info = _CreateStatInfo(content) |
167 if stat_info.version is None: | 180 if stat_info.version is None: |
168 raise FileSystemError('Failed to find version of dir %s' % dir_) | 181 raise FileSystemError('Failed to find version of dir %s' % dir_) |
169 if IsDirectory(path): | 182 if IsDirectory(path): |
170 return stat_info | 183 return stat_info |
171 if filename not in stat_info.child_versions: | 184 if filename not in stat_info.child_versions: |
172 raise FileNotFoundError( | 185 raise FileNotFoundError( |
173 '%s from %s was not in child versions for Stat' % (filename, path)) | 186 '%s from %s was not in child versions for Stat' % (filename, path)) |
174 return StatInfo(stat_info.child_versions[filename]) | 187 return StatInfo(stat_info.child_versions[filename]) |
175 fetch_future = self._FetchAsync(ToDirectory(dir_) + _JSON_FORMAT) | 188 fetch_future = self._FetchAsync(ToDirectory(dir_) + _JSON_FORMAT) |
176 return self._ResolveFetchContent(path, fetch_future).Then(stat) | 189 return self._ResolveFetchContent(path, fetch_future).Then(stat) |
177 | 190 |
178 def GetIdentity(self): | 191 def GetIdentity(self): |
179 return '@'.join((self.__class__.__name__, | 192 return '@'.join((self.__class__.__name__, |
180 StringIdentity(self._commit or self._branch))) | 193 StringIdentity(self._commit or self._branch))) |
OLD | NEW |