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 from file_system import FileSystem, FileNotFoundError, StatInfo, ToUnicode | |
6 from future import Future | |
7 import logging | 5 import logging |
8 import re | 6 import re |
9 import posixpath | 7 import posixpath |
10 import xml.dom.minidom as xml | 8 import xml.dom.minidom as xml |
11 from xml.parsers.expat import ExpatError | 9 from xml.parsers.expat import ExpatError |
12 | 10 |
| 11 from appengine_url_fetcher import AppEngineUrlFetcher |
| 12 from docs_server_utils import StringIdentity |
| 13 from file_system import FileSystem, FileNotFoundError, StatInfo, ToUnicode |
| 14 from future import Future |
| 15 import svn_constants |
| 16 import url_constants |
| 17 |
13 class _AsyncFetchFuture(object): | 18 class _AsyncFetchFuture(object): |
14 def __init__(self, paths, fetcher, binary): | 19 def __init__(self, paths, fetcher, binary): |
15 # A list of tuples of the form (path, Future). | 20 # A list of tuples of the form (path, Future). |
16 self._fetches = [(path, fetcher.FetchAsync(path)) for path in paths] | 21 self._fetches = [(path, fetcher.FetchAsync(path)) |
| 22 for path in paths] |
17 self._value = {} | 23 self._value = {} |
18 self._error = None | 24 self._error = None |
19 self._binary = binary | 25 self._binary = binary |
20 | 26 |
21 def _ListDir(self, directory): | 27 def _ListDir(self, directory): |
22 dom = xml.parseString(directory) | 28 dom = xml.parseString(directory) |
23 files = [elem.childNodes[0].data for elem in dom.getElementsByTagName('a')] | 29 files = [elem.childNodes[0].data for elem in dom.getElementsByTagName('a')] |
24 if '..' in files: | 30 if '..' in files: |
25 files.remove('..') | 31 files.remove('..') |
26 return files | 32 return files |
(...skipping 11 matching lines...) Expand all Loading... |
38 self._value[path] = self._ListDir(result.content) | 44 self._value[path] = self._ListDir(result.content) |
39 elif not self._binary: | 45 elif not self._binary: |
40 self._value[path] = ToUnicode(result.content) | 46 self._value[path] = ToUnicode(result.content) |
41 else: | 47 else: |
42 self._value[path] = result.content | 48 self._value[path] = result.content |
43 if self._error is not None: | 49 if self._error is not None: |
44 raise self._error | 50 raise self._error |
45 return self._value | 51 return self._value |
46 | 52 |
47 class SubversionFileSystem(FileSystem): | 53 class SubversionFileSystem(FileSystem): |
48 """Class to fetch resources from src.chromium.org. | 54 '''Class to fetch resources from src.chromium.org. |
49 """ | 55 ''' |
50 def __init__(self, fetcher, stat_fetcher): | 56 @staticmethod |
51 self._fetcher = fetcher | 57 def Create(branch): |
| 58 if branch == 'trunk': |
| 59 svn_path = 'trunk/src/%s' % svn_constants.EXTENSIONS_PATH |
| 60 else: |
| 61 svn_path = 'branches/%s/src/%s' % (branch, |
| 62 svn_constants.EXTENSIONS_PATH) |
| 63 return SubversionFileSystem( |
| 64 AppEngineUrlFetcher('%s/%s' % (url_constants.SVN_URL, svn_path)), |
| 65 AppEngineUrlFetcher('%s/%s' % (url_constants.VIEWVC_URL, svn_path)), |
| 66 svn_path) |
| 67 |
| 68 def __init__(self, file_fetcher, stat_fetcher, svn_path): |
| 69 self._file_fetcher = file_fetcher |
52 self._stat_fetcher = stat_fetcher | 70 self._stat_fetcher = stat_fetcher |
| 71 self._svn_path = svn_path |
53 | 72 |
54 def Read(self, paths, binary=False): | 73 def Read(self, paths, binary=False): |
55 return Future(delegate=_AsyncFetchFuture(paths, self._fetcher, binary)) | 74 return Future(delegate=_AsyncFetchFuture(paths, |
| 75 self._file_fetcher, |
| 76 binary)) |
56 | 77 |
57 def _ParseHTML(self, html): | 78 def _ParseHTML(self, html): |
58 """Unfortunately, the viewvc page has a stray </div> tag, so this takes care | 79 '''Unfortunately, the viewvc page has a stray </div> tag, so this takes care |
59 of all mismatched tags. | 80 of all mismatched tags. |
60 """ | 81 ''' |
61 try: | 82 try: |
62 return xml.parseString(html) | 83 return xml.parseString(html) |
63 except ExpatError as e: | 84 except ExpatError as e: |
64 return self._ParseHTML('\n'.join( | 85 return self._ParseHTML('\n'.join( |
65 line for (i, line) in enumerate(html.split('\n')) | 86 line for (i, line) in enumerate(html.split('\n')) |
66 if e.lineno != i + 1)) | 87 if e.lineno != i + 1)) |
67 | 88 |
68 def _CreateStatInfo(self, html): | 89 def _CreateStatInfo(self, html): |
69 def inner_text(node): | 90 def inner_text(node): |
70 '''Like node.innerText in JS DOM, but strips surrounding whitespace. | 91 '''Like node.innerText in JS DOM, but strips surrounding whitespace. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 return StatInfo(str(parent_version), | 134 return StatInfo(str(parent_version), |
114 dict((path, str(version)) | 135 dict((path, str(version)) |
115 for path, version in child_versions.iteritems())) | 136 for path, version in child_versions.iteritems())) |
116 | 137 |
117 # Bleh, but, this data is so unreliable. There are actually some empty file | 138 # Bleh, but, this data is so unreliable. There are actually some empty file |
118 # listings caused by git/svn/something not cleaning up empty dirs. | 139 # listings caused by git/svn/something not cleaning up empty dirs. |
119 return StatInfo('0', {}) | 140 return StatInfo('0', {}) |
120 | 141 |
121 def Stat(self, path): | 142 def Stat(self, path): |
122 directory, filename = posixpath.split(path) | 143 directory, filename = posixpath.split(path) |
123 result = self._stat_fetcher.Fetch(directory + '/') | 144 directory += '/' |
| 145 result = self._stat_fetcher.Fetch(directory) |
124 if result.status_code == 404: | 146 if result.status_code == 404: |
125 raise FileNotFoundError( | 147 raise FileNotFoundError( |
126 'Got 404 when fetching %s from %s for Stat' % (path, directory)) | 148 'Got 404 when fetching %s from %s for Stat' % (path, directory)) |
127 stat_info = self._CreateStatInfo(result.content) | 149 stat_info = self._CreateStatInfo(result.content) |
128 if path.endswith('/'): | 150 if path.endswith('/'): |
129 return stat_info | 151 return stat_info |
130 if filename not in stat_info.child_versions: | 152 if filename not in stat_info.child_versions: |
131 raise FileNotFoundError('%s was not in child versions' % filename) | 153 raise FileNotFoundError('%s was not in child versions' % filename) |
132 return StatInfo(stat_info.child_versions[filename]) | 154 return StatInfo(stat_info.child_versions[filename]) |
| 155 |
| 156 def GetIdentity(self): |
| 157 return '@'.join((self.__class__.__name__, StringIdentity(self._svn_path))) |
OLD | NEW |