diff options
Diffstat (limited to 'deps/v8/tools/push-to-trunk/git_recipes.py')
-rw-r--r-- | deps/v8/tools/push-to-trunk/git_recipes.py | 217 |
1 files changed, 159 insertions, 58 deletions
diff --git a/deps/v8/tools/push-to-trunk/git_recipes.py b/deps/v8/tools/push-to-trunk/git_recipes.py index 6ffb2da834..a1e6256df2 100644 --- a/deps/v8/tools/push-to-trunk/git_recipes.py +++ b/deps/v8/tools/push-to-trunk/git_recipes.py @@ -28,6 +28,51 @@ 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'((?:\w+)://[^@]+)@(\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 @@ -49,54 +94,55 @@ def Quoted(s): class GitRecipesMixin(object): - def GitIsWorkdirClean(self): - return self.Git("status -s -uno").strip() == "" + def GitIsWorkdirClean(self, **kwargs): + return self.Git("status -s -uno", **kwargs).strip() == "" @Strip - def GitBranch(self): - return self.Git("branch") + def GitBranch(self, **kwargs): + return self.Git("branch", **kwargs) - def GitCreateBranch(self, name, branch=""): + def GitCreateBranch(self, name, branch="", **kwargs): assert name - self.Git(MakeArgs(["checkout -b", name, branch])) + self.Git(MakeArgs(["checkout -b", name, branch]), **kwargs) - def GitDeleteBranch(self, name): + def GitDeleteBranch(self, name, **kwargs): assert name - self.Git(MakeArgs(["branch -D", name])) + self.Git(MakeArgs(["branch -D", name]), **kwargs) - def GitReset(self, name): + def GitReset(self, name, **kwargs): assert name - self.Git(MakeArgs(["reset --hard", name])) + self.Git(MakeArgs(["reset --hard", name]), **kwargs) - def GitStash(self): - self.Git(MakeArgs(["stash"])) + def GitStash(self, **kwargs): + self.Git(MakeArgs(["stash"]), **kwargs) - def GitRemotes(self): - return map(str.strip, self.Git(MakeArgs(["branch -r"])).splitlines()) + def GitRemotes(self, **kwargs): + return map(str.strip, + self.Git(MakeArgs(["branch -r"]), **kwargs).splitlines()) - def GitCheckout(self, name): + def GitCheckout(self, name, **kwargs): assert name - self.Git(MakeArgs(["checkout -f", name])) + self.Git(MakeArgs(["checkout -f", name]), **kwargs) - def GitCheckoutFile(self, name, branch_or_hash): + def GitCheckoutFile(self, name, branch_or_hash, **kwargs): assert name assert branch_or_hash - self.Git(MakeArgs(["checkout -f", branch_or_hash, "--", name])) + self.Git(MakeArgs(["checkout -f", branch_or_hash, "--", name]), **kwargs) - def GitCheckoutFileSafe(self, name, branch_or_hash): + def GitCheckoutFileSafe(self, name, branch_or_hash, **kwargs): try: - self.GitCheckoutFile(name, branch_or_hash) + 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): + def GitChangedFiles(self, git_hash, **kwargs): assert git_hash try: files = self.Git(MakeArgs(["diff --name-only", git_hash, - "%s^" % git_hash])) + "%s^" % git_hash]), **kwargs) return map(str.strip, files.splitlines()) except GitFailedException: # pragma: no cover # Git fails using "^" at branch roots. @@ -104,15 +150,15 @@ class GitRecipesMixin(object): @Strip - def GitCurrentBranch(self): - for line in self.Git("status -s -b -uno").strip().splitlines(): + 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): + branch="", reverse=False, **kwargs): assert not (git_hash and parent_hash) args = ["log"] if n > 0: @@ -128,27 +174,27 @@ class GitRecipesMixin(object): if parent_hash: args.append("%s^" % parent_hash) args.append(branch) - return self.Git(MakeArgs(args)) + return self.Git(MakeArgs(args), **kwargs) - def GitGetPatch(self, git_hash): + def GitGetPatch(self, git_hash, **kwargs): assert git_hash - return self.Git(MakeArgs(["log", "-1", "-p", git_hash])) + return self.Git(MakeArgs(["log", "-1", "-p", git_hash]), **kwargs) # TODO(machenbach): Unused? Remove. - def GitAdd(self, name): + def GitAdd(self, name, **kwargs): assert name - self.Git(MakeArgs(["add", Quoted(name)])) + self.Git(MakeArgs(["add", Quoted(name)]), **kwargs) - def GitApplyPatch(self, patch_file, reverse=False): + 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)) + self.Git(MakeArgs(args), **kwargs) def GitUpload(self, reviewer="", author="", force=False, cq=False, - bypass_hooks=False): + bypass_hooks=False, cc="", **kwargs): args = ["cl upload --send-mail"] if author: args += ["--email", Quoted(author)] @@ -160,54 +206,109 @@ class GitRecipesMixin(object): 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) + self.Git(MakeArgs(args), pipe=False, **kwargs) - def GitCommit(self, message="", file_name=""): + 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)] - self.Git(MakeArgs(args)) + if author: + args += ["--author", "\"%s <%s>\"" % (author, author)] + self.Git(MakeArgs(args), **kwargs) - def GitPresubmit(self): - self.Git("cl presubmit", "PRESUBMIT_TREE_CHECK=\"skip\"") + def GitPresubmit(self, **kwargs): + self.Git("cl presubmit", "PRESUBMIT_TREE_CHECK=\"skip\"", **kwargs) - def GitDCommit(self): - self.Git("cl dcommit -f --bypass-hooks", retry_on=lambda x: x is None) + def GitDCommit(self, **kwargs): + self.Git( + "cl dcommit -f --bypass-hooks", retry_on=lambda x: x is None, **kwargs) - def GitDiff(self, loc1, loc2): - return self.Git(MakeArgs(["diff", loc1, loc2])) + def GitDiff(self, loc1, loc2, **kwargs): + return self.Git(MakeArgs(["diff", loc1, loc2]), **kwargs) - def GitPull(self): - self.Git("pull") + def GitPull(self, **kwargs): + self.Git("pull", **kwargs) - def GitSVNFetch(self): - self.Git("svn fetch") + def GitFetchOrigin(self, **kwargs): + self.Git("fetch origin", **kwargs) - def GitSVNRebase(self): - self.Git("svn rebase") + def GitConvertToSVNRevision(self, git_hash, **kwargs): + result = self.Git(MakeArgs(["rev-list", "-n", "1", git_hash]), **kwargs) + if not result or not SHA1_RE.match(result): + raise GitFailedException("Git hash %s is unknown." % git_hash) + log = self.GitLog(n=1, format="%B", git_hash=git_hash, **kwargs) + for line in reversed(log.splitlines()): + match = ROLL_DEPS_GIT_SVN_ID_RE.match(line.strip()) + if match: + return match.group(1) + raise GitFailedException("Couldn't convert %s to SVN." % git_hash) + + @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(2) + return None + + ### Git svn stuff + + def GitSVNFetch(self, **kwargs): + self.Git("svn fetch", **kwargs) + + def GitSVNRebase(self, **kwargs): + self.Git("svn rebase", **kwargs) # TODO(machenbach): Unused? Remove. @Strip - def GitSVNLog(self): - return self.Git("svn log -1 --oneline") + def GitSVNLog(self, **kwargs): + return self.Git("svn log -1 --oneline", **kwargs) @Strip - def GitSVNFindGitHash(self, revision, branch=""): + def GitSVNFindGitHash(self, revision, branch="", **kwargs): assert revision - return self.Git(MakeArgs(["svn find-rev", "r%s" % revision, branch])) + args = MakeArgs(["svn find-rev", "r%s" % revision, branch]) + + # Pick the last line if multiple lines are available. The first lines might + # print information about rebuilding the svn-git mapping. + return self.Git(args, **kwargs).splitlines()[-1] @Strip - def GitSVNFindSVNRev(self, git_hash, branch=""): - return self.Git(MakeArgs(["svn find-rev", git_hash, branch])) + def GitSVNFindSVNRev(self, git_hash, branch="", **kwargs): + return self.Git(MakeArgs(["svn find-rev", git_hash, branch]), **kwargs) - def GitSVNDCommit(self): - return self.Git("svn dcommit 2>&1", retry_on=lambda x: x is None) + def GitSVNDCommit(self, **kwargs): + return self.Git("svn dcommit 2>&1", retry_on=lambda x: x is None, **kwargs) - def GitSVNTag(self, version): + def GitSVNTag(self, version, **kwargs): self.Git(("svn tag %s -m \"Tagging version %s\"" % (version, version)), - retry_on=lambda x: x is None) + retry_on=lambda x: x is None, + **kwargs) |