Chromium Code Reviews| Index: third_party/WebKit/Tools/Scripts/webkitpy/w3c/sync.py |
| diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/sync.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/sync.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..fd649f8b61c2c30f41031004db547bb139564e36 |
| --- /dev/null |
| +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/sync.py |
| @@ -0,0 +1,145 @@ |
| +# TODO: Do we need a license at the top of the file? |
|
foolip
2016/10/25 19:31:41
Yep, and the other one too. Use the short one wit
|
| + |
| +from webkitpy.common.host import Host |
| +from webkitpy.common.webkit_finder import WebKitFinder |
| +import argparse |
| +import re |
| +import os |
| + |
| + |
| +WPT_REPO_URL = 'https://chromium.googlesource.com/external/w3c/web-platform-tests.git' |
| +WPT_DEST_NAME = 'wpt' |
| +CR_WPT_DIR = 'third_party/WebKit/LayoutTests/imported/wpt/' |
| +OLDEST_POSSIBLE_WPT_COMMIT = 'f2f9d854afdf0e9973c3bc4138ea41566bca2ef2' |
| +OLDEST_POSSIBLE_CR_COMMIT = '04ad58d09c1f6c46e888e42030b0566ac65411f6' # before which no exporting should happen |
| + |
| +# Thoughts |
| +# - I feel like it would be cleaner to create the local WPT checkout outside of the local Chromium working tree. e.g. /tmp/wpt |
|
foolip
2016/10/25 19:31:41
Is this now doing the same thing as the importer,
jeffcarp
2016/10/26 20:19:17
It's currently putting the tests in third_party/We
|
| +# - Maybe create a LocalWPT class? LocalWPT.clean(), LocalWPT.apply_patch() |
| +# - Idea: could use `with local_wpt(dir):` to manage setup/teardown |
| + |
| + |
| +class TestExporter(object): |
| + |
| + def __init__(self, host, options): |
| + self.host = host |
| + self.options = options |
| + self.fs = self.host.filesystem |
| + self.finder = WebKitFinder(self.host.filesystem) |
| + self.temp_repo_path = self.finder.path_from_webkit_base(WPT_DEST_NAME) |
| + |
| + def run(self): |
| + |
| + if not self.options['no_fetch']: |
|
foolip
2016/10/25 19:31:41
I can't see where this is hooked up, but I guess t
jeffcarp
2016/10/26 20:19:17
Down on line 141 of this file there's an arg parse
|
| + self.pull_down_local_wpt() |
| + |
| + cr_export_commit = self.find_most_recent_wpt_export() |
| + |
| + if cr_export_commit: |
| + cr_commits = self.cr_commits_since(cr_export_commit) |
| + |
| + def has_changes_in_wpt(commit): |
| + assert commit |
| + |
| + diff_files = self.host.executive.run_command([ |
| + 'git', 'diff-tree', '--no-commit-id', |
| + '--name-only', '-r', '{}'.format(commit)]) |
| + |
| + files = filter(bool, diff_files.split('\n')) |
| + # Include files in LayoutTests/imported/wpt but not those with expectations |
| + return any([CR_WPT_DIR in f and '-expected' not in f for f in files]) |
|
foolip
2016/10/25 19:31:41
Maybe more strictly require the path to begin with
|
| + |
| + exportable_commits = filter(has_changes_in_wpt, cr_commits) |
| + |
| + self.host.print_('## Found %d exportable commits in Chromium!' % len(exportable_commits)) |
| + |
| + for commit in exportable_commits: |
| + # create da PR |
| + # generate the patch |
| + abs_cr_wpt_dir = os.path.abspath(os.path.join('..', '..', 'LayoutTests', 'imported', 'wpt')) |
| + # Get patch but only for files in LayoutTests/imported/wpt |
| + patch = self.host.executive.run_command([ |
|
foolip
2016/10/25 19:31:41
Being able to get this patch on stdout or into a f
|
| + 'git', 'format-patch', '-1', '--stdout', '{}'.format(commit), abs_cr_wpt_dir]) |
| + |
| + self.run_command_in_wpt(['git', 'reset', '--hard', 'HEAD']) |
| + self.run_command_in_wpt(['git', 'checkout', 'master']) |
| + branch_name = 'chromium-try-{}'.format(commit) |
| + remote_branch_name = 'remotes/github/%s' % branch_name |
| + |
| + all_branches = map(str.strip, self.run_command_in_wpt(['git', 'branch', '-a']).split('\n')) |
| + |
| + if branch_name in all_branches: |
| + self.host.print_('## Local branch %s already exists, skipping' % branch_name) |
| + continue |
| + # delete? |
| + # self.run_command_in_wpt(['git', 'branch', '-D', branch_name]) |
| + |
| + if remote_branch_name in all_branches: |
| + self.host.print_('## Remote branch %s already exists, skipping' % branch_name) |
| + continue |
| + |
| + self.host.print_('## Creating local branch %s' % branch_name) |
| + self.run_command_in_wpt(['git', 'checkout', '-b', branch_name]) |
| + |
| + # Remove Chromium WPT directory prefix |
| + patch = patch.replace(CR_WPT_DIR, '') |
|
foolip
2016/10/25 19:31:41
Could also use git am -p<n> where n is len(CR_WPT_
|
| + self.run_command_in_wpt(['git', 'apply', '-'], input=patch) |
| + |
| + self.run_command_in_wpt(['git', 'commit', '-am', 'Testing export from Chromium']) |
| + self.run_command_in_wpt(['git', 'push', 'github', branch_name]) |
| + |
| + # create PR on GH |
| + |
| + def run_command_in_wpt(self, command, **kwargs): |
| + return self.host.executive.run_command(command, cwd=self.temp_repo_path, **kwargs) |
| + |
| + def pull_down_local_wpt(self): |
| + url = WPT_REPO_URL |
| + |
| + if self.fs.exists(self.temp_repo_path): |
| + self.host.print_('## WPT checkout exists at %s, fetching latest' % (self.temp_repo_path)) |
| + self.run_command_in_wpt(['git', 'checkout', 'master']) |
| + self.run_command_in_wpt(['git', 'fetch', '--all']) |
| + self.run_command_in_wpt(['git', 'merge', '--ff-only', 'origin/master']) |
| + else: |
| + self.host.print_('## Cloning %s into %s' % (url, self.temp_repo_path)) |
| + self.host.executive.run_command(['git', 'clone', url, self.temp_repo_path]) |
| + |
| + def find_most_recent_wpt_export(self): |
| + # The diff for the entire history of WPT is 3MB, which works fine for now |
|
foolip
2016/10/25 19:31:41
Works for now. Later, maybe git rev-list OLDEST_PO
jeffcarp
2016/10/26 22:06:12
I had a possibly even simpler idea: why not just c
foolip
2016/10/26 22:34:36
That'd require you to parse out the commit to term
|
| + # (Picked a random commit) |
| + diff_output = self.host.executive.run_command([ |
| + 'git', 'log', '1d81fe1feb8f9dc43bc101a4cf9d755fdf4df0e7..HEAD' |
|
foolip
2016/10/25 19:31:41
Could use OLDEST_POSSIBLE_WPT_COMMIT here too?
|
| + ], cwd=self.temp_repo_path) |
| + |
| + commit_messages = diff_output.split('\ncommit ') |
| + |
| + for message in commit_messages: |
| + commit = message.split('\n')[0].replace('commit ', '') |
| + if commit == OLDEST_POSSIBLE_WPT_COMMIT: |
| + self.host.print_('## Reached oldest possible WPT before finding a Chromium export, stopping') |
| + return None |
| + elif 'Cr-Commit-Position' in message: |
| + match = re.match(r'Cr-Commit-Position: (?P<cr_commit>.+)$', message) |
| + cr_commit = match.group('cr_commit') |
| + if cr_commit: |
| + self.host.print_('## Found last exported commit: web-platform-tests@%s crrev: %s' % commit, cr_commit) |
| + return cr_commit |
| + elif 'testharness' in message: |
| + # Fake case for testing |
| + return OLDEST_POSSIBLE_CR_COMMIT |
| + |
| + def cr_commits_since(self, cr_commit): |
| + commits = self.host.executive.run_command([ |
| + 'git', 'rev-list', '{}..HEAD'.format(cr_commit)]) |
|
foolip
2016/10/25 19:31:41
Will this not need --reverse to test them in the r
jeffcarp
2016/10/26 20:19:17
Ah thanks for catching that.
|
| + return filter(bool, commits.split('\n')) |
| + |
| + |
| +def main(): |
| + parser = argparse.ArgumentParser(description='WPT bridge bot') |
| + |
| + parser.add_argument('--no-fetch', action='store_true') |
| + |
| + options = parser.parse_args() |
| + test_exporter = TestExporter(host=Host(), options=options) |
| + test_exporter.run() |