Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 import logging | |
| 7 import os | |
| 6 import sys | 8 import sys |
| 7 import os | |
| 8 | 9 |
| 9 # Add the original server location to sys.path so we are able to import | 10 # Add the original server location to sys.path so we are able to import |
| 10 # modules from there. | 11 # modules from there. |
| 11 SERVER_PATH = 'chrome/common/extensions/docs/server2' | 12 SERVER_PATH = 'chrome/common/extensions/docs/server2' |
| 12 if os.path.abspath(SERVER_PATH) not in sys.path: | 13 if os.path.abspath(SERVER_PATH) not in sys.path: |
| 13 sys.path.append(os.path.abspath(SERVER_PATH)) | 14 sys.path.append(os.path.abspath(SERVER_PATH)) |
| 14 | 15 |
| 15 import branch_utility | 16 import branch_utility |
| 16 import urlfetch | |
| 17 | 17 |
| 18 from google.appengine.ext import webapp | 18 from google.appengine.ext import webapp |
| 19 from google.appengine.api import memcache | |
| 19 from google.appengine.ext.webapp.util import run_wsgi_app | 20 from google.appengine.ext.webapp.util import run_wsgi_app |
| 20 | 21 |
| 21 from api_data_source import APIDataSource | 22 from api_data_source import APIDataSource |
| 23 from example_zipper import ExampleZipper | |
| 22 from fetcher_cache import FetcherCache | 24 from fetcher_cache import FetcherCache |
| 23 from intro_data_source import IntroDataSource | 25 from intro_data_source import IntroDataSource |
| 24 from local_fetcher import LocalFetcher | 26 from local_file_system import LocalFileSystem |
| 27 from memcache_file_system import MemcacheFileSystem | |
| 25 from samples_data_source import SamplesDataSource | 28 from samples_data_source import SamplesDataSource |
| 26 from server_instance import ServerInstance | 29 from server_instance import ServerInstance |
| 27 from subversion_fetcher import SubversionFetcher | 30 from subversion_file_system import SubversionFileSystem |
| 28 from template_data_source import TemplateDataSource | 31 from template_data_source import TemplateDataSource |
| 29 from example_zipper import ExampleZipper | 32 from appengine_url_fetcher import AppEngineUrlFetcher |
| 33 | |
| 34 SVN_URL = 'http://src.chromium.org/chrome' | |
| 35 TRUNK_URL = SVN_URL + '/trunk' | |
| 36 BRANCH_URL = SVN_URL + '/branches' | |
| 30 | 37 |
| 31 EXTENSIONS_PATH = 'chrome/common/extensions' | 38 EXTENSIONS_PATH = 'chrome/common/extensions' |
| 32 DOCS_PATH = 'docs' | 39 DOCS_PATH = 'docs' |
| 33 API_PATH = 'api' | 40 API_PATH = 'api' |
| 34 INTRO_PATH = DOCS_PATH + '/server2/templates/intros' | 41 INTRO_PATH = DOCS_PATH + '/server2/templates/intros' |
| 35 ARTICLE_PATH = DOCS_PATH + '/server2/templates/articles' | 42 ARTICLE_PATH = DOCS_PATH + '/server2/templates/articles' |
| 36 PUBLIC_TEMPLATE_PATH = DOCS_PATH + '/server2/templates/public' | 43 PUBLIC_TEMPLATE_PATH = DOCS_PATH + '/server2/templates/public' |
| 37 PRIVATE_TEMPLATE_PATH = DOCS_PATH + '/server2/templates/private' | 44 PRIVATE_TEMPLATE_PATH = DOCS_PATH + '/server2/templates/private' |
| 38 EXAMPLES_PATH = 'examples' | 45 EXAMPLES_PATH = DOCS_PATH + '/examples' |
| 39 FULL_EXAMPLES_PATH = DOCS_PATH + '/' + EXAMPLES_PATH | 46 FULL_EXAMPLES_PATH = DOCS_PATH + '/' + EXAMPLES_PATH |
| 40 | 47 |
| 41 # The branch that the server will default to when no branch is specified in the | 48 # The branch that the server will default to when no branch is specified in the |
| 42 # URL. This is necessary because it is not possible to pass flags to the script | 49 # URL. This is necessary because it is not possible to pass flags to the script |
| 43 # handler. | 50 # handler. |
| 44 DEFAULT_BRANCH = 'local' | 51 DEFAULT_BRANCH = 'local' |
| 45 | 52 |
| 46 # Global cache of instances because the Server is recreated for every request. | 53 # Global cache of instances because the Server is recreated for every request. |
| 47 SERVER_INSTANCES = {} | 54 SERVER_INSTANCES = {} |
| 48 | 55 |
| 56 def _GetURLFromBranch(branch): | |
| 57 if branch == 'trunk': | |
| 58 return TRUNK_URL + '/src' | |
| 59 return BRANCH_URL + '/' + branch + '/src' | |
| 60 | |
| 49 class Server(webapp.RequestHandler): | 61 class Server(webapp.RequestHandler): |
| 50 def _GetInstanceForBranch(self, branch): | 62 def _GetInstanceForBranch(self, branch): |
| 51 if branch in SERVER_INSTANCES: | 63 if branch in SERVER_INSTANCES: |
| 52 return SERVER_INSTANCES[branch] | 64 return SERVER_INSTANCES[branch] |
| 53 if branch == 'local': | 65 if branch == 'local': |
| 54 fetcher = LocalFetcher(EXTENSIONS_PATH) | 66 file_system = LocalFileSystem(EXTENSIONS_PATH) |
| 55 # No cache for local doc server. | 67 # No cache for local doc server. |
| 56 cache_timeout_seconds = 0 | 68 cache_timeout_seconds = 0 |
| 57 else: | 69 else: |
| 58 fetcher = SubversionFetcher(branch, EXTENSIONS_PATH, urlfetch) | 70 fetcher = AppEngineUrlFetcher( |
| 59 cache_timeout_seconds = 300 | 71 _GetURLFromBranch(branch) + '/' + EXTENSIONS_PATH) |
| 60 cache_builder = FetcherCache.Builder(fetcher, cache_timeout_seconds) | 72 svn_fs = SubversionFileSystem(fetcher) |
|
not at google - send to devlin
2012/07/18 10:39:15
inline svn_fs?
cduvall
2012/07/18 21:26:10
Done.
| |
| 73 file_system = MemcacheFileSystem(svn_fs, memcache) | |
| 74 cache_timeout_seconds = 60 | |
| 75 cache_builder = FetcherCache.Builder(file_system, cache_timeout_seconds) | |
| 61 api_data_source = APIDataSource(cache_builder, API_PATH) | 76 api_data_source = APIDataSource(cache_builder, API_PATH) |
| 62 intro_data_source = IntroDataSource(cache_builder, | 77 intro_data_source = IntroDataSource(cache_builder, |
| 63 [INTRO_PATH, ARTICLE_PATH]) | 78 [INTRO_PATH, ARTICLE_PATH]) |
| 64 samples_data_source = SamplesDataSource(fetcher, | 79 samples_data_source = SamplesDataSource(file_system, |
| 65 cache_builder, | 80 cache_builder, |
| 66 EXAMPLES_PATH) | 81 EXAMPLES_PATH) |
| 67 template_data_source = TemplateDataSource( | 82 template_data_source = TemplateDataSource( |
| 68 branch, | 83 branch, |
| 69 api_data_source, | 84 api_data_source, |
| 70 intro_data_source, | 85 intro_data_source, |
| 71 samples_data_source, | 86 samples_data_source, |
| 72 cache_builder, | 87 cache_builder, |
| 73 [PUBLIC_TEMPLATE_PATH, PRIVATE_TEMPLATE_PATH]) | 88 [PUBLIC_TEMPLATE_PATH, PRIVATE_TEMPLATE_PATH]) |
| 74 example_zipper = ExampleZipper(fetcher, | 89 example_zipper = ExampleZipper(file_system, |
| 75 cache_builder, | 90 cache_builder, |
| 76 DOCS_PATH, | 91 DOCS_PATH, |
| 77 EXAMPLES_PATH) | 92 EXAMPLES_PATH) |
| 78 SERVER_INSTANCES[branch] = ServerInstance( | 93 SERVER_INSTANCES[branch] = ServerInstance( |
| 79 template_data_source, | 94 template_data_source, |
| 80 example_zipper, | 95 example_zipper, |
| 81 cache_builder) | 96 cache_builder) |
| 82 return SERVER_INSTANCES[branch] | 97 return SERVER_INSTANCES[branch] |
| 83 | 98 |
| 84 def _HandleRequest(self, path): | 99 def _HandleRequest(self, path): |
| 85 channel_name, real_path = ( | 100 channel_name, real_path = ( |
| 86 branch_utility.SplitChannelNameFromPath(path, default=DEFAULT_BRANCH)) | 101 branch_utility.SplitChannelNameFromPath(path, default=DEFAULT_BRANCH)) |
| 87 branch = branch_utility.GetBranchNumberForChannelName(channel_name, | 102 branch = branch_utility.GetBranchNumberForChannelName( |
| 88 urlfetch) | 103 channel_name, |
| 104 AppEngineUrlFetcher('')) | |
| 89 if real_path == '': | 105 if real_path == '': |
| 90 real_path = 'index.html' | 106 real_path = 'index.html' |
| 91 self._GetInstanceForBranch(branch).Get(real_path, self) | 107 self._GetInstanceForBranch(branch).Get(real_path, self) |
|
not at google - send to devlin
2012/07/18 10:39:15
musing: when branch versions bump, this leaks Serv
cduvall
2012/07/18 21:26:10
Done.
| |
| 92 | 108 |
| 93 def get(self): | 109 def get(self): |
| 94 path = self.request.path | 110 path = self.request.path |
| 111 if '_ah/warmup' in path: | |
| 112 logging.info('Warmup request.') | |
| 113 self.get('/chrome/extensions/trunk/samples.html') | |
| 114 self.get('/chrome/extensions/dev/samples.html') | |
| 115 self.get('/chrome/extensions/beta/samples.html') | |
| 116 self.get('/chrome/extensions/stable/samples.html') | |
| 117 return | |
| 95 # Redirect paths like "directory" to "directory/". This is so relative file | 118 # Redirect paths like "directory" to "directory/". This is so relative file |
| 96 # paths will know to treat this as a directory. | 119 # paths will know to treat this as a directory. |
| 97 if os.path.splitext(path)[1] == '' and path[-1] != '/': | 120 if os.path.splitext(path)[1] == '' and path[-1] != '/': |
| 98 self.redirect(path + '/') | 121 self.redirect(path + '/') |
| 99 path = path.replace('/chrome/extensions/', '') | 122 path = path.replace('/chrome/extensions/', '') |
| 100 path = path.strip('/') | 123 path = path.strip('/') |
| 101 self._HandleRequest(path) | 124 self._HandleRequest(path) |
| 102 | 125 |
| 103 def main(): | 126 def main(): |
| 104 handlers = [ | 127 handlers = [ |
| 105 ('/.*', Server), | 128 ('/.*', Server), |
| 106 ] | 129 ] |
| 107 run_wsgi_app(webapp.WSGIApplication(handlers, debug=False)) | 130 run_wsgi_app(webapp.WSGIApplication(handlers, debug=False)) |
| 108 | 131 |
| 109 | 132 |
| 110 if __name__ == '__main__': | 133 if __name__ == '__main__': |
| 111 main() | 134 main() |
| OLD | NEW |