Commit cd0e1d01 authored by Maksim Ivanov's avatar Maksim Ivanov Committed by Commit Bot

Revert "Reland: "Add --merge-base-ref option to lastchange.py""

This reverts commit 5f2e9a96.

Reason for revert: gclient sync fails with the following error:

  ________ running '/usr/bin/python src/build/util/lastchange.py -o src/build/util/LASTCHANGE' in '/mnt/sdd/chrome'
  ERROR:root:Failed to get version info: %s

Original change's description:
> Reland: "Add --merge-base-ref option to lastchange.py"
> 
> Reland commit f4f6c5ff
> Revert was 172ccc05
> 
> The previous attempt at a reland changed FetchGitRevision
> which caused breakage when
> chrome/test/chromedriver/embed_version_in_cpp.py attempted to call this
> function. https://crrev.com/c/1459921 was recently merged which
> completely removed embed_version_in_cpp.py which should allow
> this change to re-land without modification from the previous
> attempt at a reland.
> 
> Change-Id: I0dbd7436938ae27167a9381415277d95d0d8312f
> Bug: 917159
> Reviewed-on: https://chromium-review.googlesource.com/c/1460454
> Reviewed-by: Dirk Pranke <dpranke@chromium.org>
> Reviewed-by: Andrii Shyshkalov <tandrii@chromium.org>
> Commit-Queue: Eli Ribble <eliribble@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#633730}

TBR=dpranke@chromium.org,tandrii@chromium.org,eliribble@chromium.org

Change-Id: Ia644ba3b8fe50b38fec26959a298f0d269fa54c9
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 917159
Reviewed-on: https://chromium-review.googlesource.com/c/1479950Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Commit-Queue: Maksim Ivanov <emaxx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#633886}
parent 08dbcae9
...@@ -7,23 +7,20 @@ ...@@ -7,23 +7,20 @@
lastchange.py -- Chromium revision fetching utility. lastchange.py -- Chromium revision fetching utility.
""" """
import argparse import re
import collections
import logging import logging
import argparse
import os import os
import subprocess import subprocess
import sys import sys
VersionInfo = collections.namedtuple("VersionInfo", class VersionInfo(object):
("revision_id", "revision", "timestamp")) def __init__(self, revision_id, full_revision_string, timestamp):
self.revision_id = revision_id
self.revision = full_revision_string
self.timestamp = timestamp
class GitError(Exception):
pass
# This function exists for compatibility with logic outside this
# repository that uses this file as a library.
# TODO(eliribble) remove this function after it has been ported into
# the repositories that depend on it
def RunGitCommand(directory, command): def RunGitCommand(directory, command):
""" """
Launches git subcommand. Launches git subcommand.
...@@ -52,95 +49,53 @@ def RunGitCommand(directory, command): ...@@ -52,95 +49,53 @@ def RunGitCommand(directory, command):
return None return None
def _RunGitCommand(directory, command): def FetchGitRevision(directory, git_log_filter):
"""Launches git subcommand.
Returns:
The stripped stdout of the git command.
Raises:
GitError on failure, including a nonzero return code.
""" """
command = ['git'] + command Fetch the Git hash (and Cr-Commit-Position if any) for a given directory.
# Force shell usage under cygwin. This is a workaround for
# mysterious loss of cwd while invoking cygwin's git.
# We can't just pass shell=True to Popen, as under win32 this will
# cause CMD to be used, while we explicitly want a cygwin shell.
if sys.platform == 'cygwin':
command = ['sh', '-c', ' '.join(command)]
try:
logging.info("Executing '%s' in %s", ' '.join(command), directory)
proc = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=directory,
shell=(sys.platform=='win32'))
stdout, stderr = proc.communicate()
stdout = stdout.strip()
logging.debug("returncode: %d", proc.returncode)
logging.debug("stdout: %s", stdout)
logging.debug("stderr: %s", stderr)
if proc.returncode != 0 or not stdout:
raise GitError((
"Git command 'git {}' in {} failed: "
"rc={}, stdout='{}' stderr='{}'").format(
" ".join(command), directory, proc.returncode, stdout, stderr))
return stdout
except OSError as e:
raise GitError("Git command 'git {}' in {} failed: {}".format(
" ".join(command), directory, e))
def GetMergeBase(directory, ref): Errors are swallowed.
"""
Return the merge-base of HEAD and ref.
Args: Args:
directory: The directory containing the .git directory. git_log_filter: a string to be used for filtering git log result.
ref: The ref to use to find the merge base.
Returns:
The git commit SHA of the merge-base as a string.
"""
logging.debug("Calculating merge base between HEAD and %s in %s",
ref, directory)
command = ['merge-base', 'HEAD', ref]
return _RunGitCommand(directory, command)
def FetchGitRevision(directory, commit_filter, start_commit="HEAD"):
"""
Fetch the Git hash (and Cr-Commit-Position if any) for a given directory.
Args:
directory: The directory containing the .git directory.
commit_filter: A filter to supply to grep to filter commits
start_commit: A commit identifier. The result of this function
will be limited to only consider commits before the provided
commit.
Returns: Returns:
A VersionInfo object. On error all values will be 0. A VersionInfo object or None on error.
""" """
hash_ = '' hsh = ''
git_args = ['log', '-1', '--format=%H %ct'] git_args = ['log', '-1', '--format=%H %ct']
if commit_filter is not None: if git_log_filter is not None:
git_args.append('--grep=' + commit_filter) git_args.append('--grep=' + git_log_filter)
proc = RunGitCommand(directory, git_args)
git_args.append(start_commit) if proc:
output = proc.communicate()[0].strip()
output = _RunGitCommand(directory, git_args) if proc.returncode == 0 and output:
hash_, commit_timestamp = output.split() hsh, ct = output.split()
if not hash_: else:
return VersionInfo('0', '0', 0) logging.error('Git error: rc=%d, output=%r' %
(proc.returncode, output))
revision = hash_ if not hsh:
output = _RunGitCommand(directory, ['cat-file', 'commit', hash_]) return None
for line in reversed(output.splitlines()): pos = ''
if line.startswith('Cr-Commit-Position:'): proc = RunGitCommand(directory, ['cat-file', 'commit', hsh])
pos = line.rsplit()[-1].strip() if proc:
logging.debug("Found Cr-Commit-Position '%s'", pos) output = proc.communicate()[0]
revision = "{}-{}".format(hash_, pos) if proc.returncode == 0 and output:
break for line in reversed(output.splitlines()):
return VersionInfo(hash_, revision, int(commit_timestamp)) if line.startswith('Cr-Commit-Position:'):
pos = line.rsplit()[-1].strip()
break
return VersionInfo(hsh, '%s-%s' % (hsh, pos), int(ct))
def FetchVersionInfo(directory=None, git_log_filter=None):
"""
Returns the last change (as a VersionInfo object)
from some appropriate revision control system.
"""
version_info = FetchGitRevision(directory, git_log_filter)
if not version_info:
version_info = VersionInfo('0', '0', 0)
return version_info
def GetHeaderGuard(path): def GetHeaderGuard(path):
...@@ -181,17 +136,6 @@ def GetHeaderContents(path, define, version): ...@@ -181,17 +136,6 @@ def GetHeaderContents(path, define, version):
return header_contents return header_contents
def GetGitTopDirectory(source_dir):
"""Get the top git directory - the directory that contains the .git directory.
Args:
source_dir: The directory to search.
Returns:
The output of "git rev-parse --show-toplevel" as a string
"""
return _RunGitCommand(source_dir, ['rev-parse', '--show-toplevel'])
def WriteIfChanged(file_name, contents): def WriteIfChanged(file_name, contents):
""" """
Writes the specified contents to the specified file_name Writes the specified contents to the specified file_name
...@@ -216,23 +160,20 @@ def main(argv=None): ...@@ -216,23 +160,20 @@ def main(argv=None):
parser = argparse.ArgumentParser(usage="lastchange.py [options]") parser = argparse.ArgumentParser(usage="lastchange.py [options]")
parser.add_argument("-m", "--version-macro", parser.add_argument("-m", "--version-macro",
help=("Name of C #define when using --header. Defaults to " help="Name of C #define when using --header. Defaults to " +
"LAST_CHANGE.")) "LAST_CHANGE.",
default="LAST_CHANGE")
parser.add_argument("-o", "--output", metavar="FILE", parser.add_argument("-o", "--output", metavar="FILE",
help=("Write last change to FILE. " help="Write last change to FILE. " +
"Can be combined with --header to write both files.")) "Can be combined with --header to write both files.")
parser.add_argument("--header", metavar="FILE", parser.add_argument("--header", metavar="FILE",
help=("Write last change to FILE as a C/C++ header. " help=("Write last change to FILE as a C/C++ header. "
"Can be combined with --output to write both files.")) "Can be combined with --output to write both files."))
parser.add_argument("--merge-base-ref",
default=None,
help=("Only consider changes since the merge "
"base between HEAD and the provided ref"))
parser.add_argument("--revision-id-only", action='store_true', parser.add_argument("--revision-id-only", action='store_true',
help=("Output the revision as a VCS revision ID only (in " help=("Output the revision as a VCS revision ID only (in "
"Git, a 40-character commit hash, excluding the " "Git, a 40-character commit hash, excluding the "
"Cr-Commit-Position).")) "Cr-Commit-Position)."))
parser.add_argument("--print-only", action="store_true", parser.add_argument("--print-only", action='store_true',
help=("Just print the revision string. Overrides any " help=("Just print the revision string. Overrides any "
"file-output-related options.")) "file-output-related options."))
parser.add_argument("-s", "--source-dir", metavar="DIR", parser.add_argument("-s", "--source-dir", metavar="DIR",
...@@ -242,14 +183,13 @@ def main(argv=None): ...@@ -242,14 +183,13 @@ def main(argv=None):
"matches the supplied filter regex. Defaults to " "matches the supplied filter regex. Defaults to "
"'^Change-Id:' to suppress local commits."), "'^Change-Id:' to suppress local commits."),
default='^Change-Id:') default='^Change-Id:')
args, extras = parser.parse_known_args(argv[1:]) args, extras = parser.parse_known_args(argv[1:])
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
out_file = args.output out_file = args.output
header = args.header header = args.header
commit_filter=args.filter git_log_filter=args.filter
while len(extras) and out_file is None: while len(extras) and out_file is None:
if out_file is None: if out_file is None:
...@@ -259,37 +199,19 @@ def main(argv=None): ...@@ -259,37 +199,19 @@ def main(argv=None):
parser.print_help() parser.print_help()
sys.exit(2) sys.exit(2)
source_dir = args.source_dir or os.path.dirname(os.path.abspath(__file__)) if args.source_dir:
try: src_dir = args.source_dir
git_top_dir = GetGitTopDirectory(source_dir)
except GitError as e:
logging.error("Failed to get git top directory from '%s': %s",
source_dir, e)
return 2
if args.merge_base_ref:
try:
merge_base_sha = GetMergeBase(git_top_dir, args.merge_base_ref)
except GitError as e:
logging.error("You requested a --merge-base-ref value of '%s' but no "
"merge base could be found between it and HEAD. Git "
"reports: %s", args.merge_base_ref, e)
return 3
else: else:
merge_base_sha = 'HEAD' src_dir = os.path.dirname(os.path.abspath(__file__))
try:
version_info = FetchGitRevision(git_top_dir, commit_filter, merge_base_sha)
except GitError as e:
logging.error("Failed to get version info: %s")
return 1
version_info = FetchVersionInfo(directory=src_dir,
git_log_filter=git_log_filter)
revision_string = version_info.revision revision_string = version_info.revision
if args.revision_id_only: if args.revision_id_only:
revision_string = version_info.revision_id revision_string = version_info.revision_id
if args.print_only: if args.print_only:
print(revision_string) print revision_string
else: else:
contents = "LASTCHANGE=%s\n" % revision_string contents = "LASTCHANGE=%s\n" % revision_string
if not out_file and not args.header: if not out_file and not args.header:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment