Chromium Code Reviews| Index: third_party/crashpad/update.py |
| diff --git a/third_party/crashpad/update.py b/third_party/crashpad/update.py |
| new file mode 100755 |
| index 0000000000000000000000000000000000000000..ed4ec7bc17dc4da875368d5767a5fea08ceedb5b |
| --- /dev/null |
| +++ b/third_party/crashpad/update.py |
| @@ -0,0 +1,188 @@ |
| +#!/usr/bin/env python |
| +# coding: utf-8 |
| + |
| +# Copyright 2015 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. |
| + |
| +import argparse |
| +import os |
| +import re |
| +import subprocess |
| +import sys |
| +import textwrap |
| + |
| + |
| +def main(args): |
| + parser = argparse.ArgumentParser( |
| + description='Update the in-tree copy of an imported project') |
| + parser.add_argument( |
| + '--project', |
| + help='The imported project name, used for the git remote name', |
| + metavar='PROJECT') |
| + parser.add_argument( |
| + '--repository', |
| + default='https://chromium.googlesource.com/crashpad/crashpad', |
| + help='The imported project\'s remote fetch URL', |
| + metavar='URL') |
| + parser.add_argument( |
| + '--subtree', |
| + default='third_party/crashpad/crashpad', |
| + help='The imported project\'s location in this project\'s tree', |
| + metavar='PATH') |
| + parser.add_argument( |
| + '--update-to', |
| + help='What to update the imported project to', |
| + metavar='COMMITISH') |
| + parser.add_argument( |
| + '--readme', |
| + help='The README.chromium file describing the imported project', |
| + metavar='FILE', |
| + dest='readme_path') |
| + parser.add_argument( |
| + '--keep-remote', |
| + default='default', |
| + choices=['default', 'no', 'yes'], |
| + help='Whether to keep the imported project\'s remote when done') |
| + parsed = parser.parse_args(args) |
| + |
| + original_head = \ |
|
Primiano Tucci (use gerrit)
2015/12/10 09:31:21
I think our coding style is more in favor of paren
Mark Mentovai
2015/12/10 15:13:55
Primiano Tucci wrote:
|
| + subprocess.check_output(['git', 'rev-parse', 'HEAD']).rstrip() |
| + |
| + # Read the README, because that’s what it’s for. Extract a few things from |
| + # it, and save it to be able to update it later. |
| + readme_path = parsed.readme_path or \ |
| + os.path.join(os.path.dirname(__file__ or '.'), 'README.chromium') |
| + readme_content_old = open(readme_path).read() |
| + |
| + project_name_match = re.search( |
| + r'^Name:\s+(.*)$', readme_content_old, re.MULTILINE) |
| + project_name = project_name_match.group(1) |
| + |
| + project_shortname_match = re.search( |
| + r'^Short Name:\s+(.*)$', readme_content_old, re.MULTILINE) |
| + project_shortname = project_shortname_match.group(1) |
| + |
| + # Extract the original commit hash from the README. |
| + revision_match = re.search(r'^Revision:\s+([0-9a-fA-F]{40})($|\s)', |
| + readme_content_old, |
| + re.MULTILINE) |
| + revision_old = revision_match.group(1) |
| + |
| + project = parsed.project or project_shortname |
| + |
| + added_remote = False |
| + try: |
| + # The remote might already exist. Check for it first, and make sure the |
|
Primiano Tucci (use gerrit)
2015/12/10 09:31:21
you don't need to add the remote here.
I think wha
Mark Mentovai
2015/12/10 15:13:55
Primiano Tucci wrote:
Primiano Tucci (use gerrit)
2015/12/10 15:26:13
git rev-parse FETCH_HEAD will always give you a sh
Mark Mentovai
2015/12/10 15:31:28
Sure, but if I say update.py --update-to=6789abcd,
Mark Mentovai
2015/12/10 15:50:01
I wrote:
Primiano Tucci (use gerrit)
2015/12/10 15:53:57
Ahh that's the part I was missing. I think the ans
|
| + # URL matches what was specified. |
| + remote_url = subprocess.check_output( |
| + ['git', 'config', '--local', 'remote.' + project + '.url']).rstrip() |
| + if remote_url != parsed.repository: |
| + raise Exception( |
| + 'repository mismatch', parsed.repository, remote_url) |
| + except subprocess.CalledProcessError as e: |
| + if e.returncode == 1: |
| + # The remote doesn’t exist. Add it. |
| + subprocess.check_call( |
| + ['git', 'remote', 'add', project, parsed.repository]) |
| + added_remote = True |
| + |
| + subprocess.check_call(['git', 'fetch', project]) |
| + |
| + commitish_new = parsed.update_to or project + '/master' |
|
Primiano Tucci (use gerrit)
2015/12/10 09:31:21
and this would become FETCH_HEAD
Mark Mentovai
2015/12/10 15:13:55
Primiano Tucci wrote:
|
| + update_range = revision_old + '..' + commitish_new |
| + |
| + # This cherry-picks each change in the window from the upstream project into |
| + # the current branch. |
| + subprocess.check_call(['git', |
|
Primiano Tucci (use gerrit)
2015/12/10 09:31:21
Not necessary for this CL: I think you want to be
Mark Mentovai
2015/12/10 15:16:01
Primiano Tucci wrote:
Mark Mentovai
2015/12/10 20:08:50
Did this now.
|
| + 'cherry-pick', |
| + '--keep-redundant', |
|
Primiano Tucci (use gerrit)
2015/12/10 09:31:21
Isn't this --keep-redundant-commits (with -commits
Mark Mentovai
2015/12/10 15:13:55
Primiano Tucci wrote:
Primiano Tucci (use gerrit)
2015/12/10 15:26:13
ah ok. I never figured out how git really does pat
|
| + '--strategy=subtree', |
| + '-Xsubtree=' + parsed.subtree, |
| + '-x', |
| + update_range]) |
| + |
| + # Make a nice commit message. Start with the full commit hash. |
| + revision_new = subprocess.check_output( |
| + ['git', 'rev-parse', commitish_new]).rstrip() |
| + new_message = 'Update ' + project_name + ' to ' + revision_new + '\n\n' |
| + |
| + # Get an abbreviated hash and subject line for each commit in the window, |
| + # sorted in chronological order. Wrap everything to 72 characters, with a |
| + # hanging indent. |
| + log_lines = subprocess.check_output(['git', |
| + '-c', |
| + 'core.abbrev=12', |
| + 'log', |
| + '--abbrev-commit', |
| + '--pretty=oneline', |
| + '--reverse', |
| + update_range]).splitlines(False) |
| + wrapper = textwrap.TextWrapper(width=72, subsequent_indent = ' ' * 13) |
| + for line in log_lines: |
| + # Strip trailing periods from subjects. |
|
Primiano Tucci (use gerrit)
2015/12/10 09:31:21
such classy :)
Mark Mentovai
2015/12/10 15:13:55
Primiano Tucci wrote:
|
| + if line.endswith('.'): |
| + line = line[:-1] |
| + |
| + # If any subjects have what look like commit hashes in them, truncate |
| + # them to 12 characters. |
| + line = re.sub(r'(\s)([0-9a-fA-F]{12})([0-9a-fA-F]{28})($|\s)', |
|
Primiano Tucci (use gerrit)
2015/12/10 09:31:21
Hmm dunno about this. This would make copy / grepp
Mark Mentovai
2015/12/10 15:13:55
Primiano Tucci wrote:
|
| + r'\1\2\4', |
| + line) |
| + |
| + new_message += '\n'.join(wrapper.wrap(line)) + '\n' |
| + |
| + # Update the README with the new hash. |
| + readme_content_new = re.sub( |
| + r'^(Revision:\s+)([0-9a-fA-F]{40})($|\s.*?$)', |
| + r'\g<1>' + revision_new, |
| + readme_content_old, |
| + 1, |
| + re.MULTILINE) |
| + |
| + # If the in-tree copy has no changes relative to the upstream, clear the |
| + # “Local Modifications” section of the README. |
| + has_local_modifications = True |
| + try: |
| + subprocess.check_call(['git', |
| + 'diff-tree', |
| + '--quiet', |
| + commitish_new, |
| + 'HEAD:' + parsed.subtree]) |
| + has_local_modifications = False |
| + readme_content_new = re.sub(r'\nLocal Modifications:\n.*$', |
| + '\nLocal Modifications:\nNone.', |
| + readme_content_new, |
| + 1) |
| + except subprocess.CalledProcessError, e: |
| + # If the return code is 1, swallow the exception. There are local |
| + # modifications. |
| + if e.returncode != 1: |
| + raise |
| + |
| + # This soft-reset causes all of the cherry-picks to show up as staged, |
| + # which will have the effect of squashing them along with the README update |
| + # when committed below. |
| + subprocess.check_call(['git', 'reset', '--soft', original_head]) |
| + |
| + # Remove the remote if desired. |
| + if parsed.keep_remote == 'no' or \ |
| + (parsed.keep_remote == 'default' and added_remote): |
| + subprocess.check_call(['git', 'remote', 'remove', project]) |
| + |
| + # Write the new README. |
| + open(readme_path, 'w').write(readme_content_new) |
| + |
| + # Commit everything. |
| + subprocess.check_call(['git', 'add', readme_path]) |
| + subprocess.check_call(['git', 'commit', '--message=' + new_message]) |
| + |
| + if has_local_modifications: |
| + print 'Remember to check the Local Modifications section in ' + \ |
| + readme_path |
| + |
| + return 0 |
| + |
| + |
| +if __name__ == '__main__': |
| + sys.exit(main(sys.argv[1:])) |