| #!/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) |
| |