| 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
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f5a231599e255d00675e7b926a45ec33a9ed1053
|
| --- /dev/null
|
| +++ b/tools/push-to-trunk/git_recipes.py
|
| @@ -0,0 +1,161 @@
|
| +#!/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
|
| +
|
| +def Strip(f):
|
| + def new_f(*args, **kwargs):
|
| + return f(*args, **kwargs).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):
|
| + return self.Git("status -s -uno").strip() == ""
|
| +
|
| + @Strip
|
| + def GitBranch(self):
|
| + return self.Git("branch")
|
| +
|
| + def GitCreateBranch(self, name, branch=""):
|
| + assert name
|
| + self.Git(MakeArgs(["checkout -b", name, branch]))
|
| +
|
| + def GitDeleteBranch(self, name):
|
| + assert name
|
| + self.Git(MakeArgs(["branch -D", name]))
|
| +
|
| + def GitCheckout(self, name):
|
| + assert name
|
| + self.Git(MakeArgs(["checkout -f", name]))
|
| +
|
| + @Strip
|
| + def GitCurrentBranch(self):
|
| + for line in self.Git("status -s -b -uno").strip().splitlines():
|
| + match = re.match(r"^## (.+)", line)
|
| + if match: return match.group(1)
|
| + raise Exception("Couldn't find curent branch.")
|
| +
|
| + @Strip
|
| + def GitLog(self, n=0, format="", grep="", git_hash="", parent_hash="",
|
| + branch="", reverse=False, patch=False):
|
| + 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)
|
| + if reverse:
|
| + args.append("--reverse")
|
| + if patch:
|
| + args.append("-p")
|
| + if git_hash:
|
| + args.append(git_hash)
|
| + if parent_hash:
|
| + args.append("%s^" % parent_hash)
|
| + args.append(branch)
|
| + return self.Git(MakeArgs(args))
|
| +
|
| + def GitAdd(self, name):
|
| + assert name
|
| + self.Git(MakeArgs(["add", Quoted(name)]))
|
| +
|
| + def GitApplyPatch(self, patch_file, reverse=False):
|
| + assert patch_file
|
| + args = ["apply --index --reject"]
|
| + if reverse:
|
| + args.append("--reverse")
|
| + args.append(Quoted(patch_file))
|
| + self.Git(MakeArgs(args))
|
| +
|
| + def GitUpload(self, reviewer="", author="", force=False):
|
| + args = ["cl upload --send-mail"]
|
| + if author:
|
| + args += ["--email", Quoted(author)]
|
| + if reviewer:
|
| + args += ["-r", Quoted(reviewer)]
|
| + if force:
|
| + args.append("-f")
|
| + # TODO(machenbach): Check output in forced mode. Verify that all required
|
| + # base files were uploaded, if not retry.
|
| + self.Git(MakeArgs(args), pipe=False)
|
| +
|
| + def GitCommit(self, message="", file_name=""):
|
| + assert message or file_name
|
| + args = ["commit"]
|
| + if file_name:
|
| + args += ["-aF", Quoted(file_name)]
|
| + if message:
|
| + args += ["-am", Quoted(message)]
|
| + self.Git(MakeArgs(args))
|
| +
|
| + def GitPresubmit(self):
|
| + self.Git("cl presubmit", "PRESUBMIT_TREE_CHECK=\"skip\"")
|
| +
|
| + def GitDCommit(self):
|
| + self.Git("cl dcommit -f --bypass-hooks", retry_on=lambda x: x is None)
|
| +
|
| + def GitDiff(self, loc1, loc2):
|
| + return self.Git(MakeArgs(["diff", loc1, loc2]))
|
| +
|
| + def GitPull(self):
|
| + self.Git("pull")
|
| +
|
| + def GitSVNFetch(self):
|
| + self.Git("svn fetch")
|
| +
|
| + @Strip
|
| + def GitSVNLog(self):
|
| + return self.Git("svn log -1 --oneline")
|
| +
|
| + @Strip
|
| + def GitSVNFindGitHash(self, revision, branch=""):
|
| + assert revision
|
| + return self.Git(MakeArgs(["svn find-rev", "r%s" % revision, branch]))
|
| +
|
| + @Strip
|
| + def GitSVNFindSVNRev(self, git_hash, branch=""):
|
| + return self.Git(MakeArgs(["svn find-rev", git_hash, branch]))
|
| +
|
| + def GitSVNDCommit(self):
|
| + return self.Git("svn dcommit 2>&1", retry_on=lambda x: x is None)
|
| +
|
| + def GitSVNTag(self, version):
|
| + self.Git(("svn tag %s -m \"Tagging version %s\"" % (version, version)),
|
| + retry_on=lambda x: x is None)
|
|
|