blob: dff1d8bb65e1c89144132bd05f65c4c008268275 [file]
#!/usr/bin/env python3
# Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
import utils
import subprocess
def GitClone(url, checkout_dir):
cmd = ['git', 'clone', url, checkout_dir]
utils.PrintCmd(cmd)
return subprocess.check_call(cmd)
def GitCheckout(revision, checkout_dir):
with utils.ChangedWorkingDirectory(checkout_dir):
cmd = ['git', 'checkout', revision]
utils.PrintCmd(cmd)
return subprocess.check_call(cmd)
def GetHeadRevision(checkout_dir, use_main=False):
revision_from = 'origin/main' if use_main else 'HEAD'
cmd = ['git', 'rev-parse', revision_from]
utils.PrintCmd(cmd)
with utils.ChangedWorkingDirectory(checkout_dir):
return subprocess.check_output(cmd).strip().decode('utf-8')
def _reviewer_arg(reviewer):
if reviewer.find('@') == -1:
reviewer = reviewer + "@google.com"
return '--reviewer=' + reviewer
def GitClAppendReviewers(cmd, reviewer, send_mail):
if reviewer:
cmd.extend(map(_reviewer_arg, reviewer))
if send_mail:
cmd.append('--send-mail')
def GitCommit(message):
cmd = ['git', 'commit', '-a', '-m', message]
utils.PrintCmd(cmd)
return subprocess.check_call(cmd)
def VersionCommitMessage(version, description=None, bugs=None):
lines = ['Version %s' % version]
if description:
lines.append('')
lines.append(description)
lines.append('')
if bugs:
for bug in sorted(bugs):
bug_str = str(bug).strip()
if not bug_str.startswith('b/'):
bug_str = 'b/%s' % bug_str
lines.append('Bug: %s' % bug_str)
lines.append('Cq-Exclude-Trybots: luci.r8.try:presubmit')
return '\n'.join(lines)
version_commit_message = VersionCommitMessage
def get_head_ref(checkout_dir=utils.REPO_ROOT):
try:
branch = subprocess.check_output(
['git', 'symbolic-ref', '-q', '--short', 'HEAD'],
cwd=checkout_dir,
stderr=subprocess.PIPE,
text=True).strip()
if branch:
return branch
except subprocess.CalledProcessError:
pass
return GetHeadRevision(checkout_dir)
def resolve_revision(revision, checkout_dir=utils.REPO_ROOT):
return subprocess.check_output(['git', 'rev-parse', '--verify', revision],
cwd=checkout_dir,
stderr=subprocess.PIPE,
text=True).strip()
def is_working_tree_clean(checkout_dir=utils.REPO_ROOT):
out = subprocess.check_output(
['git', 'status', '--porcelain', '--untracked-files=no'],
cwd=checkout_dir,
stderr=subprocess.PIPE,
text=True).strip()
return not out
def is_unmerged_commit(revision,
base_ref='origin/main',
checkout_dir=utils.REPO_ROOT):
return subprocess.call(
['git', 'merge-base', '--is-ancestor', revision, base_ref],
cwd=checkout_dir,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL) == 1
def _get_change_id(revision, checkout_dir=utils.REPO_ROOT):
out = subprocess.check_output([
'git', 'log', '-1', '--format=%(trailers:key=Change-Id,valueonly=true)',
revision
],
cwd=checkout_dir,
stderr=subprocess.PIPE,
text=True).strip()
lines = [line.strip() for line in out.splitlines() if line.strip()]
return lines[-1] if lines else None
def get_previous_cl_commit(checkout_dir=utils.REPO_ROOT):
try:
rev_list = subprocess.check_output(
['git', 'rev-list', '--parents', '-n', '1', 'HEAD'],
cwd=checkout_dir,
stderr=subprocess.PIPE,
text=True).strip().split()
if len(rev_list) != 2:
return None
head_sha, parent_sha = rev_list
if not is_unmerged_commit(parent_sha, checkout_dir=checkout_dir):
return None
try:
cherry_out = subprocess.check_output(
['git', 'cherry', 'origin/main', parent_sha, f'{parent_sha}~1'],
cwd=checkout_dir,
stderr=subprocess.PIPE,
text=True).strip()
if cherry_out.startswith('-'):
return None
except subprocess.CalledProcessError:
pass
head_change_id = _get_change_id(head_sha, checkout_dir)
parent_change_id = _get_change_id(parent_sha, checkout_dir)
if head_change_id and parent_change_id and (head_change_id
== parent_change_id):
return None
return parent_sha
except subprocess.CalledProcessError:
return None
def get_candidate_main_commits(explicit_base_hash=None,
exclude_sha=None,
max_count=25):
if explicit_base_hash:
start_ref = explicit_base_hash
else:
try:
merge_base_cmd = ['git', 'merge-base', 'HEAD', 'origin/main']
start_ref = subprocess.check_output(merge_base_cmd,
cwd=utils.REPO_ROOT,
stderr=subprocess.PIPE,
text=True).strip()
except subprocess.CalledProcessError:
start_ref = utils.get_HEAD_sha1()
try:
log_cmd = [
'git',
'log',
'--first-parent',
start_ref,
f'--max-count={max_count}',
'--pretty=format:%H',
]
commits = subprocess.check_output(log_cmd,
cwd=utils.REPO_ROOT,
text=True).strip().splitlines()
res = [
c.strip()
for c in commits
if c.strip() and (explicit_base_hash or c.strip() != exclude_sha)
]
return res or [start_ref]
except subprocess.CalledProcessError:
return [start_ref]