Commit 8e416c83 authored by chase@chromium.org's avatar chase@chromium.org

Git support in presubmit tests.

Expand presubmit_support and gclient_scm to support
getting basic status and changed files from a Git
checkout.

BUG=5339
TEST=presubmit_support.py works from a git checkout,
gcl presubmit works from a svn checkout
Review URL: http://codereview.chromium.org/242140

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@28092 0039d316-1c4b-4281-b951-d872f2087c98
parent 810a50b1
...@@ -23,6 +23,7 @@ import xml.dom.minidom ...@@ -23,6 +23,7 @@ import xml.dom.minidom
import gclient_utils import gclient_utils
SVN_COMMAND = "svn" SVN_COMMAND = "svn"
GIT_COMMAND = "git"
### SCM abstraction layer ### SCM abstraction layer
...@@ -442,6 +443,62 @@ class SVNWrapper(SCMWrapper): ...@@ -442,6 +443,62 @@ class SVNWrapper(SCMWrapper):
RunSVNAndFilterOutput(command, path, False, False, filterer.Filter) RunSVNAndFilterOutput(command, path, False, False, filterer.Filter)
# -----------------------------------------------------------------------------
# Git utils:
def CaptureGit(args, in_directory=None, print_error=True):
"""Runs git, capturing output sent to stdout as a string.
Args:
args: A sequence of command line parameters to be passed to git.
in_directory: The directory where git is to be run.
Returns:
The output sent to stdout as a string.
"""
c = [GIT_COMMAND]
c.extend(args)
# *Sigh*: Windows needs shell=True, or else it won't search %PATH% for
# the git.exe executable, but shell=True makes subprocess on Linux fail
# when it's called with a list because it only tries to execute the
# first string ("git").
stderr = None
if not print_error:
stderr = subprocess.PIPE
return subprocess.Popen(c,
cwd=in_directory,
shell=sys.platform.startswith('win'),
stdout=subprocess.PIPE,
stderr=stderr).communicate()[0]
def CaptureGitStatus(files, upstream_branch='origin'):
"""Returns git status.
@files can be a string (one file) or a list of files.
Returns an array of (status, file) tuples."""
command = ["diff", "--name-status", "-r", "%s.." % upstream_branch]
if not files:
pass
elif isinstance(files, basestring):
command.append(files)
else:
command.extend(files)
status = CaptureGit(command).rstrip()
results = []
if status:
for statusline in status.split('\n'):
m = re.match('^(\w)\t(.+)$', statusline)
if not m:
raise Exception("status currently unsupported: %s" % statusline)
results.append(('%s ' % m.group(1), m.group(2)))
return results
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# SVN utils: # SVN utils:
......
...@@ -389,7 +389,7 @@ class AffectedFile(object): ...@@ -389,7 +389,7 @@ class AffectedFile(object):
def AbsoluteLocalPath(self): def AbsoluteLocalPath(self):
"""Returns the absolute path of this file on the local disk. """Returns the absolute path of this file on the local disk.
""" """
return normpath(os.path.join(self._local_root, self.LocalPath())) return os.path.abspath(os.path.join(self._local_root, self.LocalPath()))
def IsDirectory(self): def IsDirectory(self):
"""Returns true if this object is a directory.""" """Returns true if this object is a directory."""
...@@ -562,7 +562,8 @@ class Change(object): ...@@ -562,7 +562,8 @@ class Change(object):
files = [] files = []
self._name = name self._name = name
self._full_description = description self._full_description = description
self._local_root = local_root # Convert root into an absolute path.
self._local_root = os.path.abspath(local_root)
self.issue = issue self.issue = issue
self.patchset = patchset self.patchset = patchset
self.scm = '' self.scm = ''
...@@ -764,6 +765,12 @@ class PresubmitExecuter(object): ...@@ -764,6 +765,12 @@ class PresubmitExecuter(object):
Return: Return:
A list of result objects, empty if no problems. A list of result objects, empty if no problems.
""" """
# Change to the presubmit file's directory to support local imports.
main_path = os.getcwd()
os.chdir(os.path.dirname(presubmit_path))
# Load the presubmit script into context.
input_api = InputApi(self.change, presubmit_path, self.committing) input_api = InputApi(self.change, presubmit_path, self.committing)
context = {} context = {}
exec script_text in context exec script_text in context
...@@ -789,6 +796,8 @@ class PresubmitExecuter(object): ...@@ -789,6 +796,8 @@ class PresubmitExecuter(object):
else: else:
result = () # no error since the script doesn't care about current event. result = () # no error since the script doesn't care about current event.
# Return the process to the original working directory.
os.chdir(main_path)
return result return result
...@@ -939,7 +948,7 @@ def Main(argv): ...@@ -939,7 +948,7 @@ def Main(argv):
options.files = ParseFiles(args, options.recursive) options.files = ParseFiles(args, options.recursive)
else: else:
# Grab modified files. # Grab modified files.
raise NotImplementedException() # TODO(maruel) Implement. options.files = gclient_scm.CaptureGitStatus([options.root])
elif os.path.isdir(os.path.join(options.root, '.svn')): elif os.path.isdir(os.path.join(options.root, '.svn')):
change_class = SvnChange change_class = SvnChange
if not options.files: if not options.files:
...@@ -947,12 +956,15 @@ def Main(argv): ...@@ -947,12 +956,15 @@ def Main(argv):
options.files = ParseFiles(args, options.recursive) options.files = ParseFiles(args, options.recursive)
else: else:
# Grab modified files. # Grab modified files.
files = gclient_scm.CaptureSVNStatus([options.root]) options.files = gclient_scm.CaptureSVNStatus([options.root])
else: else:
# Doesn't seem under source control. # Doesn't seem under source control.
change_class = Change change_class = Change
if options.verbose: if options.verbose:
if len(options.files) != 1:
print "Found %d files." % len(options.files) print "Found %d files." % len(options.files)
else:
print "Found 1 file."
return not DoPresubmitChecks(change_class(options.name, return not DoPresubmitChecks(change_class(options.name,
options.description, options.description,
options.root, options.root,
......
...@@ -53,12 +53,16 @@ def CheckChangeOnUpload(input_api, output_api): ...@@ -53,12 +53,16 @@ def CheckChangeOnUpload(input_api, output_api):
self.mox.StubOutWithMock(presubmit, 'random') self.mox.StubOutWithMock(presubmit, 'random')
self.mox.StubOutWithMock(presubmit, 'sys') self.mox.StubOutWithMock(presubmit, 'sys')
presubmit._ASKED_FOR_FEEDBACK = False presubmit._ASKED_FOR_FEEDBACK = False
presubmit.os.path.commonprefix = os_path_commonprefix
self.fake_root_dir = self.RootDir()
# Special mocks. # Special mocks.
def MockAbsPath(f): def MockAbsPath(f):
return f return f
def MockChdir(f):
return None
presubmit.os.path.abspath = MockAbsPath presubmit.os.path.abspath = MockAbsPath
presubmit.os.path.commonprefix = os_path_commonprefix presubmit.os.getcwd = self.RootDir
self.fake_root_dir = self.RootDir() presubmit.os.chdir = MockChdir
self.mox.StubOutWithMock(presubmit.gclient_scm, 'CaptureSVNInfo') self.mox.StubOutWithMock(presubmit.gclient_scm, 'CaptureSVNInfo')
self.mox.StubOutWithMock(presubmit.gcl, 'GetSVNFileProperty') self.mox.StubOutWithMock(presubmit.gcl, 'GetSVNFileProperty')
self.mox.StubOutWithMock(presubmit.gcl, 'ReadFile') self.mox.StubOutWithMock(presubmit.gcl, 'ReadFile')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment