Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / v8 / tools / push-to-trunk / git_recipes.py
index 6ffb2da..0f8fcef 100644 (file)
 
 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, **kwargs):
     args = ["cl upload --send-mail"]
     if author:
       args += ["--email", Quoted(author)]
@@ -162,52 +208,102 @@ class GitRecipesMixin(object):
       args.append("--bypass-hooks")
     # 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, **kwargs):
+    self.Git("cl presubmit", "PRESUBMIT_TREE_CHECK=\"skip\"", **kwargs)
 
-  def GitPresubmit(self):
-    self.Git("cl presubmit", "PRESUBMIT_TREE_CHECK=\"skip\"")
+  def GitDCommit(self, **kwargs):
+    self.Git(
+        "cl dcommit -f --bypass-hooks", retry_on=lambda x: x is None, **kwargs)
 
-  def GitDCommit(self):
-    self.Git("cl dcommit -f --bypass-hooks", retry_on=lambda x: x is None)
+  def GitDiff(self, loc1, loc2, **kwargs):
+    return self.Git(MakeArgs(["diff", loc1, loc2]), **kwargs)
 
-  def GitDiff(self, loc1, loc2):
-    return self.Git(MakeArgs(["diff", loc1, loc2]))
+  def GitPull(self, **kwargs):
+    self.Git("pull", **kwargs)
 
-  def GitPull(self):
-    self.Git("pull")
+  def GitFetchOrigin(self, **kwargs):
+    self.Git("fetch origin", **kwargs)
 
-  def GitSVNFetch(self):
-    self.Git("svn fetch")
+  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)
 
-  def GitSVNRebase(self):
-    self.Git("svn rebase")
+  @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]))
+    return self.Git(
+        MakeArgs(["svn find-rev", "r%s" % revision, branch]), **kwargs)
 
   @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)