blob: da40fedaa3f77f3fb3f5fcf64b2233ca32f46247 [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Commits files to the chromium git repository."""
from __future__ import print_function
import os
from chromite.lib import constants
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import git
from chromite.lib import osutils
from chromite.lib import tree_status
class CommitError(Exception):
"""Raised if the commit failed."""
class ChromeCommitter(object):
"""Committer object responsible for committing a git change."""
def __init__(self, args):
self._checkout_dir = args.workdir
self._dryrun = args.dryrun
self._git_committer_args = ['-c', '' % args.user_email,
'-c', '' % args.user_email]
self._commit_msg = '''user_email=%s', args.user_email)'checkout_dir=%s', args.workdir)
def __del__(self):
def FullPath(self, file_path):
"""Returns the full path in the source tree given a relative path.
file_path: Path of file.
Full path rooted in source checkout.
if os.path.isabs(file_path):
return file_path
return os.path.join(self._checkout_dir, file_path)
def Checkout(self, sparse_checkout):
"""Checks out chrome into tmp checkout dir.
sparse_checkout: List of file paths to fetch.
assert isinstance(sparse_checkout, list)
sparse_checkout += ['codereview.settings', 'WATCHLISTS']
git.ShallowFetch(self._checkout_dir, constants.CHROMIUM_GOB_URL,
git.CreateBranch(self._checkout_dir, 'auto-commit-branch',
def Commit(self, file_paths, commit_msg):
"""Commits files listed in |file_paths|.
file_paths: List of files to commit.
commit_msg: Message to use in commit.
assert file_paths and isinstance(file_paths, list)
# Make paths absolute and ensure they exist.
for i, file_path in enumerate(file_paths):
if not os.path.isabs(file_path):
file_paths[i] = self.FullPath(file_path)
if not os.path.exists(file_paths[i]):
raise CommitError('Invalid path: %s' % file_paths[i])
self._commit_msg = 'Automated Commit: ' + commit_msg
for file_path in file_paths:
commit_args = ['commit', '-m', self._commit_msg]
git.RunGit(self._checkout_dir, self._git_committer_args + commit_args,
print_cmd=True, redirect_stderr=True, capture_output=False)
except cros_build_lib.RunCommandError as e:
raise CommitError('Could not create git commit: %r' % e)
def Upload(self):
"""Uploads the change to gerrit."""'Uploading commit.')
# Run 'git cl upload' with --bypass-hooks to skip running scripts that are
# not part of the shallow checkout, -f to skip editing the CL message,
upload_args = self._git_committer_args + [
'cl', 'upload', '-v', '-m', self._commit_msg, '--bypass-hooks', '-f']
# Add the gardener(s) as TBR; fall-back to tbr-owners.
gardeners = tree_status.GetGardenerEmailAddresses()
if gardeners:
for tbr in gardeners:
upload_args += ['--tbrs', tbr]
upload_args += ['--tbr-owners']
# Marks CL as ready.
upload_args += ['--send-mail']
if self._dryrun:
upload_args += ['--dry-run']
git.RunGit(self._checkout_dir, upload_args, print_cmd=True,
redirect_stderr=True, capture_output=False)
# Flip the CQ commit bit.
submit_args = ['cl', 'set-commit', '-v']
if self._dryrun:
submit_args += ['--dry-run']
git.RunGit(self._checkout_dir, submit_args,
print_cmd=True, redirect_stderr=True, capture_output=False)
except cros_build_lib.RunCommandError as e:
# Log the change for debugging.
git.RunGit(self._checkout_dir, ['--no-pager', 'log', '--pretty=full'],
raise CommitError('Could not submit: %r' % e)'Submitted to CQ.')
def Cleanup(self):
"""Remove chrome checkout."""
osutils.RmDir(self._checkout_dir, ignore_missing=True)
def GetParser():
"""Returns parser for ChromeCommitter.
Dictionary of parsed command line args.
# We need to use the account used by the builder to upload git CLs when
# generating CLs.
default_git_account = None
if cros_build_lib.HostIsCIBuilder(golo_only=True):
default_git_account = ''
elif cros_build_lib.HostIsCIBuilder(gce_only=True):
default_git_account = ''
parser = commandline.ArgumentParser(usage=__doc__, add_help=False)
parser.add_argument('--dryrun', action='store_true', default=False,
help='Don\'t commit changes or send out emails.')
parser.add_argument('--user_email', required=False,
help='Email address to use when comitting changes.')
default=os.path.join(os.getcwd(), 'chrome_src'),
help=('Path to a checkout of the chrome src. '
'Defaults to PWD/chrome_src'))
return parser