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.
6 """Performs pull of google-input-tools from local clone of GitHub repository."""
16 _BASE_REGEX_STRING
= r
'^\s*goog\.%s\(\s*[\'"](.+)[\'"]\s
*\
)'
17 require_regex = re.compile(_BASE_REGEX_STRING % 'require
')
18 provide_regex = re.compile(_BASE_REGEX_STRING % 'provide
')
21 '# Copyright 2014 The Chromium Authors. All rights reserved.',
22 '# Use of this source code is governed by a BSD-style license that can be',
23 '# found in the LICENSE file.',
25 '# This file is auto-generated using update.py.',
29 # Entry-points required to build a virtual keyboard.
31 'i18n.input.chrome.inputview.Controller',
32 'i18n.input.chrome.inputview.content.compact.letter',
33 'i18n.input.chrome.inputview.content.compact.util',
34 'i18n.input.chrome.inputview.content.compact.symbol',
35 'i18n.input.chrome.inputview.content.compact.more',
36 'i18n.input.chrome.inputview.content.compact.numberpad',
37 'i18n.input.chrome.inputview.content.ContextlayoutUtil',
38 'i18n.input.chrome.inputview.content.util',
39 'i18n.input.chrome.inputview.EmojiType',
40 'i18n.input.chrome.inputview.layouts.CompactSpaceRow',
41 'i18n.input.chrome.inputview.layouts.RowsOf101',
42 'i18n.input.chrome.inputview.layouts.RowsOf102',
43 'i18n.input.chrome.inputview.layouts.RowsOfCompact',
44 'i18n.input.chrome.inputview.layouts.RowsOfJP',
45 'i18n.input.chrome.inputview.layouts.RowsOfNumberpad',
46 'i18n.input.chrome.inputview.layouts.SpaceRow',
47 'i18n.input.chrome.inputview.layouts.util',
48 'i18n.input.chrome.inputview.layouts.material.CompactSpaceRow',
49 'i18n.input.chrome.inputview.layouts.material.RowsOf101',
50 'i18n.input.chrome.inputview.layouts.material.RowsOf102',
51 'i18n.input.chrome.inputview.layouts.material.RowsOfCompact',
52 'i18n.input.chrome.inputview.layouts.material.RowsOfJP',
53 'i18n.input.chrome.inputview.layouts.material.RowsOfNumberpad',
54 'i18n.input.chrome.inputview.layouts.material.SpaceRow',
55 'i18n.input.chrome.inputview.layouts.material.util',
59 # Any additional required files.
66 def process_file(filename
):
67 """Extracts provided and required namespaces.
70 Scans Javascript file for provied and required namespaces.
73 filename: name of the file to process.
76 Pair of lists, where the first list contains namespaces provided by the file
77 and the second contains a list of requirements.
81 file_handle
= open(filename
, 'r')
83 for line
in file_handle
:
84 if re
.match(require_regex
, line
):
85 requires
.append(re
.search(require_regex
, line
).group(1))
86 if re
.match(provide_regex
, line
):
87 provides
.append(re
.search(provide_regex
, line
).group(1))
90 return provides
, requires
93 def expand_directories(refs
):
94 """Expands any directory references into inputs.
97 Looks for any directories in the provided references. Found directories
98 are recursively searched for .js files.
101 refs: a list of directories.
104 Pair of maps, where the first maps each namepace to the filename that
105 provides the namespace, and the second maps a filename to prerequisite
111 if os
.path
.isdir(ref
):
112 for (root
, _
, files
) in os
.walk(ref
):
114 if name
.endswith('js'):
115 filename
= os
.path
.join(root
, name
)
116 provides
, requires
= process_file(filename
)
118 providers
[p
] = filename
119 requirements
[filename
] = []
121 requirements
[filename
].append(r
)
122 return providers
, requirements
125 def extract_dependencies(namespace
, providers
, requirements
, dependencies
):
126 """Recursively extracts all dependencies for a namespace.
129 Recursively extracts all dependencies for a namespace.
132 namespace: The namespace to process.
133 providers: Mapping of namespace to filename that provides the namespace.
134 requirements: Mapping of filename to a list of prerequisite namespaces.
135 dependencies: List of files required to build inputview.
139 if namespace
in providers
:
140 filename
= providers
[namespace
]
141 if filename
not in dependencies
:
142 for ns
in requirements
[filename
]:
143 extract_dependencies(ns
, providers
, requirements
, dependencies
)
144 dependencies
.add(filename
)
148 """Resolves the user's home directory."""
150 return os
.path
.expanduser('~')
153 def expand_path_relative_to_home(path
):
154 """Resolves a path that is relative to the home directory.
163 return os
.path
.join(os
.path
.expanduser('~'), path
)
166 def get_google_input_tools_sandbox_from_options(options
):
167 """Generate the input-input-tools path from the --input flag.
170 options: Flags to update.py.
172 Path to the google-input-tools sandbox.
177 path
= expand_path_relative_to_home('google-input-tools')
178 print 'Unspecified path for google-input-tools. Defaulting to %s' % path
182 def get_closure_library_sandbox_from_options(options
):
183 """Generate the closure-library path from the --input flag.
186 options: Flags to update.py.
188 Path to the closure-library sandbox.
193 path
= expand_path_relative_to_home('closure-library')
194 print 'Unspecified path for closure-library. Defaulting to %s' % path
198 def copy_file(source
, target
):
199 """Copies a file from the source to the target location.
202 source: Path to the source file to copy.
203 target: Path to the target location to copy the file.
206 if not os
.path
.exists(os
.path
.dirname(target
)):
207 os
.makedirs(os
.path
.dirname(target
))
208 shutil
.copy(source
, target
)
209 # Ensure correct file permissions.
210 if target
.endswith('py'):
211 subprocess
.call(['chmod', '+x', target
])
213 subprocess
.call(['chmod', '-x', target
])
216 def update_file(filename
, input_source
, closure_source
, target_files
):
217 """Updates files in third_party/google_input_tools.
220 filename: The file to update.
221 input_source: Root of the google_input_tools sandbox.
222 closure_source: Root of the closure_library sandbox.
223 target_files: List of relative paths to target files.
227 if filename
.startswith(input_source
):
228 target
= os
.path
.join('src', filename
[len(input_source
)+1:])
229 elif filename
.startswith(closure_source
):
230 target
= os
.path
.join('third_party/closure_library',
231 filename
[len(closure_source
)+1:])
233 copy_file(filename
, target
)
234 target_files
.append(os
.path
.relpath(target
, os
.getcwd()))
237 def generate_build_file(target_files
):
238 """Updates inputview.gypi.
241 target_files: List of files required to build inputview.js.
244 sorted_files
= sorted(target_files
)
245 with
open('inputview.gypi', 'w') as file_handle
:
246 file_handle
.write(os
.linesep
.join(preamble
))
247 json_data
= {'variables': {'inputview_sources': sorted_files
}}
248 json_str
= json
.dumps(json_data
, indent
=2, separators
=(',', ': '))
249 file_handle
.write(json_str
.replace('\"', '\''))
252 def copy_dir(input_path
, sub_dir
):
253 """Copies all files in a subdirectory of google-input-tools.
256 Recursive copy of a directory under google-input-tools. Used to copy
257 localization and resource files.
260 input_path: Path to the google-input-tools-sandbox.
261 sub_dir: Subdirectory to copy within google-input-tools sandbox.
263 source_dir
= os
.path
.join(input_path
, 'chrome', 'os', sub_dir
)
264 for (root
, _
, files
) in os
.walk(source_dir
):
266 filename
= os
.path
.join(root
, name
)
267 relative_path
= filename
[len(source_dir
) + 1:]
268 target
= os
.path
.join('src', 'chrome', 'os', sub_dir
,
270 copy_file(filename
, target
)
274 """The entrypoint for this script."""
276 logging
.basicConfig(format
='update.py: %(message)s', level
=logging
.INFO
)
278 usage
= 'usage: %prog [options] arg'
279 parser
= optparse
.OptionParser(usage
)
280 parser
.add_option('-i',
284 help='Path to the google-input-tools sandbox.')
285 parser
.add_option('-l',
289 help='Path to the closure-library sandbox.')
291 (options
, _
) = parser
.parse_args()
293 input_path
= get_google_input_tools_sandbox_from_options(options
)
294 closure_library_path
= get_closure_library_sandbox_from_options(options
)
296 if not os
.path
.isdir(input_path
):
297 print 'Could not find google-input-tools sandbox.'
299 if not os
.path
.isdir(closure_library_path
):
300 print 'Could not find closure-library sandbox.'
303 (providers
, requirements
) = expand_directories([
304 os
.path
.join(input_path
, 'chrome'),
305 closure_library_path
])
308 for name
in namespaces
:
309 extract_dependencies(name
, providers
, requirements
, dependencies
)
312 for name
in dependencies
:
313 update_file(name
, input_path
, closure_library_path
, target_files
)
315 generate_build_file(target_files
)
318 copy_dir(input_path
, 'inputview/_locales')
319 copy_dir(input_path
, 'inputview/images')
320 copy_dir(input_path
, 'inputview/config')
321 copy_dir(input_path
, 'inputview/layouts')
322 copy_dir(input_path
, 'sounds')
324 # Copy extra support files.
326 source
= os
.path
.join(input_path
, 'chrome', 'os', 'inputview', name
)
327 target
= os
.path
.join('src', 'chrome', 'os', 'inputview', name
)
328 copy_file(source
, target
)
331 if __name__
== '__main__':