1# Copyright 2014 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"""Pull latest revisions of the W3C test repos and update our DEPS entries.""" 6 7import argparse 8 9 10from webkitpy.common.webkit_finder import WebKitFinder 11 12 13class DepsUpdater(object): 14 def __init__(self, host): 15 self.host = host 16 self.executive = host.executive 17 self.fs = host.filesystem 18 self.finder = WebKitFinder(self.fs) 19 self.verbose = False 20 self.allow_local_blink_commits = False 21 self.keep_w3c_repos_around = False 22 23 def main(self, argv=None): 24 self.parse_args(argv) 25 26 self.cd('') 27 if not self.checkout_is_okay(): 28 return 1 29 30 self.print_('## noting the current Blink commitish') 31 blink_commitish = self.run(['git', 'show-ref', 'HEAD'])[1].split()[0] 32 33 wpt_import_text = self.update('web-platform-tests', 34 'https://chromium.googlesource.com/external/w3c/web-platform-tests.git') 35 36 css_import_text = self.update('csswg-test', 37 'https://chromium.googlesource.com/external/w3c/csswg-test.git') 38 39 self.commit_changes_if_needed(blink_commitish, css_import_text, wpt_import_text) 40 41 return 0 42 43 def parse_args(self, argv): 44 parser = argparse.ArgumentParser() 45 parser.description = __doc__ 46 parser.add_argument('-v', '--verbose', action='store_true', 47 help='log what we are doing') 48 parser.add_argument('--allow-local-blink-commits', action='store_true', 49 help='allow script to run even if we have local blink commits') 50 parser.add_argument('--keep-w3c-repos-around', action='store_true', 51 help='leave the w3c repos around that were imported previously.') 52 53 args = parser.parse_args(argv) 54 self.allow_local_blink_commits = args.allow_local_blink_commits 55 self.keep_w3c_repos_around = args.keep_w3c_repos_around 56 self.verbose = args.verbose 57 58 def checkout_is_okay(self): 59 if self.run(['git', 'diff', '--quiet', 'HEAD'], exit_on_failure=False)[0]: 60 self.print_('## blink checkout is dirty, aborting') 61 return False 62 63 local_blink_commits = self.run(['git', 'log', '--oneline', 'origin/master..HEAD'])[1] 64 if local_blink_commits and not self.allow_local_blink_commits: 65 self.print_('## blink checkout has local commits, aborting') 66 return False 67 68 if self.fs.exists(self.path_from_webkit_base('web-platform-tests')): 69 self.print_('## web-platform-tests repo exists, aborting') 70 return False 71 72 if self.fs.exists(self.path_from_webkit_base('csswg-test')): 73 self.print_('## csswg-test repo exists, aborting') 74 return False 75 76 return True 77 78 def update(self, repo, url): 79 self.print_('## cloning %s' % repo) 80 self.cd('') 81 self.run(['git', 'clone', url]) 82 83 self.print_('## noting the revision we are importing') 84 master_commitish = self.run(['git', 'show-ref', 'origin/master'])[1].split()[0] 85 86 self.print_('## cleaning out tests from LayoutTests/imported/%s' % repo) 87 dest_repo = self.path_from_webkit_base('LayoutTests', 'imported', repo) 88 files_to_delete = self.fs.files_under(dest_repo, file_filter=self.is_not_baseline) 89 for subpath in files_to_delete: 90 self.remove('LayoutTests', 'imported', subpath) 91 92 self.print_('## importing the tests') 93 src_repo = self.path_from_webkit_base(repo) 94 import_path = self.path_from_webkit_base('Tools', 'Scripts', 'import-w3c-tests') 95 self.run([self.host.executable, import_path, '-d', 'imported', src_repo]) 96 97 self.cd('') 98 self.run(['git', 'add', '--all', 'LayoutTests/imported/%s' % repo]) 99 100 self.print_('## deleting any orphaned baselines') 101 previous_baselines = self.fs.files_under(dest_repo, file_filter=self.is_baseline) 102 for subpath in previous_baselines: 103 full_path = self.fs.join(dest_repo, subpath) 104 if self.fs.glob(full_path.replace('-expected.txt', '*')) == [full_path]: 105 self.fs.remove(full_path) 106 107 if not self.keep_w3c_repos_around: 108 self.print_('## deleting %s repo' % repo) 109 self.cd('') 110 self.rmtree(repo) 111 112 return 'imported %s@%s' % (repo, master_commitish) 113 114 def commit_changes_if_needed(self, blink_commitish, css_import_text, wpt_import_text): 115 if self.run(['git', 'diff', '--quiet', 'HEAD'], exit_on_failure=False)[0]: 116 self.print_('## commiting changes') 117 commit_msg = ('update-w3c-deps import using blink %s:\n' 118 '\n' 119 '%s\n' 120 '%s\n' % (blink_commitish, css_import_text, wpt_import_text)) 121 path_to_commit_msg = self.path_from_webkit_base('commit_msg') 122 if self.verbose: 123 self.print_('cat > %s <<EOF' % path_to_commit_msg) 124 self.print_(commit_msg) 125 self.print_('EOF') 126 self.fs.write_text_file(path_to_commit_msg, commit_msg) 127 self.run(['git', 'commit', '-a', '-F', path_to_commit_msg]) 128 self.remove(path_to_commit_msg) 129 self.print_('## Done: changes imported and committed') 130 else: 131 self.print_('## Done: no changes to import') 132 133 def is_baseline(self, fs, dirname, basename): 134 return basename.endswith('-expected.txt') 135 136 def is_not_baseline(self, fs, dirname, basename): 137 return not self.is_baseline(fs, dirname, basename) 138 139 def run(self, cmd, exit_on_failure=True): 140 if self.verbose: 141 self.print_(' '.join(cmd)) 142 143 proc = self.executive.popen(cmd, stdout=self.executive.PIPE, stderr=self.executive.PIPE) 144 out, err = proc.communicate() 145 if proc.returncode or self.verbose: 146 self.print_('# ret> %d' % proc.returncode) 147 if out: 148 for line in out.splitlines(): 149 self.print_('# out> %s' % line) 150 if err: 151 for line in err.splitlines(): 152 self.print_('# err> %s' % line) 153 if exit_on_failure and proc.returncode: 154 self.host.exit(proc.returncode) 155 return proc.returncode, out 156 157 def cd(self, *comps): 158 dest = self.path_from_webkit_base(*comps) 159 if self.verbose: 160 self.print_('cd %s' % dest) 161 self.fs.chdir(dest) 162 163 def remove(self, *comps): 164 dest = self.path_from_webkit_base(*comps) 165 if self.verbose: 166 self.print_('rm %s' % dest) 167 self.fs.remove(dest) 168 169 def rmtree(self, *comps): 170 dest = self.path_from_webkit_base(*comps) 171 if self.verbose: 172 self.print_('rm -fr %s' % dest) 173 self.fs.rmtree(dest) 174 175 def path_from_webkit_base(self, *comps): 176 return self.finder.path_from_webkit_base(*comps) 177 178 def print_(self, msg): 179 self.host.print_(msg) 180