OLD | NEW |
---|---|
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 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 mimetypes | 6 import mimetypes |
7 import posixpath | 7 import posixpath |
8 import traceback | 8 import traceback |
9 | 9 |
10 from compiled_file_system import SingleFile | 10 from compiled_file_system import SingleFile |
11 from directory_zipper import DirectoryZipper | 11 from directory_zipper import DirectoryZipper |
12 from docs_server_utils import ToUnicode | 12 from docs_server_utils import ToUnicode |
13 from file_system import FileNotFoundError | 13 from file_system import FileNotFoundError |
14 from future import Future | 14 from future import All, Future |
15 from path_canonicalizer import PathCanonicalizer | 15 from path_canonicalizer import PathCanonicalizer |
16 from path_util import AssertIsValid, IsDirectory, Join, ToDirectory | 16 from path_util import AssertIsValid, IsDirectory, Join, ToDirectory |
17 from special_paths import SITE_VERIFICATION_FILE | 17 from special_paths import SITE_VERIFICATION_FILE |
18 from third_party.handlebar import Handlebar | 18 from third_party.handlebar import Handlebar |
19 from third_party.markdown import markdown | 19 from third_party.markdown import markdown |
20 | 20 |
21 | 21 |
22 _MIMETYPE_OVERRIDES = { | 22 _MIMETYPE_OVERRIDES = { |
23 # SVG is not supported by mimetypes.guess_type on AppEngine. | 23 # SVG is not supported by mimetypes.guess_type on AppEngine. |
24 '.svg': 'image/svg+xml', | 24 '.svg': 'image/svg+xml', |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
122 ''' | 122 ''' |
123 AssertIsValid(path) | 123 AssertIsValid(path) |
124 base, ext = posixpath.splitext(path) | 124 base, ext = posixpath.splitext(path) |
125 if self._directory_zipper and ext == '.zip': | 125 if self._directory_zipper and ext == '.zip': |
126 # The canonical location of zip files is the canonical location of the | 126 # The canonical location of zip files is the canonical location of the |
127 # directory to zip + '.zip'. | 127 # directory to zip + '.zip'. |
128 return self._path_canonicalizer.Canonicalize(base + '/').rstrip('/') + ext | 128 return self._path_canonicalizer.Canonicalize(base + '/').rstrip('/') + ext |
129 return self._path_canonicalizer.Canonicalize(path) | 129 return self._path_canonicalizer.Canonicalize(path) |
130 | 130 |
131 def GetContentAndType(self, path): | 131 def GetContentAndType(self, path): |
132 '''Returns the ContentAndType of the file at |path|. | 132 '''Returns a Future to the ContentAndType of the file at |path|. |
133 ''' | 133 ''' |
134 AssertIsValid(path) | 134 AssertIsValid(path) |
135 base, ext = posixpath.splitext(path) | 135 base, ext = posixpath.splitext(path) |
136 | |
137 # Check for a zip file first, if zip is enabled. | |
138 if self._directory_zipper and ext == '.zip': | 136 if self._directory_zipper and ext == '.zip': |
139 zip_future = self._directory_zipper.Zip(ToDirectory(base)) | 137 zip_future = self._directory_zipper.Zip(ToDirectory(base)) |
140 return Future(callback= | 138 return Future(callback= |
141 lambda: ContentAndType(zip_future.Get(), 'application/zip', None)) | 139 lambda: ContentAndType(zip_future.Get(), 'application/zip', None)) |
140 return self._content_cache.GetFromFile(self._FindFileForPath(path)) | |
142 | 141 |
143 # If there is no file extension, look for a file with one of the default | 142 def GetVersion(self, path): |
144 # extensions. If one cannot be found, check if the path is a directory. | 143 '''Returns a Future to the version of the file at |path|. |
145 # If it is, then check for an index file with one of the default | 144 ''' |
146 # extensions. | 145 AssertIsValid(path) |
147 if not ext: | 146 base, ext = posixpath.splitext(path) |
148 new_path = self._AddExt(path) | 147 if self._directory_zipper and ext == '.zip': |
149 # Add a trailing / to check if it is a directory and not a file with | 148 stat_future = self.file_system.StatAsync(ToDirectory(base)) |
150 # no extension. | 149 else: |
151 if new_path is None and self.file_system.Exists(ToDirectory(path)).Get(): | 150 stat_future = self.file_system.StatAsync(self._FindFileForPath(path)) |
152 new_path = self._AddExt(Join(path, 'index')) | 151 return Future(callback=lambda: stat_future.Get().version) |
Yoyo Zhou
2014/08/12 22:32:57
Is this a Then?
not at google - send to devlin
2014/08/13 02:14:28
ooh, yes it is.
Sorry I went a little overboard h
| |
153 # If an index file wasn't found in this directly then we're never going | 152 |
154 # to find a file. | 153 def _FindFileForPath(self, path): |
155 if new_path is None: | 154 '''Finds the real file backing |path|. This may require looking for the |
156 return FileNotFoundError.RaiseInFuture('"%s" is a directory' % path) | 155 correct file extension, or looking for an 'index' file if it's a directory. |
156 Returns None if no path is found. | |
157 ''' | |
158 AssertIsValid(path) | |
159 _, ext = posixpath.splitext(path) | |
160 | |
161 if ext: | |
162 # There was already an extension, trust that it's a path. Elsewhere | |
163 # up the stack this will be caught if it's not. | |
164 return path | |
165 | |
166 # Look for a file with one of the default extensions. | |
167 new_path = self._AddExt(path) | |
168 if new_path is not None: | |
169 return new_path | |
170 | |
171 # Check if the path is really a directory, and if so look for an index file. | |
172 if self.file_system.Exists(ToDirectory(path)).Get(): | |
173 new_path = self._AddExt(Join(path, 'index')) | |
157 if new_path is not None: | 174 if new_path is not None: |
158 path = new_path | 175 return new_path |
159 | 176 |
160 return self._content_cache.GetFromFile(path) | 177 # Nothing found. Just return the original path and let logic up the stack |
178 # detect this as a 404 or whatever. | |
179 return path | |
161 | 180 |
162 def _AddExt(self, path): | 181 def _AddExt(self, path): |
163 '''Tries to append each of the default file extensions to path and returns | 182 '''Tries to append each of the default file extensions to path and returns |
164 the first one that is an existing file. | 183 the first one that is an existing file. |
165 ''' | 184 ''' |
166 for default_ext in self._default_extensions: | 185 for default_ext in self._default_extensions: |
167 if self.file_system.Exists(path + default_ext).Get(): | 186 if self.file_system.Exists(path + default_ext).Get(): |
168 return path + default_ext | 187 return path + default_ext |
169 return None | 188 return None |
170 | 189 |
(...skipping 12 matching lines...) Expand all Loading... | |
183 self.GetContentAndType(Join(root, base)))) | 202 self.GetContentAndType(Join(root, base)))) |
184 # TODO(kalman): Cache .zip files for each directory (if supported). | 203 # TODO(kalman): Cache .zip files for each directory (if supported). |
185 def resolve(): | 204 def resolve(): |
186 for label, future in futures: | 205 for label, future in futures: |
187 try: future.Get() | 206 try: future.Get() |
188 except: logging.error('%s: %s' % (label, traceback.format_exc())) | 207 except: logging.error('%s: %s' % (label, traceback.format_exc())) |
189 return Future(callback=resolve) | 208 return Future(callback=resolve) |
190 | 209 |
191 def __repr__(self): | 210 def __repr__(self): |
192 return 'ContentProvider of <%s>' % repr(self.file_system) | 211 return 'ContentProvider of <%s>' % repr(self.file_system) |
OLD | NEW |