| Index: tools/push-to-trunk/git_recipes.py
|
| diff --git a/tools/push-to-trunk/git_recipes.py b/tools/push-to-trunk/git_recipes.py
|
| deleted file mode 100644
|
| index 3d2a9ef87d7fd14400ec6c96c3ef18bbcbb4b64b..0000000000000000000000000000000000000000
|
| --- a/tools/push-to-trunk/git_recipes.py
|
| +++ /dev/null
|
| @@ -1,275 +0,0 @@
|
| -#!/usr/bin/env python
|
| -# Copyright 2014 the V8 project authors. All rights reserved.
|
| -# Redistribution and use in source and binary forms, with or without
|
| -# modification, are permitted provided that the following conditions are
|
| -# met:
|
| -#
|
| -# * Redistributions of source code must retain the above copyright
|
| -# notice, this list of conditions and the following disclaimer.
|
| -# * Redistributions in binary form must reproduce the above
|
| -# copyright notice, this list of conditions and the following
|
| -# disclaimer in the documentation and/or other materials provided
|
| -# with the distribution.
|
| -# * Neither the name of Google Inc. nor the names of its
|
| -# contributors may be used to endorse or promote products derived
|
| -# from this software without specific prior written permission.
|
| -#
|
| -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| -
|
| -import re
|
| -
|
| -SHA1_RE = re.compile('^[a-fA-F0-9]{40}$')
|
| -ROLL_DEPS_GIT_SVN_ID_RE = re.compile('^git-svn-id: .*@([0-9]+) .*$')
|
| -
|
| -# Regular expression that matches a single commit footer line.
|
| -COMMIT_FOOTER_ENTRY_RE = re.compile(r'([^:]+):\s+(.+)')
|
| -
|
| -# Footer metadata key for commit position.
|
| -COMMIT_POSITION_FOOTER_KEY = 'Cr-Commit-Position'
|
| -
|
| -# Regular expression to parse a commit position
|
| -COMMIT_POSITION_RE = re.compile(r'(.+)@\{#(\d+)\}')
|
| -
|
| -# Key for the 'git-svn' ID metadata commit footer entry.
|
| -GIT_SVN_ID_FOOTER_KEY = 'git-svn-id'
|
| -
|
| -# e.g., git-svn-id: https://v8.googlecode.com/svn/trunk@23117
|
| -# ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
| -GIT_SVN_ID_RE = re.compile(r'[^@]+@(\d+)\s+(?:[a-zA-Z0-9\-]+)')
|
| -
|
| -
|
| -# Copied from bot_update.py.
|
| -def GetCommitMessageFooterMap(message):
|
| - """Returns: (dict) A dictionary of commit message footer entries.
|
| - """
|
| - footers = {}
|
| -
|
| - # Extract the lines in the footer block.
|
| - lines = []
|
| - for line in message.strip().splitlines():
|
| - line = line.strip()
|
| - if len(line) == 0:
|
| - del(lines[:])
|
| - continue
|
| - lines.append(line)
|
| -
|
| - # Parse the footer
|
| - for line in lines:
|
| - m = COMMIT_FOOTER_ENTRY_RE.match(line)
|
| - if not m:
|
| - # If any single line isn't valid, the entire footer is invalid.
|
| - footers.clear()
|
| - return footers
|
| - footers[m.group(1)] = m.group(2).strip()
|
| - return footers
|
| -
|
| -
|
| -class GitFailedException(Exception):
|
| - pass
|
| -
|
| -
|
| -def Strip(f):
|
| - def new_f(*args, **kwargs):
|
| - result = f(*args, **kwargs)
|
| - if result is None:
|
| - return result
|
| - else:
|
| - return result.strip()
|
| - return new_f
|
| -
|
| -
|
| -def MakeArgs(l):
|
| - """['-a', '', 'abc', ''] -> '-a abc'"""
|
| - return " ".join(filter(None, l))
|
| -
|
| -
|
| -def Quoted(s):
|
| - return "\"%s\"" % s
|
| -
|
| -
|
| -class GitRecipesMixin(object):
|
| - def GitIsWorkdirClean(self, **kwargs):
|
| - return self.Git("status -s -uno", **kwargs).strip() == ""
|
| -
|
| - @Strip
|
| - def GitBranch(self, **kwargs):
|
| - return self.Git("branch", **kwargs)
|
| -
|
| - def GitCreateBranch(self, name, remote="", **kwargs):
|
| - assert name
|
| - remote_args = ["--upstream", remote] if remote else []
|
| - self.Git(MakeArgs(["new-branch", name] + remote_args), **kwargs)
|
| -
|
| - def GitDeleteBranch(self, name, **kwargs):
|
| - assert name
|
| - self.Git(MakeArgs(["branch -D", name]), **kwargs)
|
| -
|
| - def GitReset(self, name, **kwargs):
|
| - assert name
|
| - self.Git(MakeArgs(["reset --hard", name]), **kwargs)
|
| -
|
| - def GitStash(self, **kwargs):
|
| - self.Git(MakeArgs(["stash"]), **kwargs)
|
| -
|
| - def GitRemotes(self, **kwargs):
|
| - return map(str.strip,
|
| - self.Git(MakeArgs(["branch -r"]), **kwargs).splitlines())
|
| -
|
| - def GitCheckout(self, name, **kwargs):
|
| - assert name
|
| - self.Git(MakeArgs(["checkout -f", name]), **kwargs)
|
| -
|
| - def GitCheckoutFile(self, name, branch_or_hash, **kwargs):
|
| - assert name
|
| - assert branch_or_hash
|
| - self.Git(MakeArgs(["checkout -f", branch_or_hash, "--", name]), **kwargs)
|
| -
|
| - def GitCheckoutFileSafe(self, name, branch_or_hash, **kwargs):
|
| - try:
|
| - self.GitCheckoutFile(name, branch_or_hash, **kwargs)
|
| - except GitFailedException: # pragma: no cover
|
| - # The file doesn't exist in that revision.
|
| - return False
|
| - return True
|
| -
|
| - def GitChangedFiles(self, git_hash, **kwargs):
|
| - assert git_hash
|
| - try:
|
| - files = self.Git(MakeArgs(["diff --name-only",
|
| - git_hash,
|
| - "%s^" % git_hash]), **kwargs)
|
| - return map(str.strip, files.splitlines())
|
| - except GitFailedException: # pragma: no cover
|
| - # Git fails using "^" at branch roots.
|
| - return []
|
| -
|
| -
|
| - @Strip
|
| - def GitCurrentBranch(self, **kwargs):
|
| - for line in self.Git("status -s -b -uno", **kwargs).strip().splitlines():
|
| - match = re.match(r"^## (.+)", line)
|
| - if match: return match.group(1)
|
| - raise Exception("Couldn't find curent branch.") # pragma: no cover
|
| -
|
| - @Strip
|
| - def GitLog(self, n=0, format="", grep="", git_hash="", parent_hash="",
|
| - branch="", reverse=False, **kwargs):
|
| - assert not (git_hash and parent_hash)
|
| - args = ["log"]
|
| - if n > 0:
|
| - args.append("-%d" % n)
|
| - if format:
|
| - args.append("--format=%s" % format)
|
| - if grep:
|
| - args.append("--grep=\"%s\"" % grep.replace("\"", "\\\""))
|
| - if reverse:
|
| - args.append("--reverse")
|
| - if git_hash:
|
| - args.append(git_hash)
|
| - if parent_hash:
|
| - args.append("%s^" % parent_hash)
|
| - args.append(branch)
|
| - return self.Git(MakeArgs(args), **kwargs)
|
| -
|
| - def GitGetPatch(self, git_hash, **kwargs):
|
| - assert git_hash
|
| - return self.Git(MakeArgs(["log", "-1", "-p", git_hash]), **kwargs)
|
| -
|
| - # TODO(machenbach): Unused? Remove.
|
| - def GitAdd(self, name, **kwargs):
|
| - assert name
|
| - self.Git(MakeArgs(["add", Quoted(name)]), **kwargs)
|
| -
|
| - def GitApplyPatch(self, patch_file, reverse=False, **kwargs):
|
| - assert patch_file
|
| - args = ["apply --index --reject"]
|
| - if reverse:
|
| - args.append("--reverse")
|
| - args.append(Quoted(patch_file))
|
| - self.Git(MakeArgs(args), **kwargs)
|
| -
|
| - def GitUpload(self, reviewer="", author="", force=False, cq=False,
|
| - bypass_hooks=False, cc="", **kwargs):
|
| - args = ["cl upload --send-mail"]
|
| - if author:
|
| - args += ["--email", Quoted(author)]
|
| - if reviewer:
|
| - args += ["-r", Quoted(reviewer)]
|
| - if force:
|
| - args.append("-f")
|
| - if cq:
|
| - args.append("--use-commit-queue")
|
| - if bypass_hooks:
|
| - args.append("--bypass-hooks")
|
| - if cc:
|
| - args += ["--cc", Quoted(cc)]
|
| - # TODO(machenbach): Check output in forced mode. Verify that all required
|
| - # base files were uploaded, if not retry.
|
| - self.Git(MakeArgs(args), pipe=False, **kwargs)
|
| -
|
| - def GitCommit(self, message="", file_name="", author=None, **kwargs):
|
| - assert message or file_name
|
| - args = ["commit"]
|
| - if file_name:
|
| - args += ["-aF", Quoted(file_name)]
|
| - if message:
|
| - args += ["-am", Quoted(message)]
|
| - if author:
|
| - args += ["--author", "\"%s <%s>\"" % (author, author)]
|
| - self.Git(MakeArgs(args), **kwargs)
|
| -
|
| - def GitPresubmit(self, **kwargs):
|
| - self.Git("cl presubmit", "PRESUBMIT_TREE_CHECK=\"skip\"", **kwargs)
|
| -
|
| - def GitCLLand(self, **kwargs):
|
| - self.Git(
|
| - "cl land -f --bypass-hooks", retry_on=lambda x: x is None, **kwargs)
|
| -
|
| - def GitDiff(self, loc1, loc2, **kwargs):
|
| - return self.Git(MakeArgs(["diff", loc1, loc2]), **kwargs)
|
| -
|
| - def GitPull(self, **kwargs):
|
| - self.Git("pull", **kwargs)
|
| -
|
| - def GitFetchOrigin(self, **kwargs):
|
| - self.Git("fetch origin", **kwargs)
|
| -
|
| - @Strip
|
| - # Copied from bot_update.py and modified for svn-like numbers only.
|
| - def GetCommitPositionNumber(self, git_hash, **kwargs):
|
| - """Dumps the 'git' log for a specific revision and parses out the commit
|
| - position number.
|
| -
|
| - If a commit position metadata key is found, its number will be returned.
|
| -
|
| - Otherwise, we will search for a 'git-svn' metadata entry. If one is found,
|
| - its SVN revision value is returned.
|
| - """
|
| - git_log = self.GitLog(format='%B', n=1, git_hash=git_hash, **kwargs)
|
| - footer_map = GetCommitMessageFooterMap(git_log)
|
| -
|
| - # Search for commit position metadata
|
| - value = footer_map.get(COMMIT_POSITION_FOOTER_KEY)
|
| - if value:
|
| - match = COMMIT_POSITION_RE.match(value)
|
| - if match:
|
| - return match.group(2)
|
| -
|
| - # Extract the svn revision from 'git-svn' metadata
|
| - value = footer_map.get(GIT_SVN_ID_FOOTER_KEY)
|
| - if value:
|
| - match = GIT_SVN_ID_RE.match(value)
|
| - if match:
|
| - return match.group(1)
|
| - raise GitFailedException("Couldn't determine commit position for %s" %
|
| - git_hash)
|
|
|