| 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 logging | 5 import logging |
| 6 import posixpath | 6 import posixpath |
| 7 import traceback | 7 import traceback |
| 8 import xml.dom.minidom as xml | 8 import xml.dom.minidom as xml |
| 9 from xml.parsers.expat import ExpatError | 9 from xml.parsers.expat import ExpatError |
| 10 | 10 |
| 11 from appengine_url_fetcher import AppEngineUrlFetcher | 11 from appengine_url_fetcher import AppEngineUrlFetcher |
| 12 from docs_server_utils import StringIdentity | 12 from docs_server_utils import StringIdentity |
| 13 from file_system import ( | 13 from file_system import ( |
| 14 FileNotFoundError, FileSystem, FileSystemError, StatInfo, ToUnicode) | 14 FileNotFoundError, FileSystem, FileSystemError, StatInfo, ToUnicode) |
| 15 from future import Future | 15 from future import Future |
| 16 import svn_constants | |
| 17 import url_constants | 16 import url_constants |
| 18 | 17 |
| 18 |
| 19 def _ParseHTML(html): | 19 def _ParseHTML(html): |
| 20 '''Unfortunately, the viewvc page has a stray </div> tag, so this takes care | 20 '''Unfortunately, the viewvc page has a stray </div> tag, so this takes care |
| 21 of all mismatched tags. | 21 of all mismatched tags. |
| 22 ''' | 22 ''' |
| 23 try: | 23 try: |
| 24 return xml.parseString(html) | 24 return xml.parseString(html) |
| 25 except ExpatError as e: | 25 except ExpatError as e: |
| 26 return _ParseHTML('\n'.join( | 26 return _ParseHTML('\n'.join( |
| 27 line for (i, line) in enumerate(html.split('\n')) | 27 line for (i, line) in enumerate(html.split('\n')) |
| 28 if e.lineno != i + 1)) | 28 if e.lineno != i + 1)) |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 if self._error is not None: | 137 if self._error is not None: |
| 138 raise self._error | 138 raise self._error |
| 139 return self._value | 139 return self._value |
| 140 | 140 |
| 141 class SubversionFileSystem(FileSystem): | 141 class SubversionFileSystem(FileSystem): |
| 142 '''Class to fetch resources from src.chromium.org. | 142 '''Class to fetch resources from src.chromium.org. |
| 143 ''' | 143 ''' |
| 144 @staticmethod | 144 @staticmethod |
| 145 def Create(branch='trunk', revision=None): | 145 def Create(branch='trunk', revision=None): |
| 146 if branch == 'trunk': | 146 if branch == 'trunk': |
| 147 svn_path = 'trunk/src/%s' % svn_constants.EXTENSIONS_PATH | 147 svn_path = 'trunk/src' |
| 148 else: | 148 else: |
| 149 svn_path = 'branches/%s/src/%s' % (branch, svn_constants.EXTENSIONS_PATH) | 149 svn_path = 'branches/%s/src' % branch |
| 150 return SubversionFileSystem( | 150 return SubversionFileSystem( |
| 151 AppEngineUrlFetcher('%s/%s' % (url_constants.SVN_URL, svn_path)), | 151 AppEngineUrlFetcher('%s/%s' % (url_constants.SVN_URL, svn_path)), |
| 152 AppEngineUrlFetcher('%s/%s' % (url_constants.VIEWVC_URL, svn_path)), | 152 AppEngineUrlFetcher('%s/%s' % (url_constants.VIEWVC_URL, svn_path)), |
| 153 svn_path, | 153 svn_path, |
| 154 revision=revision) | 154 revision=revision) |
| 155 | 155 |
| 156 def __init__(self, file_fetcher, stat_fetcher, svn_path, revision=None): | 156 def __init__(self, file_fetcher, stat_fetcher, svn_path, revision=None): |
| 157 self._file_fetcher = file_fetcher | 157 self._file_fetcher = file_fetcher |
| 158 self._stat_fetcher = stat_fetcher | 158 self._stat_fetcher = stat_fetcher |
| 159 self._svn_path = svn_path | 159 self._svn_path = svn_path |
| 160 self._revision = revision | 160 self._revision = revision |
| 161 | 161 |
| 162 def Read(self, paths, binary=False): | 162 def Read(self, paths, binary=False): |
| 163 args = None | 163 args = None |
| 164 if self._revision is not None: | 164 if self._revision is not None: |
| 165 # |fetcher| gets from svn.chromium.org which uses p= for version. | 165 # |fetcher| gets from svn.chromium.org which uses p= for version. |
| 166 args = 'p=%s' % self._revision | 166 args = 'p=%s' % self._revision |
| 167 return Future(delegate=_AsyncFetchFuture(paths, | 167 return Future(delegate=_AsyncFetchFuture(paths, |
| 168 self._file_fetcher, | 168 self._file_fetcher, |
| 169 binary, | 169 binary, |
| 170 args=args)) | 170 args=args)) |
| 171 | 171 |
| 172 def Refresh(self): | 172 def Refresh(self): |
| 173 return Future(value=()) | 173 return Future(value=()) |
| 174 | 174 |
| 175 def Stat(self, path): | 175 def Stat(self, path): |
| 176 directory, filename = posixpath.split(path) | 176 directory, filename = posixpath.split(path) |
| 177 directory += '/' | |
| 178 if self._revision is not None: | 177 if self._revision is not None: |
| 179 # |stat_fetch| uses viewvc which uses pathrev= for version. | 178 # |stat_fetch| uses viewvc which uses pathrev= for version. |
| 180 directory += '?pathrev=%s' % self._revision | 179 directory += '?pathrev=%s' % self._revision |
| 181 | 180 |
| 182 try: | 181 try: |
| 183 result = self._stat_fetcher.Fetch(directory) | 182 result = self._stat_fetcher.Fetch(directory) |
| 184 except Exception as e: | 183 except Exception as e: |
| 185 raise FileSystemError('Error fetching %s for Stat: %s' % | 184 raise FileSystemError('Error fetching %s for Stat: %s' % |
| 186 (path, traceback.format_exc())) | 185 (path, traceback.format_exc())) |
| 187 | 186 |
| 188 if result.status_code == 404: | 187 if result.status_code == 404: |
| 189 raise FileNotFoundError('Got 404 when fetching %s for Stat, content %s' % | 188 raise FileNotFoundError('Got 404 when fetching %s for Stat, content %s' % |
| 190 (path, result.content)) | 189 (path, result.content)) |
| 191 if result.status_code != 200: | 190 if result.status_code != 200: |
| 192 raise FileNotFoundError('Got %s when fetching %s for Stat, content %s' % | 191 raise FileNotFoundError('Got %s when fetching %s for Stat, content %s' % |
| 193 (result.status_code, path, result.content)) | 192 (result.status_code, path, result.content)) |
| 194 | 193 |
| 195 stat_info = _CreateStatInfo(result.content) | 194 stat_info = _CreateStatInfo(result.content) |
| 196 if stat_info.version is None: | 195 if stat_info.version is None: |
| 197 raise FileSystemError('Failed to find version of dir %s' % directory) | 196 raise FileSystemError('Failed to find version of dir %s' % directory) |
| 198 if path.endswith('/'): | 197 if path == '' or path.endswith('/'): |
| 199 return stat_info | 198 return stat_info |
| 200 if filename not in stat_info.child_versions: | 199 if filename not in stat_info.child_versions: |
| 201 raise FileNotFoundError( | 200 raise FileNotFoundError( |
| 202 '%s from %s was not in child versions for Stat' % (filename, path)) | 201 '%s from %s was not in child versions for Stat' % (filename, path)) |
| 203 return StatInfo(stat_info.child_versions[filename]) | 202 return StatInfo(stat_info.child_versions[filename]) |
| 204 | 203 |
| 205 def GetIdentity(self): | 204 def GetIdentity(self): |
| 206 # NOTE: no revision here, since it would mess up the caching of reads. It | 205 # NOTE: no revision here, since it would mess up the caching of reads. It |
| 207 # probably doesn't matter since all the caching classes will use the result | 206 # probably doesn't matter since all the caching classes will use the result |
| 208 # of Stat to decide whether to re-read - and Stat has a ceiling of the | 207 # of Stat to decide whether to re-read - and Stat has a ceiling of the |
| 209 # revision - so when the revision changes, so might Stat. That is enough. | 208 # revision - so when the revision changes, so might Stat. That is enough. |
| 210 return '@'.join((self.__class__.__name__, StringIdentity(self._svn_path))) | 209 return '@'.join((self.__class__.__name__, StringIdentity(self._svn_path))) |
| OLD | NEW |