Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # 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
| |
| 2 | |
| 3 from webkitpy.common.host import Host | |
| 4 from webkitpy.common.webkit_finder import WebKitFinder | |
| 5 import argparse | |
| 6 import re | |
| 7 import os | |
| 8 | |
| 9 | |
| 10 WPT_REPO_URL = 'https://chromium.googlesource.com/external/w3c/web-platform-test s.git' | |
| 11 WPT_DEST_NAME = 'wpt' | |
| 12 CR_WPT_DIR = 'third_party/WebKit/LayoutTests/imported/wpt/' | |
| 13 OLDEST_POSSIBLE_WPT_COMMIT = 'f2f9d854afdf0e9973c3bc4138ea41566bca2ef2' | |
| 14 OLDEST_POSSIBLE_CR_COMMIT = '04ad58d09c1f6c46e888e42030b0566ac65411f6' # before which no exporting should happen | |
| 15 | |
| 16 # Thoughts | |
| 17 # - 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
| |
| 18 # - Maybe create a LocalWPT class? LocalWPT.clean(), LocalWPT.apply_patch() | |
| 19 # - Idea: could use `with local_wpt(dir):` to manage setup/teardown | |
| 20 | |
| 21 | |
| 22 class TestExporter(object): | |
| 23 | |
| 24 def __init__(self, host, options): | |
| 25 self.host = host | |
| 26 self.options = options | |
| 27 self.fs = self.host.filesystem | |
| 28 self.finder = WebKitFinder(self.host.filesystem) | |
| 29 self.temp_repo_path = self.finder.path_from_webkit_base(WPT_DEST_NAME) | |
| 30 | |
| 31 def run(self): | |
| 32 | |
| 33 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
| |
| 34 self.pull_down_local_wpt() | |
| 35 | |
| 36 cr_export_commit = self.find_most_recent_wpt_export() | |
| 37 | |
| 38 if cr_export_commit: | |
| 39 cr_commits = self.cr_commits_since(cr_export_commit) | |
| 40 | |
| 41 def has_changes_in_wpt(commit): | |
| 42 assert commit | |
| 43 | |
| 44 diff_files = self.host.executive.run_command([ | |
| 45 'git', 'diff-tree', '--no-commit-id', | |
| 46 '--name-only', '-r', '{}'.format(commit)]) | |
| 47 | |
| 48 files = filter(bool, diff_files.split('\n')) | |
| 49 # Include files in LayoutTests/imported/wpt but not those with e xpectations | |
| 50 return any([CR_WPT_DIR in f and '-expected' not in f for f in fi les]) | |
|
foolip
2016/10/25 19:31:41
Maybe more strictly require the path to begin with
| |
| 51 | |
| 52 exportable_commits = filter(has_changes_in_wpt, cr_commits) | |
| 53 | |
| 54 self.host.print_('## Found %d exportable commits in Chromium!' % len (exportable_commits)) | |
| 55 | |
| 56 for commit in exportable_commits: | |
| 57 # create da PR | |
| 58 # generate the patch | |
| 59 abs_cr_wpt_dir = os.path.abspath(os.path.join('..', '..', 'Layou tTests', 'imported', 'wpt')) | |
| 60 # Get patch but only for files in LayoutTests/imported/wpt | |
| 61 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
| |
| 62 'git', 'format-patch', '-1', '--stdout', '{}'.format(commit) , abs_cr_wpt_dir]) | |
| 63 | |
| 64 self.run_command_in_wpt(['git', 'reset', '--hard', 'HEAD']) | |
| 65 self.run_command_in_wpt(['git', 'checkout', 'master']) | |
| 66 branch_name = 'chromium-try-{}'.format(commit) | |
| 67 remote_branch_name = 'remotes/github/%s' % branch_name | |
| 68 | |
| 69 all_branches = map(str.strip, self.run_command_in_wpt(['git', 'b ranch', '-a']).split('\n')) | |
| 70 | |
| 71 if branch_name in all_branches: | |
| 72 self.host.print_('## Local branch %s already exists, skippin g' % branch_name) | |
| 73 continue | |
| 74 # delete? | |
| 75 # self.run_command_in_wpt(['git', 'branch', '-D', branch_nam e]) | |
| 76 | |
| 77 if remote_branch_name in all_branches: | |
| 78 self.host.print_('## Remote branch %s already exists, skippi ng' % branch_name) | |
| 79 continue | |
| 80 | |
| 81 self.host.print_('## Creating local branch %s' % branch_name) | |
| 82 self.run_command_in_wpt(['git', 'checkout', '-b', branch_name]) | |
| 83 | |
| 84 # Remove Chromium WPT directory prefix | |
| 85 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_
| |
| 86 self.run_command_in_wpt(['git', 'apply', '-'], input=patch) | |
| 87 | |
| 88 self.run_command_in_wpt(['git', 'commit', '-am', 'Testing export from Chromium']) | |
| 89 self.run_command_in_wpt(['git', 'push', 'github', branch_name]) | |
| 90 | |
| 91 # create PR on GH | |
| 92 | |
| 93 def run_command_in_wpt(self, command, **kwargs): | |
| 94 return self.host.executive.run_command(command, cwd=self.temp_repo_path, **kwargs) | |
| 95 | |
| 96 def pull_down_local_wpt(self): | |
| 97 url = WPT_REPO_URL | |
| 98 | |
| 99 if self.fs.exists(self.temp_repo_path): | |
| 100 self.host.print_('## WPT checkout exists at %s, fetching latest' % ( self.temp_repo_path)) | |
| 101 self.run_command_in_wpt(['git', 'checkout', 'master']) | |
| 102 self.run_command_in_wpt(['git', 'fetch', '--all']) | |
| 103 self.run_command_in_wpt(['git', 'merge', '--ff-only', 'origin/master ']) | |
| 104 else: | |
| 105 self.host.print_('## Cloning %s into %s' % (url, self.temp_repo_path )) | |
| 106 self.host.executive.run_command(['git', 'clone', url, self.temp_repo _path]) | |
| 107 | |
| 108 def find_most_recent_wpt_export(self): | |
| 109 # The diff for the entire history of WPT is 3MB, which works fine for no w | |
|
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
| |
| 110 # (Picked a random commit) | |
| 111 diff_output = self.host.executive.run_command([ | |
| 112 'git', 'log', '1d81fe1feb8f9dc43bc101a4cf9d755fdf4df0e7..HEAD' | |
|
foolip
2016/10/25 19:31:41
Could use OLDEST_POSSIBLE_WPT_COMMIT here too?
| |
| 113 ], cwd=self.temp_repo_path) | |
| 114 | |
| 115 commit_messages = diff_output.split('\ncommit ') | |
| 116 | |
| 117 for message in commit_messages: | |
| 118 commit = message.split('\n')[0].replace('commit ', '') | |
| 119 if commit == OLDEST_POSSIBLE_WPT_COMMIT: | |
| 120 self.host.print_('## Reached oldest possible WPT before finding a Chromium export, stopping') | |
| 121 return None | |
| 122 elif 'Cr-Commit-Position' in message: | |
| 123 match = re.match(r'Cr-Commit-Position: (?P<cr_commit>.+)$', mess age) | |
| 124 cr_commit = match.group('cr_commit') | |
| 125 if cr_commit: | |
| 126 self.host.print_('## Found last exported commit: web-platfor m-tests@%s crrev: %s' % commit, cr_commit) | |
| 127 return cr_commit | |
| 128 elif 'testharness' in message: | |
| 129 # Fake case for testing | |
| 130 return OLDEST_POSSIBLE_CR_COMMIT | |
| 131 | |
| 132 def cr_commits_since(self, cr_commit): | |
| 133 commits = self.host.executive.run_command([ | |
| 134 '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.
| |
| 135 return filter(bool, commits.split('\n')) | |
| 136 | |
| 137 | |
| 138 def main(): | |
| 139 parser = argparse.ArgumentParser(description='WPT bridge bot') | |
| 140 | |
| 141 parser.add_argument('--no-fetch', action='store_true') | |
| 142 | |
| 143 options = parser.parse_args() | |
| 144 test_exporter = TestExporter(host=Host(), options=options) | |
| 145 test_exporter.run() | |
| OLD | NEW |