2 # Copyright 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
15 _BASE_REGEX_STRING = '^\s*goog\.%s\(\s*[\'"](.+)[\'"]\s*\)'
16 require_regex = re.compile(_BASE_REGEX_STRING % 'require')
17 provide_regex = re.compile(_BASE_REGEX_STRING % 'provide')
20 '# Copyright 2014 The Chromium Authors. All rights reserved.',
21 '# Use of this source code is governed by a BSD-style license that can be',
22 '# found in the LICENSE file.',
24 '# This file is auto-generated using update.py.',
27 # Entry-points required to build a virtual keyboard.
29 'i18n.input.chrome.inputview.Controller',
30 'i18n.input.chrome.inputview.content.compact.letter',
31 'i18n.input.chrome.inputview.content.compact.util',
32 'i18n.input.chrome.inputview.content.compact.symbol',
33 'i18n.input.chrome.inputview.content.compact.more',
34 'i18n.input.chrome.inputview.content.compact.numberpad',
35 'i18n.input.chrome.inputview.content.ContextlayoutUtil',
36 'i18n.input.chrome.inputview.content.util',
37 'i18n.input.chrome.inputview.EmojiType',
38 'i18n.input.chrome.inputview.layouts.CompactSpaceRow',
39 'i18n.input.chrome.inputview.layouts.RowsOf101',
40 'i18n.input.chrome.inputview.layouts.RowsOf102',
41 'i18n.input.chrome.inputview.layouts.RowsOfCompact',
42 'i18n.input.chrome.inputview.layouts.RowsOfJP',
43 'i18n.input.chrome.inputview.layouts.SpaceRow',
44 'i18n.input.chrome.inputview.layouts.util',
45 'i18n.input.hwt.util']
47 # Any additional required files.
53 def ProcessFile(filename):
54 """Extracts provided and required namespaces.
57 Scans Javascript file for provied and required namespaces.
60 filename: name of the file to process.
63 Pair of lists, where the first list contains namespaces provided by the file
64 and the second contains a list of requirements.
68 file_handle = open(filename, 'r')
70 for line in file_handle:
71 if re.match(require_regex, line):
72 requires.append(re.search(require_regex, line).group(1))
73 if re.match(provide_regex, line):
74 provides.append(re.search(provide_regex, line).group(1))
77 return provides, requires
80 def ExpandDirectories(refs):
81 """Expands any directory references into inputs.
84 Looks for any directories in the provided references. Found directories
85 are recursively searched for .js files.
88 refs: a list of directories.
91 Pair of maps, where the first maps each namepace to the filename that
92 provides the namespace, and the second maps a filename to prerequisite
98 if os.path.isdir(ref):
99 for (root, dirs, files) in os.walk(ref):
101 if name.endswith('js'):
102 filename = os.path.join(root, name)
103 provides, requires = ProcessFile(filename)
105 providers[p] = filename
106 requirements[filename] = []
108 requirements[filename].append(r)
109 return providers, requirements
112 def ExtractDependencies(namespace, providers, requirements, dependencies):
113 """Recursively extracts all dependencies for a namespace.
115 Recursively extracts all dependencies for a namespace.
118 namespace: The namespace to process.
119 providers: Mapping of namespace to filename that provides the namespace.
120 requireemnts: Mapping of filename to a list of prerequisite namespaces.
123 if namespace in providers:
124 filename = providers[namespace]
125 if not filename in dependencies:
126 for ns in requirements[filename]:
127 ExtractDependencies(ns, providers, requirements, dependencies)
128 dependencies.add(filename)
132 """Resolves the user's home directory."""
134 return os.path.expanduser('~')
137 def ExpandPathRelativeToHome(path):
138 """Resolves a path that is relative to the home directory.
147 return os.path.join(os.path.expanduser('~'), path)
150 def GetGoogleInputToolsSandboxFromOptions(options):
151 """Generate the input-input-tools path from the --input flag.
154 options: Flags to update.py.
156 Path to the google-input-tools sandbox.
161 path = ExpandPathRelativeToHome('google-input-tools')
162 print 'Unspecified path for google-input-tools. Defaulting to %s' % path
166 def GetClosureLibrarySandboxFromOptions(options):
167 """Generate the closure-library path from the --input flag.
170 options: Flags to update.py.
172 Path to the closure-library sandbox.
177 path = ExpandPathRelativeToHome('closure-library')
178 print 'Unspecified path for closure-library. Defaulting to %s' % path
182 def CopyFile(source, target):
183 """Copies a file from the source to the target location.
186 source: Path to the source file to copy.
187 target: Path to the target location to copy the file.
190 if not os.path.exists(os.path.dirname(target)):
191 os.makedirs(os.path.dirname(target))
192 shutil.copy(source, target)
193 # Ensure correct file permissions.
194 if target.endswith('py'):
195 subprocess.call(['chmod', '+x', target])
197 subprocess.call(['chmod', '-x', target])
200 def UpdateFile(filename, input_source, closure_source, target_files):
201 """Updates files in third_party/google_input_tools.
204 filename: The file to update.
205 input_source: Root of the google_input_tools sandbox.
206 closure_source: Root of the closure_library sandbox.
207 target_files: List of relative paths to target files.
211 if filename.startswith(input_source):
212 target = os.path.join('src', filename[len(input_source)+1:])
213 elif filename.startswith(closure_source):
214 target = os.path.join('third_party/closure_library', \
215 filename[len(closure_source)+1:])
217 CopyFile(filename, target)
218 target_files.append(os.path.relpath(target, os.getcwd()))
221 def GenerateBuildFile(target_files):
222 """Updates inputview.gypi.
225 target_files: List of files required to build inputview.js.
228 sorted_files = sorted(target_files)
229 with open('inputview.gypi', 'w') as file_handle:
230 file_handle.write(os.linesep.join(preamble))
231 json_data = {'variables': {'inputview_sources': sorted_files}}
232 json_str = json.dumps(json_data, indent=2, separators=(',', ': '))
233 file_handle.write(json_str.replace('\"', '\''))
236 def CopyDir(input_path, sub_dir):
237 """Copies all files in a subdirectory of google-input-tools.
240 Recursive copy of a directory under google-input-tools. Used to copy
241 localization and resource files.
244 input_path: Path to the google-input-tools-sandbox.
246 dir = os.path.join(input_path, "chrome", "os", "inputview", sub_dir)
247 for (root, dirs, files) in os.walk(dir):
249 filename = os.path.join(root, name)
250 relative_path = filename[len(dir) + 1:]
251 target = os.path.join('src', 'chrome', 'os', 'inputview', sub_dir,
253 CopyFile(filename, target)
257 """The entrypoint for this script."""
259 logging.basicConfig(format='update.py: %(message)s', level=logging.INFO)
261 usage = 'usage: %prog [options] arg'
262 parser = optparse.OptionParser(usage)
263 parser.add_option('-i',
267 help='Path to the google-input-tools sandbox.')
268 parser.add_option('-l',
272 help='Path to the closure-library sandbox.')
274 (options, args) = parser.parse_args()
276 input_path = GetGoogleInputToolsSandboxFromOptions(options)
277 closure_library_path = GetClosureLibrarySandboxFromOptions(options)
279 if not os.path.isdir(input_path):
280 print 'Could not find google-input-tools sandbox.'
282 if not os.path.isdir(closure_library_path):
283 print 'Could not find closure-library sandbox.'
286 (providers, requirements) = \
287 ExpandDirectories([os.path.join(input_path, 'chrome'),
288 closure_library_path])
291 for name in namespaces:
292 ExtractDependencies(name, providers, requirements, dependencies)
295 for name in dependencies:
296 UpdateFile(name, input_path, closure_library_path, target_files)
298 GenerateBuildFile(target_files)
301 CopyDir(input_path, "_locales")
302 CopyDir(input_path, "images")
303 CopyDir(input_path, 'config')
304 CopyDir(input_path, 'layouts')
305 CopyDir(input_path, 'sounds')
307 # Copy extra support files.
309 source = os.path.join(input_path, 'chrome', 'os', 'inputview', name)
310 target = os.path.join('src', 'chrome', 'os', 'inputview', name)
311 CopyFile(source ,target)
314 if __name__ == '__main__':