• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# Copyright 2014 the V8 project authors. All rights reserved.
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions are
5# met:
6#
7#     * Redistributions of source code must retain the above copyright
8#       notice, this list of conditions and the following disclaimer.
9#     * Redistributions in binary form must reproduce the above
10#       copyright notice, this list of conditions and the following
11#       disclaimer in the documentation and/or other materials provided
12#       with the distribution.
13#     * Neither the name of Google Inc. nor the names of its
14#       contributors may be used to endorse or promote products derived
15#       from this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29import re
30
31
32class GitFailedException(Exception):
33  pass
34
35
36def Strip(f):
37  def new_f(*args, **kwargs):
38    return f(*args, **kwargs).strip()
39  return new_f
40
41
42def MakeArgs(l):
43  """['-a', '', 'abc', ''] -> '-a abc'"""
44  return " ".join(filter(None, l))
45
46
47def Quoted(s):
48  return "\"%s\"" % s
49
50
51class GitRecipesMixin(object):
52  def GitIsWorkdirClean(self):
53    return self.Git("status -s -uno").strip() == ""
54
55  @Strip
56  def GitBranch(self):
57    return self.Git("branch")
58
59  def GitCreateBranch(self, name, branch=""):
60    assert name
61    self.Git(MakeArgs(["checkout -b", name, branch]))
62
63  def GitDeleteBranch(self, name):
64    assert name
65    self.Git(MakeArgs(["branch -D", name]))
66
67  def GitReset(self, name):
68    assert name
69    self.Git(MakeArgs(["reset --hard", name]))
70
71  def GitRemotes(self):
72    return map(str.strip, self.Git(MakeArgs(["branch -r"])).splitlines())
73
74  def GitCheckout(self, name):
75    assert name
76    self.Git(MakeArgs(["checkout -f", name]))
77
78  def GitCheckoutFile(self, name, branch_or_hash):
79    assert name
80    assert branch_or_hash
81    self.Git(MakeArgs(["checkout -f", branch_or_hash, "--", name]))
82
83  def GitCheckoutFileSafe(self, name, branch_or_hash):
84    try:
85      self.GitCheckoutFile(name, branch_or_hash)
86    except GitFailedException:  # pragma: no cover
87      # The file doesn't exist in that revision.
88      return False
89    return True
90
91  def GitChangedFiles(self, git_hash):
92    assert git_hash
93    try:
94      files = self.Git(MakeArgs(["diff --name-only",
95                                 git_hash,
96                                 "%s^" % git_hash]))
97      return map(str.strip, files.splitlines())
98    except GitFailedException:  # pragma: no cover
99      # Git fails using "^" at branch roots.
100      return []
101
102
103  @Strip
104  def GitCurrentBranch(self):
105    for line in self.Git("status -s -b -uno").strip().splitlines():
106      match = re.match(r"^## (.+)", line)
107      if match: return match.group(1)
108    raise Exception("Couldn't find curent branch.")  # pragma: no cover
109
110  @Strip
111  def GitLog(self, n=0, format="", grep="", git_hash="", parent_hash="",
112             branch="", reverse=False):
113    assert not (git_hash and parent_hash)
114    args = ["log"]
115    if n > 0:
116      args.append("-%d" % n)
117    if format:
118      args.append("--format=%s" % format)
119    if grep:
120      args.append("--grep=\"%s\"" % grep.replace("\"", "\\\""))
121    if reverse:
122      args.append("--reverse")
123    if git_hash:
124      args.append(git_hash)
125    if parent_hash:
126      args.append("%s^" % parent_hash)
127    args.append(branch)
128    return self.Git(MakeArgs(args))
129
130  def GitGetPatch(self, git_hash):
131    assert git_hash
132    return self.Git(MakeArgs(["log", "-1", "-p", git_hash]))
133
134  # TODO(machenbach): Unused? Remove.
135  def GitAdd(self, name):
136    assert name
137    self.Git(MakeArgs(["add", Quoted(name)]))
138
139  def GitApplyPatch(self, patch_file, reverse=False):
140    assert patch_file
141    args = ["apply --index --reject"]
142    if reverse:
143      args.append("--reverse")
144    args.append(Quoted(patch_file))
145    self.Git(MakeArgs(args))
146
147  def GitUpload(self, reviewer="", author="", force=False):
148    args = ["cl upload --send-mail"]
149    if author:
150      args += ["--email", Quoted(author)]
151    if reviewer:
152      args += ["-r", Quoted(reviewer)]
153    if force:
154      args.append("-f")
155    # TODO(machenbach): Check output in forced mode. Verify that all required
156    # base files were uploaded, if not retry.
157    self.Git(MakeArgs(args), pipe=False)
158
159  def GitCommit(self, message="", file_name=""):
160    assert message or file_name
161    args = ["commit"]
162    if file_name:
163      args += ["-aF", Quoted(file_name)]
164    if message:
165      args += ["-am", Quoted(message)]
166    self.Git(MakeArgs(args))
167
168  def GitPresubmit(self):
169    self.Git("cl presubmit", "PRESUBMIT_TREE_CHECK=\"skip\"")
170
171  def GitDCommit(self):
172    self.Git("cl dcommit -f --bypass-hooks", retry_on=lambda x: x is None)
173
174  def GitDiff(self, loc1, loc2):
175    return self.Git(MakeArgs(["diff", loc1, loc2]))
176
177  def GitPull(self):
178    self.Git("pull")
179
180  def GitSVNFetch(self):
181    self.Git("svn fetch")
182
183  # TODO(machenbach): Unused? Remove.
184  @Strip
185  def GitSVNLog(self):
186    return self.Git("svn log -1 --oneline")
187
188  @Strip
189  def GitSVNFindGitHash(self, revision, branch=""):
190    assert revision
191    return self.Git(MakeArgs(["svn find-rev", "r%s" % revision, branch]))
192
193  @Strip
194  def GitSVNFindSVNRev(self, git_hash, branch=""):
195    return self.Git(MakeArgs(["svn find-rev", git_hash, branch]))
196
197  def GitSVNDCommit(self):
198    return self.Git("svn dcommit 2>&1", retry_on=lambda x: x is None)
199
200  def GitSVNTag(self, version):
201    self.Git(("svn tag %s -m \"Tagging version %s\"" % (version, version)),
202             retry_on=lambda x: x is None)
203