blob: df71bbc42254b564c641f796f6f6b9248c377f59 [file] [log] [blame]
#!/usr/bin/python
#
# Copyright 2018 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.
#
# Various utility fns for robosushi.
import os
from subprocess import call
import subprocess
def log(msg):
print "[ %s ]" % msg
class UserInstructions(Exception):
"""Handy exception subclass that just prints very verbose instructions to the
user. Normal exceptions tend to lose the message in the stack trace, which we
probably don't care about."""
def __init__ (self, msg):
self._msg = msg
def __str__(self):
sep = "=" * 78
return "\n\n%s\n%s\n%s\n\n" % (sep, self._msg, sep)
class RoboConfiguration:
def __init__(self):
"""Ensure that our config has basic fields fill in, and passes some sanity
checks too.
Important: We might be doing --setup, so these sanity checks should only be
for things that we don't plan for fix as part of that.
"""
self.set_prompt_on_call(False)
# This is the prefix that our branches start with.
self._sushi_branch_prefix = "sushi-"
# This is the title that we use for the commit with GN configs.
self._gn_commit_title = "GN Configuration"
# Title of the commit with chromium/patches/README.
self._patches_commit_title = "Chromium patches file"
# Title of the commit with README.chromium
self._readme_chromium_commit_title = "README.chromium file"
self.EnsureHostInfo()
self.EnsureChromeSrc()
# Origin side of the merge. Only needs to change if you're trying to
# modify and test robosushi itself. See robosushi.py for details.
self._origin_merge_base = "origin/master"
# Directory where llvm lives.
self._llvm_path = os.path.join(self.chrome_src(), "third_party",
"llvm-build", "Release+Asserts", "bin")
self.EnsurePathContainsLLVM()
log("Using chrome src: %s" % self.chrome_src())
self.EnsureFFmpegHome()
log("Using ffmpeg home: %s" % self.ffmpeg_home())
self.EnsureASANConfig()
self.ComputeBranchName()
log("On branch: %s" % self.branch_name())
if self.sushi_branch_name():
log("On sushi branch: %s" % self.sushi_branch_name())
# Filename that we'll ask generate_gn.py to write git commands to.
self._autorename_git_file = os.path.join(
self.ffmpeg_home(),
"chromium",
"scripts",
".git_commands.sh")
def chrome_src(self):
"""Return /path/to/chromium/src"""
return self._chrome_src
def host_operating_system(self):
"""Return host type, e.g. "linux" """
return self._host_operating_system
def host_architecture(self):
"""Return host architecture, e.g. "x64" """
return self._host_architecture
def ffmpeg_home(self):
"""Return /path/to/third_party/ffmpeg"""
return self._ffmpeg_home
def relative_asan_directory(self):
return self._relative_asan_directory
def absolute_asan_directory(self):
return os.path.join(self.chrome_src(), self.relative_asan_directory())
def chdir_to_chrome_src(self):
os.chdir(self.chrome_src())
def chdir_to_ffmpeg_home(self):
os.chdir(self.ffmpeg_home())
def branch_name(self):
"""Return the current workspace's branch name, or None. This might be any
branch (e.g., "master"), not just one that we've created."""
return self._branch_name
def sushi_branch_name(self):
"""If the workspace is currently on a branch that we created (a "sushi
branch"), return it. Else return None."""
return self._sushi_branch_name
def sushi_branch_prefix(self):
"""Return the branch name that indicates that this is a "sushi branch"."""
return self._sushi_branch_prefix
def gn_commit_title(self):
return self._gn_commit_title
def patches_commit_title(self):
return self._patches_commit_title
def readme_chromium_commit_title(self):
return self._readme_chromium_commit_title
def nasm_path(self):
return self._nasm_path
def origin_merge_base(self):
return self._origin_merge_base
def override_origin_merge_base(self, new_base):
self._origin_merge_base = new_base
def EnsureHostInfo(self):
"""Ensure that the host architecture and platform are set."""
# TODO(liberato): autodetect
self._host_operating_system = "linux"
self._host_architecture = "x64"
def EnsureChromeSrc(self):
"""Find the /absolute/path/to/my_chrome_dir/src"""
wd = os.getcwd()
# Walk up the tree until we find src/AUTHORS
while wd != "/":
if os.path.isfile(os.path.join(wd, "src", "AUTHORS")):
self._chrome_src = os.path.join(wd, "src")
return
wd = os.path.dirname(wd)
raise Exception("could not find src/AUTHORS in any parent of the wd")
def EnsureFFmpegHome(self):
"""Ensure that |self| has "ffmpeg_home" set."""
self._ffmpeg_home = os.path.join(self.chrome_src(), "third_party", "ffmpeg")
def EnsureASANConfig(self):
"""Find the asan directories. Note that we don't create them."""
# Compute gn ASAN out dirnames.
self.chdir_to_chrome_src();
local_directory = os.path.join("out", "sushi_asan")
# ASAN dir, suitable for 'ninja -C'
self._relative_asan_directory = local_directory
def EnsurePathContainsLLVM(self):
"""Make sure that we have chromium's LLVM in $PATH.
We don't want folks to accidentally use the wrong clang.
"""
llvm_path = os.path.join(self.chrome_src(), "third_party",
"llvm-build", "Release+Asserts", "bin")
if self.llvm_path() not in os.environ["PATH"]:
raise UserInstructions(
"Please add:\n%s\nto the beginning of $PATH" %
self.llvm_path())
def llvm_path(self):
return self._llvm_path
def ComputeBranchName(self):
"""Get the current branch name and set it."""
self.chdir_to_ffmpeg_home()
branch_name = subprocess.Popen(["git", "rev-parse", "--abbrev-ref", "HEAD"],
stdout=subprocess.PIPE).communicate()[0].strip()
self.SetBranchName(branch_name)
def SetBranchName(self, name):
"""Set our branch name, which may be a sushi branch or not."""
self._branch_name = name
# If this is one of our branches, then record that too.
if name and not name.startswith(self.sushi_branch_prefix()):
name = None
self._sushi_branch_name = name
def autorename_git_file(self):
return self._autorename_git_file
def prompt_on_call(self):
""" Return True if and only if we're supposed to ask the user before running
any command that might have a side-effect."""
return self._prompt_on_call
def set_prompt_on_call(self, value):
self._prompt_on_call = value
def Call(self, args, shell=False):
"""Run the command specified by |args| (see subprocess.call), optionally
prompting the user."""
if self.prompt_on_call():
print("[%s] About to run: %s " % (os.getcwd(), args))
raw_input("Press ENTER to continue, or interrupt the script: ")
return call(args, shell=shell)