131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com#!/usr/bin/python2
231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com# Copyright 2014 Google Inc.
431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com#
531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com# Use of this source code is governed by a BSD-style license that can be
631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com# found in the LICENSE file.
731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com"""Skia's Chromium DEPS roll script.
931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
1031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comThis script:
1131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com- searches through the last N Skia git commits to find out the hash that is
1231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com  associated with the SVN revision number.
1331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com- creates a new branch in the Chromium tree, modifies the DEPS file to
1431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com  point at the given Skia commit, commits, uploads to Rietveld, and
1531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com  deletes the local copy of the branch.
1631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com- creates a whitespace-only commit and uploads that to to Rietveld.
1731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com- returns the Chromium tree to its previous state.
1831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
190ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.orgTo specify the location of the git executable, set the GIT_EXECUTABLE
200ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.orgenvironment variable.
210ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
2231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comUsage:
2331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com  %prog -c CHROMIUM_PATH -r REVISION [OPTIONAL_OPTIONS]
2431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com"""
2531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
2631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
2731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comimport optparse
2831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comimport os
2931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comimport re
3031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comimport shutil
3131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comimport subprocess
3231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comimport sys
3331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comimport tempfile
3431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
350ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.orgimport git_utils
360ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.orgimport misc_utils
370ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
3917bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.comDEFAULT_BOTS_LIST = [
4017bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'android_clang_dbg',
4117bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'android_dbg',
4217bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'android_rel',
4317bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'cros_daisy',
4417bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'linux',
4517bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'linux_asan',
4617bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'linux_chromeos',
4717bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'linux_chromeos_asan',
48a94866d1537fbb3a976f5f846002b45a7f182aa0commit-bot@chromium.org    'linux_chromium_gn_dbg',
4917bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'linux_gpu',
5017bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'linux_layout',
5117bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'linux_layout_rel',
5217bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'mac',
5317bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'mac_asan',
5417bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'mac_gpu',
5517bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'mac_layout',
5617bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'mac_layout_rel',
5717bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'win',
5817bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'win_gpu',
5917bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'win_layout',
6017bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com    'win_layout_rel',
6117bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com]
6217bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com
6317bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com
6431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comclass DepsRollConfig(object):
6531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """Contains configuration options for this module.
6631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
6731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Attributes:
6831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        git: (string) The git executable.
6931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        chromium_path: (string) path to a local chromium git repository.
7031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        save_branches: (boolean) iff false, delete temporary branches.
7131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        verbose: (boolean)  iff false, suppress the output from git-cl.
7231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        search_depth: (int) how far back to look for the revision.
7331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        skia_url: (string) Skia's git repository.
7431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        self.skip_cl_upload: (boolean)
7531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        self.cl_bot_list: (list of strings)
7631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """
7731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
7831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    # pylint: disable=I0011,R0903,R0902
7931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    def __init__(self, options=None):
8031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        self.skia_url = 'https://skia.googlesource.com/skia.git'
8131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        self.revision_format = (
8231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            'git-svn-id: http://skia.googlecode.com/svn/trunk@%d ')
8331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
840ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        self.git = git_utils.git_executable()
850ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
8631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        if not options:
8731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            options = DepsRollConfig.GetOptionParser()
8831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        # pylint: disable=I0011,E1103
8931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        self.verbose = options.verbose
900ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        self.vsp = misc_utils.VerboseSubprocess(self.verbose)
918c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        self.save_branches = not options.delete_branches
9231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        self.search_depth = options.search_depth
9331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        self.chromium_path = options.chromium_path
9431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        self.skip_cl_upload = options.skip_cl_upload
9531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        # Split and remove empty strigns from the bot list.
9631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        self.cl_bot_list = [bot for bot in options.bots.split(',') if bot]
9731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        self.skia_git_checkout_path = options.skia_git_path
9831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        self.default_branch_name = 'autogenerated_deps_roll_branch'
9934f47f9e7c0dec305a73e044cdf893315c489ff7commit-bot@chromium.org        self.reviewers_list = ','.join([
10034f47f9e7c0dec305a73e044cdf893315c489ff7commit-bot@chromium.org            # 'rmistry@google.com',
10134f47f9e7c0dec305a73e044cdf893315c489ff7commit-bot@chromium.org            # 'reed@google.com',
10234f47f9e7c0dec305a73e044cdf893315c489ff7commit-bot@chromium.org            # 'bsalomon@google.com',
10334f47f9e7c0dec305a73e044cdf893315c489ff7commit-bot@chromium.org            # 'robertphillips@google.com',
10434f47f9e7c0dec305a73e044cdf893315c489ff7commit-bot@chromium.org            ])
1050ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        self.cc_list = ','.join([
10634f47f9e7c0dec305a73e044cdf893315c489ff7commit-bot@chromium.org            # 'skia-team@google.com',
10734f47f9e7c0dec305a73e044cdf893315c489ff7commit-bot@chromium.org            ])
10831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
10931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    @staticmethod
11031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    def GetOptionParser():
11131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        # pylint: disable=I0011,C0103
11231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        """Returns an optparse.OptionParser object.
11331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
11431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        Returns:
11531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            An optparse.OptionParser object.
11631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
11731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        Called by the main() function.
11831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        """
11931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser = optparse.OptionParser(usage=__doc__)
12031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        # Anyone using this script on a regular basis should set the
12131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        # CHROMIUM_CHECKOUT_PATH environment variable.
12231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser.add_option(
12331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            '-c', '--chromium_path', help='Path to local Chromium Git'
12431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            ' repository checkout, defaults to CHROMIUM_CHECKOUT_PATH'
12531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            ' if that environment variable is set.',
12631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            default=os.environ.get('CHROMIUM_CHECKOUT_PATH'))
12731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser.add_option(
12831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            '-r', '--revision', type='int', default=None,
12931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            help='The Skia SVN revision number, defaults to top of tree.')
1308c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        option_parser.add_option(
1318c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            '-g', '--git_hash', default=None,
1328c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            help='A partial Skia Git hash.  Do not set this and revision.')
1338c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
13431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        # Anyone using this script on a regular basis should set the
13531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        # SKIA_GIT_CHECKOUT_PATH environment variable.
13631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser.add_option(
13731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            '', '--skia_git_path',
13831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            help='Path of a pure-git Skia repository checkout.  If empty,'
13931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            ' a temporary will be cloned.  Defaults to SKIA_GIT_CHECKOUT'
14031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            '_PATH, if that environment variable is set.',
14131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            default=os.environ.get('SKIA_GIT_CHECKOUT_PATH'))
14231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser.add_option(
14331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            '', '--search_depth', type='int', default=100,
14431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            help='How far back to look for the revision.')
14531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser.add_option(
1468c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            '', '--delete_branches', help='Delete the temporary branches',
1478c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            action='store_true', dest='delete_branches', default=False)
14831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser.add_option(
14931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            '', '--verbose', help='Do not suppress the output from `git cl`.',
15031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            action='store_true', dest='verbose', default=False)
15131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser.add_option(
15231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            '', '--skip_cl_upload', help='Skip the cl upload step; useful'
1530ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            ' for testing.',
15431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            action='store_true', default=False)
15531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
15631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        default_bots_help = (
15731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            'Comma-separated list of bots, defaults to a list of %d bots.'
15831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            '  To skip `git cl try`, set this to an empty string.'
15917bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com            % len(DEFAULT_BOTS_LIST))
16017bb951e657eb8c5d89a2dae152e4c3c4e887ddbborenet@google.com        default_bots = ','.join(DEFAULT_BOTS_LIST)
16131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser.add_option(
16231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            '', '--bots', help=default_bots_help, default=default_bots)
16331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
16431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        return option_parser
16531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
16631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
16731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comclass DepsRollError(Exception):
16831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """Exceptions specific to this module."""
16931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    pass
17031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
17131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
1728c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.comdef get_svn_revision(config, commit):
1738c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    """Works in both git and git-svn. returns a string."""
1748c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    svn_format = (
1758c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        '(git-svn-id: [^@ ]+@|SVN changes up to revision |'
1768c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        'LKGR w/ DEPS up to revision )(?P<return>[0-9]+)')
1770ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    svn_revision = misc_utils.ReSearch.search_within_output(
1788c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        config.verbose, svn_format, None,
1798c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        [config.git, 'log', '-n', '1', '--format=format:%B', commit])
1808c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    if not svn_revision:
1818c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        raise DepsRollError(
1828c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            'Revision number missing from Chromium origin/master.')
1838c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    return int(svn_revision)
1848c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
1858c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
1868c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.comclass SkiaGitCheckout(object):
1878c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    """Class to create a temporary skia git checkout, if necessary.
1888c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    """
1898c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    # pylint: disable=I0011,R0903
1908c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
1918c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    def __init__(self, config, depth):
1928c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        self._config = config
1938c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        self._depth = depth
1948c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        self._use_temp = None
1958c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        self._original_cwd = None
1968c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
1978c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    def __enter__(self):
1988c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        config = self._config
1998c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        git = config.git
2008c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        skia_dir = None
2018c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        self._original_cwd = os.getcwd()
2028c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        if config.skia_git_checkout_path:
2030ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            if config.skia_git_checkout_path != os.curdir:
2040ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                skia_dir = config.skia_git_checkout_path
2050ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                ## Update origin/master if needed.
2060ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                if self._config.verbose:
2070ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                    print '~~$', 'cd', skia_dir
2080ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                os.chdir(skia_dir)
2098c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            config.vsp.check_call([git, 'fetch', '-q', 'origin'])
2108c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            self._use_temp = None
2118c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        else:
2128c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            skia_dir = tempfile.mkdtemp(prefix='git_skia_tmp_')
2138c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            self._use_temp = skia_dir
2148c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            try:
2158c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com                os.chdir(skia_dir)
2168c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com                config.vsp.check_call(
2178c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com                    [git, 'clone', '-q', '--depth=%d' % self._depth,
2188c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com                     '--single-branch', config.skia_url, '.'])
2198c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            except (OSError, subprocess.CalledProcessError) as error:
2208c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com                shutil.rmtree(skia_dir)
2218c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com                raise error
2228c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
2238c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    def __exit__(self, etype, value, traceback):
2240ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        if self._config.skia_git_checkout_path != os.curdir:
2250ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            if self._config.verbose:
2260ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                print '~~$', 'cd', self._original_cwd
2270ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            os.chdir(self._original_cwd)
2288c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        if self._use_temp:
2298c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            shutil.rmtree(self._use_temp)
23031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
2318c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
2328c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.comdef revision_and_hash(config):
2338c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    """Finds revision number and git hash of origin/master in the Skia tree.
23431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
23531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Args:
2368c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        config: (roll_deps.DepsRollConfig) object containing options.
23731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
23831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Returns:
2398c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        A tuple (revision, hash)
2408c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            revision: (int) SVN revision number.
2418c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            git_hash: (string) full Git commit hash.
2428c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
24331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Raises:
2448c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        roll_deps.DepsRollError: if the revision can't be found.
2458c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        OSError: failed to execute git or git-cl.
2468c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        subprocess.CalledProcessError: git returned unexpected status.
24731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """
2488c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    with SkiaGitCheckout(config, 1):
2498c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        revision = get_svn_revision(config, 'origin/master')
2508c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        git_hash = config.vsp.strip_output(
2518c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            [config.git, 'show-ref', 'origin/master', '--hash'])
2528c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        if not git_hash:
2538c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            raise DepsRollError('Git hash can not be found.')
2548c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    return revision, git_hash
25531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
25631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
2578c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.comdef revision_and_hash_from_revision(config, revision):
2588c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    """Finds revision number and git hash of a commit in the Skia tree.
25931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
26031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Args:
26131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        config: (roll_deps.DepsRollConfig) object containing options.
2628c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        revision: (int) SVN revision number.
2638c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
26431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Returns:
2658c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        A tuple (revision, hash)
2668c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            revision: (int) SVN revision number.
2678c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            git_hash: (string) full Git commit hash.
2688c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
26931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Raises:
2708c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        roll_deps.DepsRollError: if the revision can't be found.
2718c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        OSError: failed to execute git or git-cl.
2728c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        subprocess.CalledProcessError: git returned unexpected status.
27331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """
2748c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    with SkiaGitCheckout(config, config.search_depth):
2758c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        revision_regex = config.revision_format % revision
2768c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        git_hash = config.vsp.strip_output(
2778c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            [config.git, 'log', '--grep', revision_regex,
2788c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com             '--format=format:%H', 'origin/master'])
2798c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        if not git_hash:
2808c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            raise DepsRollError('Git hash can not be found.')
2818c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    return revision, git_hash
28231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
28331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
2848c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.comdef revision_and_hash_from_partial(config, partial_hash):
2858c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    """Returns the SVN revision number and full git hash.
28631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
28731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Args:
28831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        config: (roll_deps.DepsRollConfig) object containing options.
2898c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        partial_hash: (string) Partial git commit hash.
29031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
29131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Returns:
29231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        A tuple (revision, hash)
29331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            revision: (int) SVN revision number.
2948c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            git_hash: (string) full Git commit hash.
29531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
29631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Raises:
29731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        roll_deps.DepsRollError: if the revision can't be found.
29831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        OSError: failed to execute git or git-cl.
29931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        subprocess.CalledProcessError: git returned unexpected status.
30031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """
3018c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    with SkiaGitCheckout(config, config.search_depth):
3028c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        git_hash = config.vsp.strip_output(
3038c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            ['git', 'log', '-n', '1', '--format=format:%H', partial_hash])
3048c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        if not git_hash:
3058c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            raise DepsRollError('Partial Git hash can not be found.')
3068c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        revision = get_svn_revision(config, git_hash)
3078c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    return revision, git_hash
30831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
30931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
31031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comdef change_skia_deps(revision, git_hash, depspath):
31131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """Update the DEPS file.
31231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
31331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Modify the skia_revision and skia_hash entries in the given DEPS file.
31431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
31531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Args:
31631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        revision: (int) Skia SVN revision.
31731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        git_hash: (string) Skia Git hash.
31831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        depspath: (string) path to DEPS file.
31931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """
32031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    temp_file = tempfile.NamedTemporaryFile(delete=False,
32131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com                                            prefix='skia_DEPS_ROLL_tmp_')
32231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    try:
32331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        deps_regex_rev = re.compile('"skia_revision": "[0-9]*",')
32431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        deps_regex_hash = re.compile('"skia_hash": "[0-9a-f]*",')
32531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
32631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        deps_regex_rev_repl = '"skia_revision": "%d",' % revision
32731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        deps_regex_hash_repl = '"skia_hash": "%s",' % git_hash
32831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
32931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        with open(depspath, 'r') as input_stream:
33031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            for line in input_stream:
33131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com                line = deps_regex_rev.sub(deps_regex_rev_repl, line)
33231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com                line = deps_regex_hash.sub(deps_regex_hash_repl, line)
33331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com                temp_file.write(line)
33431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    finally:
33531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        temp_file.close()
33631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    shutil.move(temp_file.name, depspath)
33731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
33831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
3390ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.orgdef git_cl_uploader(config, message, file_list):
3400ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    """Create a commit in the current git branch; upload via git-cl.
3410ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3420ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    Assumes that you are already on the branch you want to be on.
3430ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3440ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    Args:
3450ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        config: (roll_deps.DepsRollConfig) object containing options.
3460ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        message: (string) the commit message, can be multiline.
3470ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        file_list: (list of strings) list of filenames to pass to `git add`.
3480ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3490ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    Returns:
3500ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        The output of `git cl issue`, if not config.skip_cl_upload, else ''.
3510ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    """
3520ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3530ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    git, vsp = config.git, config.vsp
3540ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    svn_info = str(get_svn_revision(config, 'HEAD'))
3550ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3560ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    for filename in file_list:
3570ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        assert os.path.exists(filename)
3580ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        vsp.check_call([git, 'add', filename])
3590ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3600ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    vsp.check_call([git, 'commit', '-q', '-m', message])
3610ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3620ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    git_cl = [git, 'cl', 'upload', '-f',
3630ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org              '--bypass-hooks', '--bypass-watchlists']
3640ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    if config.cc_list:
3650ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        git_cl.append('--cc=%s' % config.cc_list)
3660ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    if config.reviewers_list:
3670ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        git_cl.append('--reviewers=%s' % config.reviewers_list)
3680ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3698687608c4566ecb298fdb5159f54a47eb249cbafcommit-bot@chromium.org    git_try = [
3708687608c4566ecb298fdb5159f54a47eb249cbafcommit-bot@chromium.org        git, 'cl', 'try', '-m', 'tryserver.chromium', '--revision', svn_info]
3710ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    git_try.extend([arg for bot in config.cl_bot_list for arg in ('-b', bot)])
3720ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3730ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    branch_name = git_utils.git_branch_name(vsp.verbose)
3740ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3750ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    if config.skip_cl_upload:
3760ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        space = '   '
3770ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        print 'You should call:'
3780ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        print '%scd %s' % (space, os.getcwd())
3790ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        misc_utils.print_subprocess_args(space, [git, 'checkout', branch_name])
3800ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        misc_utils.print_subprocess_args(space, git_cl)
3810ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        if config.cl_bot_list:
3820ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            misc_utils.print_subprocess_args(space, git_try)
3830ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        print
3840ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        return ''
3850ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    else:
3860ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        vsp.check_call(git_cl)
3870ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        issue = vsp.strip_output([git, 'cl', 'issue'])
3880ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        if config.cl_bot_list:
3890ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            vsp.check_call(git_try)
3900ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        return issue
3910ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
3920ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
39331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comdef roll_deps(config, revision, git_hash):
39431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """Upload changed DEPS and a whitespace change.
39531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
39631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Given the correct git_hash, create two Reitveld issues.
39731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
39831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Args:
39931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        config: (roll_deps.DepsRollConfig) object containing options.
40031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        revision: (int) Skia SVN revision.
40131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        git_hash: (string) Skia Git hash.
40231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
40331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Returns:
40431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        a tuple containing textual description of the two issues.
40531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
40631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Raises:
40731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        OSError: failed to execute git or git-cl.
40831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        subprocess.CalledProcessError: git returned unexpected status.
40931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """
4108c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
41131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    git = config.git
4120ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    with misc_utils.ChangeDir(config.chromium_path, config.verbose):
4138c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        config.vsp.check_call([git, 'fetch', '-q', 'origin'])
4148c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
4150ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        old_revision = misc_utils.ReSearch.search_within_output(
4168c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            config.verbose, '"skia_revision": "(?P<return>[0-9]+)",', None,
4178c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            [git, 'show', 'origin/master:DEPS'])
4188c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        assert old_revision
4198c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        if revision == int(old_revision):
4208c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            print 'DEPS is up to date!'
4211b94819fcbe766039a488ad3975db2e1a8a25e28commit-bot@chromium.org            return (None, None)
4228c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
4238c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        master_hash = config.vsp.strip_output(
42431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            [git, 'show-ref', 'origin/master', '--hash'])
4258c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        master_revision = get_svn_revision(config, 'origin/master')
4268c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
42731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        # master_hash[8] gives each whitespace CL a unique name.
4280ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        if config.save_branches:
4290ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            branch = 'control_%s' % master_hash[:8]
4300ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        else:
4310ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            branch = None
4328c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        message = ('whitespace change %s\n\n'
4338c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com                   'Chromium base revision: %d / %s\n\n'
4348c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com                   'This CL was created by Skia\'s roll_deps.py script.\n'
4358c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com                  ) % (master_hash[:8], master_revision, master_hash[:8])
4360ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        with git_utils.ChangeGitBranch(branch, 'origin/master',
4370ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                                       config.verbose):
4380ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            branch = git_utils.git_branch_name(config.vsp.verbose)
43931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
44031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            with open('build/whitespace_file.txt', 'a') as output_stream:
44131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com                output_stream.write('\nCONTROL\n')
4428c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
4430ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            whitespace_cl = git_cl_uploader(
4440ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                config, message, ['build/whitespace_file.txt'])
4450ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
4460ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            control_url = misc_utils.ReSearch.search_within_string(
4470ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                whitespace_cl, '(?P<return>https?://[^) ]+)', '?')
4480ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            if config.save_branches:
4490ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                whitespace_cl = '%s\n    branch: %s' % (whitespace_cl, branch)
4508c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
4518c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        if config.save_branches:
4528c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            branch = 'roll_%d_%s' % (revision, master_hash[:8])
4530ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        else:
4540ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            branch = None
4558c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        message = (
4568c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            'roll skia DEPS to %d\n\n'
4578c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            'Chromium base revision: %d / %s\n'
4588c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            'Old Skia revision: %s\n'
4598c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            'New Skia revision: %d\n'
4608c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            'Control CL: %s\n\n'
46106cd6c1a6da4be7a8bdd6ced729c56cec626e1b3commit-bot@chromium.org            'This CL was created by Skia\'s roll_deps.py script.\n\n'
46206cd6c1a6da4be7a8bdd6ced729c56cec626e1b3commit-bot@chromium.org            'Bypassing commit queue trybots:\n'
46306cd6c1a6da4be7a8bdd6ced729c56cec626e1b3commit-bot@chromium.org            'NOTRY=true\n'
4648c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            % (revision, master_revision, master_hash[:8],
4658c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com               old_revision, revision, control_url))
4660ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org        with git_utils.ChangeGitBranch(branch, 'origin/master',
4670ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                                       config.verbose):
4680ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            branch = git_utils.git_branch_name(config.vsp.verbose)
4690ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
47031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            change_skia_deps(revision, git_hash, 'DEPS')
4710ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            deps_cl = git_cl_uploader(config, message, ['DEPS'])
4720ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org            if config.save_branches:
4730ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org                deps_cl = '%s\n    branch: %s' % (deps_cl, branch)
47431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
47531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        return deps_cl, whitespace_cl
47631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
47731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
4788c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.comdef find_hash_and_roll_deps(config, revision=None, partial_hash=None):
47931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """Call find_hash_from_revision() and roll_deps().
48031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
48131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    The calls to git will be verbose on standard output.  After a
48231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    successful upload of both issues, print links to the new
48331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    codereview issues.
48431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
48531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Args:
48631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        config: (roll_deps.DepsRollConfig) object containing options.
48731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        revision: (int or None) the Skia SVN revision number or None
48831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com            to use the tip of the tree.
4898c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        partial_hash: (string or None) a partial pure-git Skia commit
4908c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            hash.  Don't pass both partial_hash and revision.
49131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
49231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Raises:
49331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        roll_deps.DepsRollError: if the revision can't be found.
49431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        OSError: failed to execute git or git-cl.
49531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        subprocess.CalledProcessError: git returned unexpected status.
49631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """
4978c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
4988c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    if revision and partial_hash:
4998c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        raise DepsRollError('Pass revision or partial_hash, not both.')
5008c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com
5018c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    if partial_hash:
5028c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        revision, git_hash = revision_and_hash_from_partial(
5038c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com            config, partial_hash)
5048c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    elif revision:
5058c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        revision, git_hash = revision_and_hash_from_revision(config, revision)
5068c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    else:
5078c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        revision, git_hash = revision_and_hash(config)
50831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
50931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    print 'revision=%r\nhash=%r\n' % (revision, git_hash)
51031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
5111b94819fcbe766039a488ad3975db2e1a8a25e28commit-bot@chromium.org    deps_issue, whitespace_issue = roll_deps(config, revision, git_hash)
51231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
5131b94819fcbe766039a488ad3975db2e1a8a25e28commit-bot@chromium.org    if deps_issue and whitespace_issue:
5148c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        print 'DEPS roll:\n    %s\n' % deps_issue
5158c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com        print 'Whitespace change:\n    %s\n' % whitespace_issue
5161b94819fcbe766039a488ad3975db2e1a8a25e28commit-bot@chromium.org    else:
5171b94819fcbe766039a488ad3975db2e1a8a25e28commit-bot@chromium.org        print >> sys.stderr, 'No issues created.'
51831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
51931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
52031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comdef main(args):
52131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """main function; see module-level docstring and GetOptionParser help.
52231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
52331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    Args:
52431fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        args: sys.argv[1:]-type argument list.
52531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    """
52631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    option_parser = DepsRollConfig.GetOptionParser()
52731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    options = option_parser.parse_args(args)[0]
52831fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
52931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    if not options.chromium_path:
53031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser.error('Must specify chromium_path.')
53131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    if not os.path.isdir(options.chromium_path):
53231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser.error('chromium_path must be a directory.')
5330ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org
5340ed90029e3a6ca5c225b6ffc100eae1e508e7105commit-bot@chromium.org    if not git_utils.git_executable():
53531fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com        option_parser.error('Invalid git executable.')
53631fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
53731fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    config = DepsRollConfig(options)
5388c5d2c1e7500e72f1e76edf608bf54e2d60c40b5halcanary@google.com    find_hash_and_roll_deps(config, options.revision, options.git_hash)
53931fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
54031fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
54131fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.comif __name__ == '__main__':
54231fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com    main(sys.argv[1:])
54331fdb92995bbd49cc3b60a5d6b97fd20b0c0ef47halcanary@google.com
544