| # Copyright 2016 The Chromium Authors. All rights reserved. | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| from webkitpy.w3c.chromium_finder import absolute_chromium_dir, absolute_chromium_wpt_dir | |
| CHROMIUM_WPT_DIR = 'third_party/WebKit/LayoutTests/external/wpt/' | |
| class ChromiumCommit(object): | |
| def __init__(self, host, sha=None, position=None): | |
| """ | |
| Args: | |
| host: A Host object | |
| sha: A Chromium commit SHA | |
| position: A string of the form: | |
| 'Cr-Commit-Position: refs/heads/master@{#431915}' | |
| or just: | |
| 'refs/heads/master@{#431915}' | |
| """ | |
| self.host = host | |
| self.absolute_chromium_dir = absolute_chromium_dir(host) | |
| self.absolute_chromium_wpt_dir = absolute_chromium_wpt_dir(host) | |
| assert sha or position, 'requires sha or position' | |
| assert not (sha and position), 'cannot accept both sha and position' | |
| if position and not sha: | |
| if position.startswith('Cr-Commit-Position: '): | |
| position = position[len('Cr-Commit-Position: '):] | |
| sha = self.position_to_sha(position) | |
| assert len(sha) == 40, 'Expected SHA-1 hash, got {}'.format(sha) | |
| self.sha = sha | |
| self.position = position | |
| def num_behind_master(self): | |
| """Returns the number of commits this commit is behind origin/master. | |
| It is inclusive of this commit and of the latest commit. | |
| """ | |
| return len(self.host.executive.run_command([ | |
| 'git', 'rev-list', '{}..origin/master'.format(self.sha) | |
| ], cwd=self.absolute_chromium_dir).splitlines()) | |
| def position_to_sha(self, commit_position): | |
| return self.host.executive.run_command([ | |
| 'git', 'crrev-parse', commit_position | |
| ], cwd=self.absolute_chromium_dir).strip() | |
| def subject(self): | |
| return self.host.executive.run_command([ | |
| 'git', 'show', '--format=%s', '--no-patch', self.sha | |
| ], cwd=self.absolute_chromium_dir) | |
| def body(self): | |
| return self.host.executive.run_command([ | |
| 'git', 'show', '--format=%b', '--no-patch', self.sha | |
| ], cwd=self.absolute_chromium_dir) | |
| def author(self): | |
| return self.host.executive.run_command([ | |
| 'git', 'show', '--format="%aN <%aE>"', '--no-patch', self.sha | |
| ], cwd=self.absolute_chromium_dir) | |
| def message(self): | |
| """Returns a string with a commit's subject and body.""" | |
| return self.host.executive.run_command([ | |
| 'git', 'show', '--format=%B', '--no-patch', self.sha | |
| ], cwd=self.absolute_chromium_dir) | |
| def filtered_changed_files(self): | |
| """Makes a patch with just changes in files in the WPT dir for a given commit.""" | |
| changed_files = self.host.executive.run_command([ | |
| 'git', 'diff-tree', '--name-only', '--no-commit-id', '-r', self.sha, | |
| '--', self.absolute_chromium_wpt_dir | |
| ], cwd=self.absolute_chromium_dir).splitlines() | |
| blacklist = [ | |
| 'MANIFEST.json', | |
| self.host.filesystem.join('resources', 'testharnessreport.js'), | |
| ] | |
| qualified_blacklist = [CHROMIUM_WPT_DIR + f for f in blacklist] | |
| return [f for f in changed_files if f not in qualified_blacklist and not self.is_baseline(f)] | |
| @staticmethod | |
| def is_baseline(basename): | |
| # TODO(qyearsley): Find a better, centralized place for this. | |
| return basename.endswith('-expected.txt') | |
| def format_patch(self): | |
| """Makes a patch with only exportable changes.""" | |
| filtered_files = self.filtered_changed_files() | |
| if not filtered_files: | |
| return '' | |
| return self.host.executive.run_command([ | |
| 'git', 'format-patch', '-1', '--stdout', self.sha, '--' | |
| ] + filtered_files, cwd=self.absolute_chromium_dir) |