OLD | NEW |
1 # Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. | 1 # Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. |
2 # | 2 # |
3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
4 # modification, are permitted provided that the following conditions | 4 # modification, are permitted provided that the following conditions |
5 # are met: | 5 # are met: |
6 # | 6 # |
7 # 1. Redistributions of source code must retain the above | 7 # 1. Redistributions of source code must retain the above |
8 # copyright notice, this list of conditions and the following | 8 # copyright notice, this list of conditions and the following |
9 # disclaimer. | 9 # disclaimer. |
10 # 2. Redistributions in binary form must reproduce the above | 10 # 2. Redistributions in binary form must reproduce the above |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 self.top_of_repo = top_of_repo | 159 self.top_of_repo = top_of_repo |
160 self.options = options | 160 self.options = options |
161 | 161 |
162 self.filesystem = self.host.filesystem | 162 self.filesystem = self.host.filesystem |
163 self.webkit_finder = WebKitFinder(self.filesystem) | 163 self.webkit_finder = WebKitFinder(self.filesystem) |
164 self._webkit_root = self.webkit_finder.webkit_base() | 164 self._webkit_root = self.webkit_finder.webkit_base() |
165 self.layout_tests_dir = self.webkit_finder.path_from_webkit_base('Layout
Tests') | 165 self.layout_tests_dir = self.webkit_finder.path_from_webkit_base('Layout
Tests') |
166 self.destination_directory = self.filesystem.normpath(self.filesystem.jo
in(self.layout_tests_dir, options.destination, | 166 self.destination_directory = self.filesystem.normpath(self.filesystem.jo
in(self.layout_tests_dir, options.destination, |
167
self.filesystem.basename(self.top_of_repo))) | 167
self.filesystem.basename(self.top_of_repo))) |
168 self.import_in_place = (self.dir_to_import == self.destination_directory
) | 168 self.import_in_place = (self.dir_to_import == self.destination_directory
) |
| 169 self.dir_above_repo = self.filesystem.dirname(self.top_of_repo) |
169 | 170 |
170 self.changeset = CHANGESET_NOT_AVAILABLE | 171 self.changeset = CHANGESET_NOT_AVAILABLE |
171 | 172 |
172 self.import_list = [] | 173 self.import_list = [] |
173 | 174 |
174 def do_import(self): | 175 def do_import(self): |
175 _log.info("Importing %s into %s", self.dir_to_import, self.destination_d
irectory) | 176 _log.info("Importing %s into %s", self.dir_to_import, self.destination_d
irectory) |
176 self.find_importable_tests(self.dir_to_import) | 177 self.find_importable_tests(self.dir_to_import) |
177 self.load_changeset() | 178 self.load_changeset() |
178 self.import_tests() | 179 self.import_tests() |
179 | 180 |
180 def load_changeset(self): | 181 def load_changeset(self): |
181 """Returns the current changeset from mercurial or "Not Available".""" | 182 """Returns the current changeset from mercurial or "Not Available".""" |
182 try: | 183 try: |
183 self.changeset = self.host.executive.run_command(['hg', 'tip']).spli
t('changeset:')[1] | 184 self.changeset = self.host.executive.run_command(['hg', 'tip']).spli
t('changeset:')[1] |
184 except (OSError, ScriptError): | 185 except (OSError, ScriptError): |
185 self.changeset = CHANGESET_NOT_AVAILABLE | 186 self.changeset = CHANGESET_NOT_AVAILABLE |
186 | 187 |
187 def find_importable_tests(self, directory): | 188 def find_importable_tests(self, directory): |
188 # FIXME: use filesystem | 189 # FIXME: use filesystem |
189 paths_to_skip = self.find_paths_to_skip() | 190 paths_to_skip = self.find_paths_to_skip() |
190 | 191 |
191 for root, dirs, files in os.walk(directory): | 192 for root, dirs, files in os.walk(directory): |
192 cur_dir = root.replace(self.layout_tests_dir + '/', '') + '/' | 193 cur_dir = root.replace(self.dir_above_repo + '/', '') + '/' |
193 _log.info(' scanning ' + cur_dir + '...') | 194 _log.info(' scanning ' + cur_dir + '...') |
194 total_tests = 0 | 195 total_tests = 0 |
195 reftests = 0 | 196 reftests = 0 |
196 jstests = 0 | 197 jstests = 0 |
197 | 198 |
198 DIRS_TO_SKIP = ('.git', '.hg') | 199 DIRS_TO_SKIP = ('.git', '.hg') |
199 if dirs: | 200 if dirs: |
200 for d in DIRS_TO_SKIP: | 201 for d in DIRS_TO_SKIP: |
201 if d in dirs: | 202 if d in dirs: |
202 dirs.remove(d) | 203 dirs.remove(d) |
203 | 204 |
204 for path in paths_to_skip: | 205 for path in paths_to_skip: |
205 path_base = path.replace(cur_dir, '') | 206 path_base = path.replace(self.options.destination + '/', '') |
| 207 path_base = path_base.replace(cur_dir, '') |
206 path_full = self.filesystem.join(root, path_base) | 208 path_full = self.filesystem.join(root, path_base) |
207 if path_base in dirs: | 209 if path_base in dirs: |
208 dirs.remove(path_base) | 210 dirs.remove(path_base) |
209 if not self.options.dry_run and self.import_in_place: | 211 if not self.options.dry_run and self.import_in_place: |
210 _log.info(" pruning %s" % path_base) | 212 _log.info(" pruning %s" % path_base) |
211 self.filesystem.rmtree(path_full) | 213 self.filesystem.rmtree(path_full) |
| 214 else: |
| 215 _log.info(" skipping %s" % path_base) |
| 216 |
212 | 217 |
213 copy_list = [] | 218 copy_list = [] |
214 | 219 |
215 for filename in files: | 220 for filename in files: |
216 path_full = self.filesystem.join(root, filename) | 221 path_full = self.filesystem.join(root, filename) |
217 path_base = path_full.replace(self.layout_tests_dir + '/', '') | 222 path_base = path_full.replace(self.layout_tests_dir + '/', '') |
218 if path_base in paths_to_skip: | 223 if path_base in paths_to_skip: |
219 if not self.options.dry_run and self.import_in_place: | 224 if not self.options.dry_run and self.import_in_place: |
220 _log.info(" pruning %s" % path_base) | 225 _log.info(" pruning %s" % path_base) |
221 self.filesystem.remove(path_full) | 226 self.filesystem.remove(path_full) |
222 continue | 227 continue |
| 228 else: |
| 229 continue |
223 # FIXME: This block should really be a separate function, but th
e early-continues make that difficult. | 230 # FIXME: This block should really be a separate function, but th
e early-continues make that difficult. |
224 | 231 |
225 if filename.startswith('.') or filename.endswith('.pl'): | 232 if filename.startswith('.') or filename.endswith('.pl'): |
226 continue # For some reason the w3c repo contains random per
l scripts we don't care about. | 233 continue # For some reason the w3c repo contains random per
l scripts we don't care about. |
227 | 234 |
228 fullpath = os.path.join(root, filename) | 235 fullpath = os.path.join(root, filename) |
229 | 236 |
230 mimetype = mimetypes.guess_type(fullpath) | 237 mimetype = mimetypes.guess_type(fullpath) |
231 if not 'html' in str(mimetype[0]) and not 'application/xhtml+xml
' in str(mimetype[0]) and not 'application/xml' in str(mimetype[0]): | 238 if not 'html' in str(mimetype[0]) and not 'application/xhtml+xml
' in str(mimetype[0]) and not 'application/xml' in str(mimetype[0]): |
232 copy_list.append({'src': fullpath, 'dest': filename}) | 239 copy_list.append({'src': fullpath, 'dest': filename}) |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 if not(os.path.exists(orig_filepath)): | 350 if not(os.path.exists(orig_filepath)): |
344 _log.warning('%s not found. Possible error in the test.', or
ig_filepath) | 351 _log.warning('%s not found. Possible error in the test.', or
ig_filepath) |
345 continue | 352 continue |
346 | 353 |
347 new_filepath = os.path.join(new_path, file_to_copy['dest']) | 354 new_filepath = os.path.join(new_path, file_to_copy['dest']) |
348 | 355 |
349 if not(os.path.exists(os.path.dirname(new_filepath))): | 356 if not(os.path.exists(os.path.dirname(new_filepath))): |
350 if not self.import_in_place and not self.options.dry_run: | 357 if not self.import_in_place and not self.options.dry_run: |
351 os.makedirs(os.path.dirname(new_filepath)) | 358 os.makedirs(os.path.dirname(new_filepath)) |
352 | 359 |
| 360 relpath = os.path.relpath(new_filepath, self.layout_tests_dir) |
353 if not self.options.overwrite and os.path.exists(new_filepath): | 361 if not self.options.overwrite and os.path.exists(new_filepath): |
354 _log.info(' skipping import of existing file ' + new_filepa
th) | 362 _log.info(' skipping %s' % relpath) |
355 else: | 363 else: |
356 # FIXME: Maybe doing a file diff is in order here for existi
ng files? | 364 # FIXME: Maybe doing a file diff is in order here for existi
ng files? |
357 # In other words, there's no sense in overwriting identical
files, but | 365 # In other words, there's no sense in overwriting identical
files, but |
358 # there's no harm in copying the identical thing. | 366 # there's no harm in copying the identical thing. |
359 _log.info(' importing %s', os.path.relpath(new_filepath, se
lf.layout_tests_dir)) | 367 _log.info(' %s' % relpath) |
360 | 368 |
361 # Only html, xml, or css should be converted | 369 # Only html, xml, or css should be converted |
362 # FIXME: Eventually, so should js when support is added for this
type of conversion | 370 # FIXME: Eventually, so should js when support is added for this
type of conversion |
363 mimetype = mimetypes.guess_type(orig_filepath) | 371 mimetype = mimetypes.guess_type(orig_filepath) |
364 if 'html' in str(mimetype[0]) or 'xml' in str(mimetype[0]) or '
css' in str(mimetype[0]): | 372 if 'html' in str(mimetype[0]) or 'xml' in str(mimetype[0]) or '
css' in str(mimetype[0]): |
365 converted_file = convert_for_webkit(new_path, filename=orig_
filepath) | 373 converted_file = convert_for_webkit(new_path, filename=orig_
filepath) |
366 | 374 |
367 if not converted_file: | 375 if not converted_file: |
368 if not self.import_in_place and not self.options.dry_run
: | 376 if not self.import_in_place and not self.options.dry_run
: |
369 shutil.copyfile(orig_filepath, new_filepath) # The
file was unmodified. | 377 shutil.copyfile(orig_filepath, new_filepath) # The
file was unmodified. |
370 else: | 378 else: |
371 for prefixed_property in converted_file[0]: | 379 for prefixed_property in converted_file[0]: |
372 total_prefixed_properties.setdefault(prefixed_proper
ty, 0) | 380 total_prefixed_properties.setdefault(prefixed_proper
ty, 0) |
373 total_prefixed_properties[prefixed_property] += 1 | 381 total_prefixed_properties[prefixed_property] += 1 |
374 | 382 |
375 prefixed_properties.extend(set(converted_file[0]) - set(
prefixed_properties)) | 383 prefixed_properties.extend(set(converted_file[0]) - set(
prefixed_properties)) |
376 if not self.options.dry_run: | 384 if not self.options.dry_run: |
377 outfile = open(new_filepath, 'wb') | 385 outfile = open(new_filepath, 'wb') |
378 outfile.write(converted_file[1]) | 386 outfile.write(converted_file[1]) |
379 outfile.close() | 387 outfile.close() |
380 else: | 388 else: |
381 if not self.import_in_place and not self.options.dry_run: | 389 if not self.import_in_place and not self.options.dry_run: |
382 shutil.copyfile(orig_filepath, new_filepath) | 390 shutil.copyfile(orig_filepath, new_filepath) |
383 | 391 |
384 copied_files.append(new_filepath.replace(self._webkit_root, '')) | 392 copied_files.append(new_filepath.replace(self._webkit_root, '')) |
385 | 393 |
386 if not self.import_in_place and not self.options.dry_run: | |
387 self.remove_deleted_files(new_path, copied_files) | |
388 self.write_import_log(new_path, copied_files, prefixed_propertie
s) | |
389 | |
390 _log.info('') | 394 _log.info('') |
391 _log.info('Import complete') | 395 _log.info('Import complete') |
392 _log.info('') | 396 _log.info('') |
393 _log.info('IMPORTED %d TOTAL TESTS', total_imported_tests) | 397 _log.info('IMPORTED %d TOTAL TESTS', total_imported_tests) |
394 _log.info('Imported %d reftests', total_imported_reftests) | 398 _log.info('Imported %d reftests', total_imported_reftests) |
395 _log.info('Imported %d JS tests', total_imported_jstests) | 399 _log.info('Imported %d JS tests', total_imported_jstests) |
396 _log.info('Imported %d pixel/manual tests', total_imported_tests - total
_imported_jstests - total_imported_reftests) | 400 _log.info('Imported %d pixel/manual tests', total_imported_tests - total
_imported_jstests - total_imported_reftests) |
397 _log.info('') | 401 _log.info('') |
398 _log.info('Properties needing prefixes (by count):') | 402 |
399 for prefixed_property in sorted(total_prefixed_properties, key=lambda p:
total_prefixed_properties[p]): | 403 if total_prefixed_properties: |
400 _log.info(' %s: %s', prefixed_property, total_prefixed_properties[p
refixed_property]) | 404 _log.info('Properties needing prefixes (by count):') |
| 405 for prefixed_property in sorted(total_prefixed_properties, key=lambd
a p: total_prefixed_properties[p]): |
| 406 _log.info(' %s: %s', prefixed_property, total_prefixed_properti
es[prefixed_property]) |
401 | 407 |
402 def setup_destination_directory(self): | 408 def setup_destination_directory(self): |
403 """ Creates a destination directory that mirrors that of the source dire
ctory """ | 409 """ Creates a destination directory that mirrors that of the source dire
ctory """ |
404 | 410 |
405 new_subpath = self.dir_to_import[len(self.top_of_repo):] | 411 new_subpath = self.dir_to_import[len(self.top_of_repo):] |
406 | 412 |
407 destination_directory = os.path.join(self.destination_directory, new_sub
path) | 413 destination_directory = os.path.join(self.destination_directory, new_sub
path) |
408 | 414 |
409 if not os.path.exists(destination_directory): | 415 if not os.path.exists(destination_directory): |
410 os.makedirs(destination_directory) | 416 os.makedirs(destination_directory) |
411 | 417 |
412 _log.info('Tests will be imported into: %s', destination_directory) | 418 _log.info('Tests will be imported into: %s', destination_directory) |
413 | |
414 def remove_deleted_files(self, dir_to_import, new_file_list): | |
415 previous_file_list = [] | |
416 | |
417 import_log_file = os.path.join(dir_to_import, 'w3c-import.log') | |
418 if not os.path.exists(import_log_file): | |
419 return | |
420 | |
421 import_log = open(import_log_file, 'r') | |
422 contents = import_log.readlines() | |
423 | |
424 if 'List of files\n' in contents: | |
425 list_index = contents.index('List of files:\n') + 1 | |
426 previous_file_list = [filename.strip() for filename in contents[list
_index:]] | |
427 | |
428 deleted_files = set(previous_file_list) - set(new_file_list) | |
429 for deleted_file in deleted_files: | |
430 _log.info('Deleting file removed from the W3C repo: %s', deleted_fil
e) | |
431 deleted_file = os.path.join(self._webkit_root, deleted_file) | |
432 os.remove(deleted_file) | |
433 | |
434 import_log.close() | |
435 | |
436 def write_import_log(self, dir_to_import, file_list, prop_list): | |
437 now = datetime.datetime.now() | |
438 | |
439 import_log = open(os.path.join(dir_to_import, 'w3c-import.log'), 'w') | |
440 import_log.write('The tests in this directory were imported from the W3C
repository.\n') | |
441 import_log.write('Do NOT modify these tests directly in Webkit. Instead,
push changes to the W3C CSS repo:\n\n') | |
442 import_log.write('http://hg.csswg.org/test\n\n') | |
443 import_log.write('Then run the Tools/Scripts/import-w3c-tests in Webkit
to reimport\n\n') | |
444 import_log.write('Do NOT modify or remove this file\n\n') | |
445 import_log.write('------------------------------------------------------
------------------\n') | |
446 import_log.write('Last Import: ' + now.strftime('%Y-%m-%d %H:%M') + '\n'
) | |
447 import_log.write('W3C Mercurial changeset: ' + self.changeset + '\n') | |
448 import_log.write('------------------------------------------------------
------------------\n') | |
449 import_log.write('Properties requiring vendor prefixes:\n') | |
450 if prop_list: | |
451 for prop in prop_list: | |
452 import_log.write(prop + '\n') | |
453 else: | |
454 import_log.write('None\n') | |
455 import_log.write('------------------------------------------------------
------------------\n') | |
456 import_log.write('List of files:\n') | |
457 for item in file_list: | |
458 import_log.write(item + '\n') | |
459 | |
460 import_log.close() | |
OLD | NEW |