OLD | NEW |
---|---|
(Empty) | |
1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 # Use of this source code is governed by a BSD-style license that can be | |
3 # found in the LICENSE file. | |
4 | |
5 import json | |
6 import os | |
7 | |
8 from appengine_url_fetcher import AppEngineUrlFetcher | |
9 from caching_file_system import CachingFileSystem | |
10 from compiled_file_system import CompiledFileSystem | |
11 from object_store_creator import ObjectStoreCreator | |
12 from subversion_file_system import SubversionFileSystem | |
13 import svn_constants | |
14 import third_party.json_schema_compiler.model as model | |
15 import url_constants | |
16 | |
epeterson
2013/04/17 03:38:50
Removed the [huge] dependency on api_data_source f
| |
17 class AvailabilityDataSource(object): | |
18 '''Uses API data sources generated by a ChromeVersionDataSource in order to | |
19 search the filesystem for the earliest existence of a specified API throughout | |
20 the different versions of Chrome; this constitutes an API's availability. | |
21 ''' | |
22 class Factory(object): | |
23 def __init__(self, chrome_version_utility, svn_file_system=None): | |
24 self._chrome_version_utility = chrome_version_utility | |
25 self._object_store = ObjectStoreCreator(AvailabilityDataSource).Create() | |
26 | |
27 # The |svn_file_system| will only be none for testing. | |
28 if svn_file_system is not None: | |
29 json_string = svn_file_system.ReadSingle('%s/api_availabilities.json' | |
30 % svn_constants.JSON_PATH) | |
31 self._existing_availabilities = json.loads(json_string) | |
32 | |
epeterson
2013/04/17 03:38:50
This hasn't been tested on the appengine, because
| |
33 def Create(self): | |
34 return AvailabilityDataSource(self._chrome_version_utility, | |
35 self._object_store, | |
36 self._existing_availabilities) | |
37 | |
38 def __init__(self, | |
39 chrome_version_utility, | |
40 object_store, | |
41 existing_availabilities): | |
42 self._chrome_version_utility = chrome_version_utility | |
43 self._object_store = object_store | |
44 self._existing_availabilities = existing_availabilities | |
45 | |
46 def _CreateSvnFileSystemForBranch(self, branch): | |
47 '''Creates a file system tied to a a specific branch of the svn repository. | |
48 ''' | |
49 if branch == 'trunk': | |
50 svn_url = '/'.join((url_constants.SVN_TRUNK_URL, | |
51 'src', | |
52 svn_constants.EXTENSIONS_PATH)) | |
53 else: | |
54 svn_url = '/'.join((url_constants.SVN_BRANCH_URL, | |
55 branch, | |
56 'src', | |
57 svn_constants.EXTENSIONS_PATH)) | |
58 viewvc_url = svn_url.replace(url_constants.SVN_URL, | |
59 url_constants.VIEWVC_URL) | |
60 | |
61 svn_file_system = CachingFileSystem( | |
62 SubversionFileSystem(AppEngineUrlFetcher(svn_url), | |
63 AppEngineUrlFetcher(viewvc_url)), | |
64 ObjectStoreCreator.Factory(branch)) | |
65 return svn_file_system | |
66 | |
67 def _GetAllNames(self, base_dir, apis): | |
68 '''Returns unix_hacker_style names for all APIs currently available. | |
69 ''' | |
70 return [ | |
71 model.UnixName(os.path.splitext(api)[0]) | |
72 for api in apis | |
73 ] | |
74 | |
75 def _GetAsSubdirectory(self, name): | |
76 if name.startswith('experimental_'): | |
77 parts = name[len('experimental_'):].split('_', 1) | |
78 if len(parts) > 1: | |
79 parts[1] = 'experimental_%s' % parts[1] | |
80 return '/'.join(parts) | |
81 else: | |
82 return '%s/%s' % (parts[0], name) | |
83 return name.replace('_', '/', 1) | |
84 | |
85 def _CheckApiExistence(self, api_name, version): | |
86 '''Finds a list of APIs that are present in the given |version|, and checks | |
87 to see whether or not |api_name| exists in that list. | |
88 ''' | |
89 names = self._object_store.Get(version).Get() | |
90 | |
91 if names is None: | |
92 svn_file_system = self._CreateSvnFileSystemForBranch( | |
93 self._chrome_version_utility.GetBranchNumberForVersion(version)) | |
94 compiled_fs_factory = CompiledFileSystem.Factory( | |
95 svn_file_system, | |
96 ObjectStoreCreator.Factory()) | |
97 names_cache = compiled_fs_factory.Create(self._GetAllNames, | |
98 AvailabilityDataSource) | |
99 names = names_cache.GetFromFileListing(svn_constants.API_PATH) | |
epeterson
2013/04/17 03:38:50
Instead of trying to load every file and check for
| |
100 self._object_store.Set(version, names) | |
101 api_name = model.UnixName(api_name) | |
102 return api_name in names or self._GetAsSubdirectory(api_name) in names | |
103 | |
104 def FindEarliestAvailability(self, api_name): | |
105 '''Searches in descending order through filesystem caches tied to specific | |
106 chrome version numbers and looks for the existence of a specified api, | |
107 |api_name|. When an api is not found, returns the previous version number | |
108 (the last known version where the api was found). | |
109 ''' | |
110 availability = self._object_store.Get(api_name).Get() | |
111 if availability is not None: | |
112 return availability | |
113 elif availability is False: | |
114 return None | |
115 | |
116 # Check for a predetermined availability for this API. | |
117 availability = self._existing_availabilities.get(api_name, None) | |
118 if availability is not None: | |
119 self._object_store.Set(api_name, availability) | |
120 return availability | |
121 | |
122 # If the API isn't found in trunk, then it isn't currently available. | |
123 if not self._CheckApiExistence(api_name, 'trunk'): | |
124 self._object_store.Set(api_name, False) | |
125 return None | |
126 | |
127 latest_version = int(self._chrome_version_utility.GetLatestVersionNumber()) | |
128 version_int = latest_version | |
129 # Extension APIs are not present in the filesystem before version 18. | |
130 while version_int >= 18: | |
131 if not self._CheckApiExistence(api_name, str(version_int)): | |
132 break | |
133 version_int -= 1 | |
134 | |
135 version_int += 1 | |
136 if version_int > latest_version: | |
137 availability = 'trunk' | |
138 else: | |
139 availability = str(version_int) | |
140 | |
141 self._object_store.Set(api_name, availability) | |
142 return availability | |
OLD | NEW |