Commit d579fcf9 authored by maruel@chromium.org's avatar maruel@chromium.org

Enforces using cwd in all svn calls.

That helps weed out some issues faces with svn plus helped me figure out some
misuses.

Most of the commands have been implicitly depending on os.getcwd(). This change
makes it always consistent and clear when dependence on the current directory is
needed.

Remove default arguments to scm.SVN.GenerateDiff and a few other calls to be
sure the refactoring was done right.

R=dpranke@chromium.org
BUG=
TEST=make sure most commands aren't broke


Review URL: http://codereview.chromium.org/8771042

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@114262 0039d316-1c4b-4281-b951-d872f2087c98
parent 4159b736
......@@ -87,7 +87,10 @@ def CheckHomeForFile(filename):
def UnknownFiles():
"""Runs svn status and returns unknown files."""
return [item[1] for item in SVN.CaptureStatus([]) if item[0][0] == '?']
return [
item[1] for item in SVN.CaptureStatus([], GetRepositoryRoot())
if item[0][0] == '?'
]
def GetRepositoryRoot():
......@@ -138,7 +141,7 @@ def GetCachedFile(filename, max_age=60*60*24*3, use_root=False):
return None
if (not os.path.exists(cached_file) or
(time.time() - os.stat(cached_file).st_mtime) > max_age):
dir_info = SVN.CaptureInfo('.')
dir_info = SVN.CaptureLocalInfo([], '.')
repo_root = dir_info['Repository Root']
if use_root:
url_path = repo_root
......@@ -548,8 +551,7 @@ class ChangeInfo(object):
files = values['files']
if update_status:
for item in files[:]:
filename = os.path.join(local_root, item[1])
status_result = SVN.CaptureStatus(filename)
status_result = SVN.CaptureStatus(item[1], local_root)
if not status_result or not status_result[0][0]:
# File has been reverted.
save = True
......@@ -678,7 +680,7 @@ def GetModifiedFiles():
files_in_cl[filename] = change_info.name
# Get all the modified files.
status_result = SVN.CaptureStatus(None)
status_result = SVN.CaptureStatus(None, GetRepositoryRoot())
for line in status_result:
status = line[0]
filename = line[1]
......@@ -733,8 +735,9 @@ def ListFiles(show_unknown_files):
return 0
def GenerateDiff(files, root=None):
return SVN.GenerateDiff(files, root=root)
def GenerateDiff(files):
return SVN.GenerateDiff(
files, GetRepositoryRoot(), full_move=False, revision=None)
def OptionallyDoPresubmitChecks(change_info, committing, args):
......@@ -1037,7 +1040,14 @@ def CMDcommit(change_info, args):
def CMDchange(args):
"""Creates or edits a changelist.
Only scans the current directory and subdirectories."""
Only scans the current directory and subdirectories.
"""
# Verify the user is running the change command from a read-write checkout.
svn_info = SVN.CaptureLocalInfo([], '.')
if not svn_info:
ErrorExit("Current checkout is unversioned. Please retry with a versioned "
"directory.")
if len(args) == 0:
# Generate a random changelist name.
changename = GenerateChangeName()
......@@ -1047,12 +1057,6 @@ def CMDchange(args):
changename = args[0]
change_info = ChangeInfo.Load(changename, GetRepositoryRoot(), False, True)
# Verify the user is running the change command from a read-write checkout.
svn_info = SVN.CaptureInfo('.')
if not svn_info:
ErrorExit("Current checkout is unversioned. Please retry with a versioned "
"directory.")
if len(args) == 2:
if not os.path.isfile(args[1]):
ErrorExit('The change "%s" doesn\'t exist.' % args[1])
......@@ -1439,6 +1443,7 @@ def main(argv):
except upload.ClientLoginError, e:
print >> sys.stderr, 'Got an exception logging in to Rietveld'
print >> sys.stderr, str(e)
return 1
except urllib2.HTTPError, e:
if e.code != 500:
raise
......
......@@ -711,8 +711,9 @@ class SVNWrapper(SCMWrapper):
def GetRevisionDate(self, revision):
"""Returns the given revision's date in ISO-8601 format (which contains the
time zone)."""
date = scm.SVN.Capture(['propget', '--revprop', 'svn:date', '-r', revision,
os.path.join(self.checkout_path, '.')])
date = scm.SVN.Capture(
['propget', '--revprop', 'svn:date', '-r', revision],
os.path.join(self.checkout_path, '.'))
return date.strip()
def cleanup(self, options, args, file_list):
......@@ -796,7 +797,8 @@ class SVNWrapper(SCMWrapper):
# Get the existing scm url and the revision number of the current checkout.
try:
from_info = scm.SVN.CaptureInfo(os.path.join(self.checkout_path, '.'))
from_info = scm.SVN.CaptureLocalInfo(
[], os.path.join(self.checkout_path, '.'))
except (gclient_utils.Error, subprocess2.CalledProcessError):
raise gclient_utils.Error(
('Can\'t update/checkout %s if an unversioned directory is present. '
......@@ -809,14 +811,16 @@ class SVNWrapper(SCMWrapper):
self.checkout_path, from_info))
# Look for locked directories.
dir_info = scm.SVN.CaptureStatus(os.path.join(self.checkout_path, '.'))
dir_info = scm.SVN.CaptureStatus(
None, os.path.join(self.checkout_path, '.'))
if any(d[0][2] == 'L' for d in dir_info):
try:
self._Run(['cleanup', self.checkout_path], options)
except subprocess2.CalledProcessError, e:
# Get the status again, svn cleanup may have cleaned up at least
# something.
dir_info = scm.SVN.CaptureStatus(os.path.join(self.checkout_path, '.'))
dir_info = scm.SVN.CaptureStatus(
None, os.path.join(self.checkout_path, '.'))
# Try to fix the failures by removing troublesome files.
for d in dir_info:
......@@ -832,14 +836,14 @@ class SVNWrapper(SCMWrapper):
# Retrieve the current HEAD version because svn is slow at null updates.
if options.manually_grab_svn_rev and not revision:
from_info_live = scm.SVN.CaptureInfo(from_info['URL'])
from_info_live = scm.SVN.CaptureRemoteInfo(from_info['URL'])
revision = str(from_info_live['Revision'])
rev_str = ' at %s' % revision
if from_info['URL'] != base_url:
# The repository url changed, need to switch.
try:
to_info = scm.SVN.CaptureInfo(url)
to_info = scm.SVN.CaptureRemoteInfo(url)
except (gclient_utils.Error, subprocess2.CalledProcessError):
# The url is invalid or the server is not accessible, it's safer to bail
# out right now.
......@@ -868,7 +872,7 @@ class SVNWrapper(SCMWrapper):
else:
if not options.force and not options.reset:
# Look for local modifications but ignore unversioned files.
for status in scm.SVN.CaptureStatus(self.checkout_path):
for status in scm.SVN.CaptureStatus(None, self.checkout_path):
if status[0] != '?':
raise gclient_utils.Error(
('Can\'t switch the checkout to %s; UUID don\'t match and '
......
......@@ -302,9 +302,8 @@ class InputApi(object):
Remember to check for the None case and show an appropriate error!
"""
local_path = scm.SVN.CaptureInfo(depot_path).get('Path')
if local_path:
return local_path
return scm.SVN.CaptureLocalInfo([depot_path], self.change.RepositoryRoot()
).get('Path')
def LocalToDepotPath(self, local_path):
"""Translate a local path to a depot path.
......@@ -315,9 +314,8 @@ class InputApi(object):
Returns:
The depot path (SVN URL) of the file if mapped, otherwise None.
"""
depot_path = scm.SVN.CaptureInfo(local_path).get('URL')
if depot_path:
return depot_path
return scm.SVN.CaptureLocalInfo([local_path], self.change.RepositoryRoot()
).get('URL')
def AffectedFiles(self, include_dirs=False, include_deletes=True,
file_filter=None):
......@@ -429,7 +427,7 @@ class AffectedFile(object):
"""Representation of a file in a change."""
# Method could be a function
# pylint: disable=R0201
def __init__(self, path, action, repository_root=''):
def __init__(self, path, action, repository_root):
self._path = path
self._action = action
self._local_root = repository_root
......@@ -563,8 +561,8 @@ class SvnAffectedFile(AffectedFile):
def ServerPath(self):
if self._server_path is None:
self._server_path = scm.SVN.CaptureInfo(
self.AbsoluteLocalPath()).get('URL', '')
self._server_path = scm.SVN.CaptureLocalInfo(
[self.LocalPath()], self._local_root).get('URL', '')
return self._server_path
def IsDirectory(self):
......@@ -575,14 +573,15 @@ class SvnAffectedFile(AffectedFile):
# querying subversion, especially on Windows.
self._is_directory = os.path.isdir(path)
else:
self._is_directory = scm.SVN.CaptureInfo(
path).get('Node Kind') in ('dir', 'directory')
self._is_directory = scm.SVN.CaptureLocalInfo(
[self.LocalPath()], self._local_root
).get('Node Kind') in ('dir', 'directory')
return self._is_directory
def Property(self, property_name):
if not property_name in self._properties:
self._properties[property_name] = scm.SVN.GetFileProperty(
self.AbsoluteLocalPath(), property_name).rstrip()
self.LocalPath(), property_name, self._local_root).rstrip()
return self._properties[property_name]
def IsTextFile(self):
......@@ -593,13 +592,14 @@ class SvnAffectedFile(AffectedFile):
elif self.IsDirectory():
self._is_text_file = False
else:
mime_type = scm.SVN.GetFileProperty(self.AbsoluteLocalPath(),
'svn:mime-type')
mime_type = scm.SVN.GetFileProperty(
self.LocalPath(), 'svn:mime-type', self._local_root)
self._is_text_file = (not mime_type or mime_type.startswith('text/'))
return self._is_text_file
def GenerateScmDiff(self):
return scm.SVN.GenerateDiff([self.AbsoluteLocalPath()])
return scm.SVN.GenerateDiff(
[self.LocalPath()], self._local_root, False, None)
class GitAffectedFile(AffectedFile):
......
......@@ -398,13 +398,13 @@ class SVN(object):
current_version = None
@staticmethod
def Capture(args, **kwargs):
def Capture(args, cwd, **kwargs):
"""Always redirect stderr.
Throws an exception if non-0 is returned.
"""
return subprocess2.check_output(
['svn'] + args, stderr=subprocess2.PIPE, **kwargs)
['svn'] + args, stderr=subprocess2.PIPE, cwd=cwd, **kwargs)
@staticmethod
def RunAndGetFileList(verbose, args, cwd, file_list, stdout=None):
......@@ -514,13 +514,30 @@ class SVN(object):
break
@staticmethod
def CaptureInfo(cwd):
def CaptureRemoteInfo(url):
"""Returns a dictionary from the svn info output for the given url.
Throws an exception if svn info fails.
"""
assert isinstance(url, str)
return SVN._CaptureInfo([url], None)
@staticmethod
def CaptureLocalInfo(files, cwd):
"""Returns a dictionary from the svn info output for the given files.
Throws an exception if svn info fails.
"""
assert isinstance(files, (list, tuple))
return SVN._CaptureInfo(files, cwd)
@staticmethod
def _CaptureInfo(files, cwd):
"""Returns a dictionary from the svn info output for the given file.
Throws an exception if svn info fails."""
result = {}
output = SVN.Capture(['info', '--xml', cwd])
info = ElementTree.XML(output)
info = ElementTree.XML(SVN.Capture(['info', '--xml'] + files, cwd))
if info is None:
return result
entry = info.find('entry')
......@@ -563,10 +580,10 @@ class SVN(object):
Returns:
Int base revision
"""
return SVN.CaptureInfo(cwd).get('Revision')
return SVN.CaptureLocalInfo([], cwd).get('Revision')
@staticmethod
def CaptureStatus(files):
def CaptureStatus(files, cwd):
"""Returns the svn 1.5 svn status emulated output.
@files can be a string (one file) or a list of files.
......@@ -598,7 +615,7 @@ class SVN(object):
'replaced': 'R',
'unversioned': '?',
}
dom = ElementTree.XML(SVN.Capture(command))
dom = ElementTree.XML(SVN.Capture(command, cwd))
results = []
if dom is None:
return results
......@@ -645,9 +662,10 @@ class SVN(object):
return results
@staticmethod
def IsMoved(filename):
def IsMoved(filename, cwd):
"""Determine if a file has been added through svn mv"""
return SVN.IsMovedInfo(SVN.CaptureInfo(filename))
assert isinstance(filename, basestring)
return SVN.IsMovedInfo(SVN.CaptureLocalInfo([filename], cwd))
@staticmethod
def IsMovedInfo(info):
......@@ -657,7 +675,7 @@ class SVN(object):
info.get('Schedule') == 'add')
@staticmethod
def GetFileProperty(filename, property_name):
def GetFileProperty(filename, property_name, cwd):
"""Returns the value of an SVN property for the given file.
Args:
......@@ -670,12 +688,12 @@ class SVN(object):
empty string is also returned.
"""
try:
return SVN.Capture(['propget', property_name, filename])
return SVN.Capture(['propget', property_name, filename], cwd)
except subprocess2.CalledProcessError:
return ''
@staticmethod
def DiffItem(filename, full_move=False, revision=None):
def DiffItem(filename, cwd, full_move, revision):
"""Diffs a single file.
Should be simple, eh? No it isn't.
......@@ -693,15 +711,18 @@ class SVN(object):
try:
# Use "svn info" output instead of os.path.isdir because the latter fails
# when the file is deleted.
return SVN._DiffItemInternal(filename, SVN.CaptureInfo(filename),
bogus_dir,
full_move=full_move, revision=revision)
return SVN._DiffItemInternal(
filename,
cwd,
SVN.CaptureLocalInfo([filename], cwd),
bogus_dir,
full_move,
revision)
finally:
gclient_utils.RemoveDirectory(bogus_dir)
@staticmethod
def _DiffItemInternal(filename, info, bogus_dir, full_move=False,
revision=None):
def _DiffItemInternal(filename, cwd, info, bogus_dir, full_move, revision):
"""Grabs the diff data."""
command = ["diff", "--config-dir", bogus_dir, filename]
if revision:
......@@ -737,7 +758,7 @@ class SVN(object):
else:
if info.get("Node Kind") != "directory":
# svn diff on a mv/cp'd file outputs nothing if there was no change.
data = SVN.Capture(command)
data = SVN.Capture(command, cwd)
if not data:
# We put in an empty Index entry so upload.py knows about them.
data = "Index: %s\n" % filename.replace(os.sep, '/')
......@@ -746,7 +767,7 @@ class SVN(object):
if info.get("Node Kind") != "directory":
# Normal simple case.
try:
data = SVN.Capture(command)
data = SVN.Capture(command, cwd)
except subprocess2.CalledProcessError:
if revision:
data = GenFakeDiff(filename)
......@@ -756,7 +777,7 @@ class SVN(object):
return data
@staticmethod
def GenerateDiff(filenames, root=None, full_move=False, revision=None):
def GenerateDiff(filenames, cwd, full_move, revision):
"""Returns a string containing the diff for the given file list.
The files in the list should either be absolute paths or relative to the
......@@ -765,9 +786,7 @@ class SVN(object):
The diff will always use relative paths.
"""
assert isinstance(filenames, (list, tuple))
previous_cwd = os.getcwd()
root = root or SVN.GetCheckoutRoot(previous_cwd)
root = os.path.normcase(os.path.join(root, ''))
root = os.path.normcase(os.path.join(cwd, ''))
def RelativePath(path, root):
"""We must use relative paths."""
if os.path.normcase(path).startswith(root):
......@@ -781,11 +800,10 @@ class SVN(object):
# config directory, which gets around these problems.
bogus_dir = tempfile.mkdtemp()
try:
os.chdir(root)
# Cleanup filenames
filenames = [RelativePath(f, root) for f in filenames]
# Get information about the modified items (files and directories)
data = dict([(f, SVN.CaptureInfo(f)) for f in filenames])
data = dict([(f, SVN.CaptureLocalInfo([f], root)) for f in filenames])
diffs = []
if full_move:
# Eliminate modified files inside moved/copied directory.
......@@ -805,12 +823,12 @@ class SVN(object):
# for now, the most common case is a head copy,
# so let's just encode that as a straight up cp.
srcurl = info.get('Copied From URL')
root = info.get('Repository Root')
file_root = info.get('Repository Root')
rev = int(info.get('Copied From Rev'))
assert srcurl.startswith(root)
src = srcurl[len(root)+1:]
assert srcurl.startswith(file_root)
src = srcurl[len(file_root)+1:]
try:
srcinfo = SVN.CaptureInfo(srcurl)
srcinfo = SVN.CaptureRemoteInfo(srcurl)
except subprocess2.CalledProcessError, e:
if not 'Not a valid URL' in e.stderr:
raise
......@@ -818,7 +836,7 @@ class SVN(object):
# revision the file was deleted.
srcinfo = {'Revision': rev}
if (srcinfo.get('Revision') != rev and
SVN.Capture(['diff', '-r', '%d:head' % rev, srcurl])):
SVN.Capture(['diff', '-r', '%d:head' % rev, srcurl], cwd)):
metaheaders.append("#$ svn cp -r %d %s %s "
"### WARNING: note non-trunk copy\n" %
(rev, src, filename))
......@@ -832,9 +850,8 @@ class SVN(object):
diffs.append("### END SVN COPY METADATA\n")
# Now ready to do the actual diff.
for filename in sorted(data.iterkeys()):
diffs.append(SVN._DiffItemInternal(filename, data[filename], bogus_dir,
full_move=full_move,
revision=revision))
diffs.append(SVN._DiffItemInternal(
filename, cwd, data[filename], bogus_dir, full_move, revision))
# Use StringIO since it can be messy when diffing a directory move with
# full_move=True.
buf = cStringIO.StringIO()
......@@ -844,14 +861,13 @@ class SVN(object):
buf.close()
return result
finally:
os.chdir(previous_cwd)
gclient_utils.RemoveDirectory(bogus_dir)
@staticmethod
def GetEmail(repo_root):
def GetEmail(cwd):
"""Retrieves the svn account which we assume is an email address."""
try:
infos = SVN.CaptureInfo(repo_root)
infos = SVN.CaptureLocalInfo([], cwd)
except subprocess2.CalledProcessError:
return None
......@@ -904,36 +920,36 @@ class SVN(object):
return values
@staticmethod
def GetCheckoutRoot(directory):
def GetCheckoutRoot(cwd):
"""Returns the top level directory of the current repository.
The directory is returned as an absolute path.
"""
directory = os.path.abspath(directory)
cwd = os.path.abspath(cwd)
try:
info = SVN.CaptureInfo(directory)
info = SVN.CaptureLocalInfo([], cwd)
cur_dir_repo_root = info['Repository Root']
url = info['URL']
except subprocess2.CalledProcessError:
return None
while True:
parent = os.path.dirname(directory)
parent = os.path.dirname(cwd)
try:
info = SVN.CaptureInfo(parent)
info = SVN.CaptureLocalInfo([], parent)
if (info['Repository Root'] != cur_dir_repo_root or
info['URL'] != os.path.dirname(url)):
break
url = info['URL']
except subprocess2.CalledProcessError:
break
directory = parent
return GetCasedPath(directory)
cwd = parent
return GetCasedPath(cwd)
@classmethod
def AssertVersion(cls, min_version):
"""Asserts svn's version is at least min_version."""
if cls.current_version is None:
cls.current_version = cls.Capture(['--version']).split()[2]
cls.current_version = cls.Capture(['--version'], None).split()[2]
current_version_list = map(only_int, cls.current_version.split('.'))
for min_ver in map(int, min_version.split('.')):
ver = current_version_list.pop(0)
......@@ -944,16 +960,16 @@ class SVN(object):
return (True, cls.current_version)
@staticmethod
def Revert(repo_root, callback=None, ignore_externals=False):
"""Reverts all svn modifications in repo_root, including properties.
def Revert(cwd, callback=None, ignore_externals=False):
"""Reverts all svn modifications in cwd, including properties.
Deletes any modified files or directory.
A "svn update --revision BASE" call is required after to revive deleted
files.
"""
for file_status in SVN.CaptureStatus(repo_root):
file_path = os.path.join(repo_root, file_status[1])
for file_status in SVN.CaptureStatus(None, cwd):
file_path = os.path.join(cwd, file_status[1])
if (ignore_externals and
file_status[0][0] == 'X' and
file_status[0][1:].isspace()):
......@@ -985,11 +1001,11 @@ class SVN(object):
not file_status[0][1:].isspace()):
# Added, deleted file requires manual intervention and require calling
# revert, like for properties.
if not os.path.isdir(repo_root):
if not os.path.isdir(cwd):
# '.' was deleted. It's not worth continuing.
return
try:
SVN.Capture(['revert', file_status[1]], cwd=repo_root)
SVN.Capture(['revert', file_status[1]], cwd=cwd)
except subprocess2.CalledProcessError:
if not os.path.exists(file_path):
continue
......
......@@ -63,7 +63,7 @@ def commit_svn(repo, usr, pwd):
"""Commits the changes and returns the new revision number."""
to_add = []
to_remove = []
for status, filepath in scm.SVN.CaptureStatus(repo):
for status, filepath in scm.SVN.CaptureStatus(None, repo):
if status[0] == '?':
to_add.append(filepath)
elif status[0] == '!':
......
......@@ -24,7 +24,7 @@ class GclTestsBase(SuperMoxTestBase):
SuperMoxTestBase.setUp(self)
self.fake_root_dir = self.RootDir()
self.mox.StubOutWithMock(gcl, 'RunShell')
self.mox.StubOutWithMock(gcl.SVN, 'CaptureInfo')
self.mox.StubOutWithMock(gcl.SVN, '_CaptureInfo')
self.mox.StubOutWithMock(gcl.SVN, 'GetCheckoutRoot')
self.mox.StubOutWithMock(gcl, 'tempfile')
self.mox.StubOutWithMock(gcl.upload, 'RealMain')
......
......@@ -31,6 +31,10 @@ import subprocess2
join = gclient_scm.os.path.join
# Access to a protected member XXX of a client class
# pylint: disable=W0212
class GCBaseTestCase(object):
def assertRaisesError(self, msg, fn, *args, **kwargs):
"""Like unittest's assertRaises() but checks for Gclient.Error."""
......@@ -52,9 +56,8 @@ class BaseTestCase(GCBaseTestCase, SuperMoxTestBase):
self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'FileRead')
self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'FileWrite')
self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'RemoveDirectory')
self._CaptureSVNInfo = gclient_scm.scm.SVN.CaptureInfo
self.mox.StubOutWithMock(gclient_scm.scm.SVN, 'Capture')
self.mox.StubOutWithMock(gclient_scm.scm.SVN, 'CaptureInfo')
self.mox.StubOutWithMock(gclient_scm.scm.SVN, '_CaptureInfo')
self.mox.StubOutWithMock(gclient_scm.scm.SVN, 'CaptureStatus')
self.mox.StubOutWithMock(gclient_scm.scm.SVN, 'RunAndGetFileList')
self.mox.StubOutWithMock(subprocess2, 'communicate')
......@@ -156,7 +159,7 @@ class SVNWrapperTestCase(BaseTestCase):
options = self.Options(verbose=True)
gclient_scm.os.path.isdir(self.base_path).AndReturn(False)
gclient_scm.os.path.exists(self.base_path).AndReturn(False)
gclient_scm.scm.SVN.Capture(['--version']
gclient_scm.scm.SVN.Capture(['--version'], None
).AndReturn('svn, version 1.5.1 (r32289)')
# It'll to a checkout instead.
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
......@@ -197,7 +200,8 @@ class SVNWrapperTestCase(BaseTestCase):
gclient_scm.os.makedirs(parent)
gclient_scm.os.path.exists(parent).AndReturn(True)
files_list = self.mox.CreateMockAnything()
gclient_scm.scm.SVN.Capture(['--version']).AndReturn('svn, version 1.6')
gclient_scm.scm.SVN.Capture(['--version'], None
).AndReturn('svn, version 1.6')
gclient_scm.scm.SVN.RunAndGetFileList(
options.verbose,
['checkout', self.url, self.base_path, '--force', '--ignore-externals'],
......@@ -216,7 +220,7 @@ class SVNWrapperTestCase(BaseTestCase):
options = self.Options(verbose=True)
gclient_scm.os.path.isdir(self.base_path).AndReturn(True)
gclient_scm.os.path.isdir(join(self.base_path, '.svn')).AndReturn(True)
gclient_scm.scm.SVN.CaptureStatus(self.base_path).AndReturn([])
gclient_scm.scm.SVN.CaptureStatus(None, self.base_path).AndReturn([])
gclient_scm.os.path.isdir(self.base_path).AndReturn(True)
gclient_scm.scm.SVN.RunAndGetFileList(
options.verbose,
......@@ -237,7 +241,7 @@ class SVNWrapperTestCase(BaseTestCase):
items = [
('~ ', 'a'),
]
gclient_scm.scm.SVN.CaptureStatus(self.base_path).AndReturn(items)
gclient_scm.scm.SVN.CaptureStatus(None, self.base_path).AndReturn(items)
file_path = join(self.base_path, 'a')
gclient_scm.os.path.exists(file_path).AndReturn(True)
gclient_scm.os.path.isfile(file_path).AndReturn(False)
......@@ -266,7 +270,7 @@ class SVNWrapperTestCase(BaseTestCase):
items = [
('~ ', '.'),
]
gclient_scm.scm.SVN.CaptureStatus(self.base_path).AndReturn(items)
gclient_scm.scm.SVN.CaptureStatus(None, self.base_path).AndReturn(items)
file_path = join(self.base_path, '.')
gclient_scm.os.path.exists(file_path).AndReturn(True)
gclient_scm.os.path.isfile(file_path).AndReturn(False)
......@@ -317,7 +321,7 @@ class SVNWrapperTestCase(BaseTestCase):
gclient_scm.os.makedirs(parent)
gclient_scm.os.path.exists(parent).AndReturn(True)
files_list = self.mox.CreateMockAnything()
gclient_scm.scm.SVN.Capture(['--version']
gclient_scm.scm.SVN.Capture(['--version'], None
).AndReturn('svn, version 1.5.1 (r32289)')
gclient_scm.scm.SVN.RunAndGetFileList(
options.verbose,
......@@ -344,17 +348,18 @@ class SVNWrapperTestCase(BaseTestCase):
# Verify no locked files.
dotted_path = join(self.base_path, '.')
gclient_scm.scm.SVN.CaptureStatus(dotted_path).AndReturn([])
gclient_scm.scm.SVN.CaptureStatus(None, dotted_path).AndReturn([])
# Checkout or update.
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
gclient_scm.scm.SVN.CaptureInfo(dotted_path).AndReturn(file_info)
gclient_scm.scm.SVN._CaptureInfo([], dotted_path).AndReturn(file_info)
# Cheat a bit here.
gclient_scm.scm.SVN.CaptureInfo(file_info['URL']).AndReturn(file_info)
gclient_scm.scm.SVN._CaptureInfo([file_info['URL']], None
).AndReturn(file_info)
additional_args = []
if options.manually_grab_svn_rev:
additional_args = ['--revision', str(file_info['Revision'])]
gclient_scm.scm.SVN.Capture(['--version']
gclient_scm.scm.SVN.Capture(['--version'], None
).AndReturn('svn, version 1.5.1 (r32289)')
additional_args.extend(['--force', '--ignore-externals'])
files_list = []
......@@ -377,14 +382,14 @@ class SVNWrapperTestCase(BaseTestCase):
# Checks to make sure that we support svn co --depth.
gclient_scm.scm.SVN.current_version = None
gclient_scm.scm.SVN.Capture(['--version']
gclient_scm.scm.SVN.Capture(['--version'], None
).AndReturn('svn, version 1.5.1 (r32289)')
gclient_scm.os.path.exists(join(self.base_path, '.svn')).AndReturn(False)
gclient_scm.os.path.exists(join(self.base_path, 'DEPS')).AndReturn(False)
# Verify no locked files.
dotted_path = join(self.base_path, '.')
gclient_scm.scm.SVN.CaptureStatus(dotted_path).AndReturn([])
gclient_scm.scm.SVN.CaptureStatus(None, dotted_path).AndReturn([])
# When checking out a single file, we issue an svn checkout and svn update.
files_list = self.mox.CreateMockAnything()
......@@ -402,8 +407,9 @@ class SVNWrapperTestCase(BaseTestCase):
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
gclient_scm.scm.SVN.CaptureInfo(dotted_path).AndReturn(file_info)
gclient_scm.scm.SVN.CaptureInfo(file_info['URL']).AndReturn(file_info)
gclient_scm.scm.SVN._CaptureInfo([], dotted_path).AndReturn(file_info)
gclient_scm.scm.SVN._CaptureInfo([file_info['URL']], None
).AndReturn(file_info)
self.mox.ReplayAll()
scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
......@@ -416,7 +422,7 @@ class SVNWrapperTestCase(BaseTestCase):
# Checks to make sure that we support svn co --depth.
gclient_scm.scm.SVN.current_version = None
gclient_scm.scm.SVN.Capture(['--version']
gclient_scm.scm.SVN.Capture(['--version'], None
).AndReturn('svn, version 1.4.4 (r25188)')
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
......@@ -440,7 +446,7 @@ class SVNWrapperTestCase(BaseTestCase):
# Checks to make sure that we support svn co --depth.
gclient_scm.scm.SVN.current_version = None
gclient_scm.scm.SVN.Capture(['--version']
gclient_scm.scm.SVN.Capture(['--version'], None
).AndReturn('svn, version 1.5.1 (r32289)')
gclient_scm.os.path.exists(join(self.base_path, '.svn')).AndReturn(False)
# If DEPS already exists, assume we're upgrading from svn1.4, so delete
......@@ -449,7 +455,8 @@ class SVNWrapperTestCase(BaseTestCase):
gclient_scm.os.remove(join(self.base_path, 'DEPS'))
# Verify no locked files.
gclient_scm.scm.SVN.CaptureStatus(join(self.base_path, '.')).AndReturn([])
gclient_scm.scm.SVN.CaptureStatus(
None, join(self.base_path, '.')).AndReturn([])
# When checking out a single file, we issue an svn checkout and svn update.
files_list = self.mox.CreateMockAnything()
......@@ -467,9 +474,10 @@ class SVNWrapperTestCase(BaseTestCase):
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
gclient_scm.scm.SVN.CaptureInfo(
join(self.base_path, ".")).AndReturn(file_info)
gclient_scm.scm.SVN.CaptureInfo(file_info['URL']).AndReturn(file_info)
gclient_scm.scm.SVN._CaptureInfo(
[], join(self.base_path, ".")).AndReturn(file_info)
gclient_scm.scm.SVN._CaptureInfo([file_info['URL']], None
).AndReturn(file_info)
self.mox.ReplayAll()
scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
......@@ -486,21 +494,23 @@ class SVNWrapperTestCase(BaseTestCase):
}
# Checks to make sure that we support svn co --depth.
gclient_scm.scm.SVN.current_version = None
gclient_scm.scm.SVN.Capture(['--version']
gclient_scm.scm.SVN.Capture(['--version'], None
).AndReturn('svn, version 1.5.1 (r32289)')
gclient_scm.os.path.exists(join(self.base_path, '.svn')).AndReturn(True)
# Verify no locked files.
gclient_scm.scm.SVN.CaptureStatus(join(self.base_path, '.')).AndReturn([])
gclient_scm.scm.SVN.CaptureStatus(None, join(self.base_path, '.')
).AndReturn([])
# Now we fall back on scm.update().
files_list = self.mox.CreateMockAnything()
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
gclient_scm.scm.SVN.CaptureInfo(
join(self.base_path, '.')).AndReturn(file_info)
gclient_scm.scm.SVN.CaptureInfo(file_info['URL']).AndReturn(file_info)
gclient_scm.scm.SVN._CaptureInfo(
[], join(self.base_path, '.')).AndReturn(file_info)
gclient_scm.scm.SVN._CaptureInfo([file_info['URL']], None
).AndReturn(file_info)
self.mox.ReplayAll()
scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
......@@ -872,7 +882,6 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase):
relpath=self.relpath)
file_path = join(self.base_path, 'b')
open(file_path, 'w').writelines('conflict\n')
# pylint: disable=W0212
scm._Run(['commit', '-am', 'test'], options)
__builtin__.raw_input = lambda x: 'y'
exception = ('Conflict while rebasing this branch.\n'
......
......@@ -25,6 +25,10 @@ import rietveld
presubmit_canned_checks = presubmit.presubmit_canned_checks
# Access to a protected member XXX of a client class
# pylint: disable=W0212
class PresubmitTestsBase(SuperMoxTestBase):
"""Setups and tear downs the mocks but doesn't test anything as-is."""
presubmit_text = """
......@@ -112,18 +116,19 @@ def GetPreferredTrySlaves(project):
"""
def setUp(self):
SuperMoxTestBase.setUp(self)
class FakeChange(object):
root = '/'
def __init__(self, obj):
self._root = obj.fake_root_dir
def RepositoryRoot(self):
return self.root
return self._root
SuperMoxTestBase.setUp(self)
self.fake_change = FakeChange()
self.mox.StubOutWithMock(presubmit, 'random')
self.mox.StubOutWithMock(presubmit, 'warn')
presubmit._ASKED_FOR_FEEDBACK = False
self.fake_root_dir = self.RootDir()
self.fake_change = FakeChange(self)
# Special mocks.
def MockAbsPath(f):
return f
......@@ -134,7 +139,7 @@ def GetPreferredTrySlaves(project):
presubmit.os.getcwd = self.RootDir
presubmit.os.chdir = MockChdir
self.mox.StubOutWithMock(presubmit.scm, 'determine_scm')
self.mox.StubOutWithMock(presubmit.scm.SVN, 'CaptureInfo')
self.mox.StubOutWithMock(presubmit.scm.SVN, '_CaptureInfo')
self.mox.StubOutWithMock(presubmit.scm.SVN, 'GetFileProperty')
self.mox.StubOutWithMock(presubmit.gclient_utils, 'FileRead')
self.mox.StubOutWithMock(presubmit.gclient_utils, 'FileWrite')
......@@ -253,37 +258,45 @@ class PresubmitUnittest(PresubmitTestsBase):
['?', 'flop/notfound.txt'], # not found in SVN, still exists locally
['D', 'boo/flap.h'],
]
blat = presubmit.os.path.join(self.fake_root_dir, 'foo', 'blat.cc')
notfound = presubmit.os.path.join(
self.fake_root_dir, 'flop', 'notfound.txt')
flap = presubmit.os.path.join(self.fake_root_dir, 'boo', 'flap.h')
binary = presubmit.os.path.join(self.fake_root_dir, 'binary.dll')
isdir = presubmit.os.path.join(self.fake_root_dir, 'isdir')
presubmit.os.path.exists(blat).AndReturn(True)
presubmit.os.path.isdir(blat).AndReturn(False)
presubmit.os.path.exists(binary).AndReturn(True)
presubmit.os.path.isdir(binary).AndReturn(False)
presubmit.os.path.exists(isdir).AndReturn(True)
presubmit.os.path.isdir(isdir).AndReturn(True)
presubmit.os.path.exists(notfound).AndReturn(True)
presubmit.os.path.isdir(notfound).AndReturn(False)
presubmit.os.path.exists(flap).AndReturn(False)
presubmit.scm.SVN.CaptureInfo(flap
blat = presubmit.os.path.join('foo', 'blat.cc')
notfound = presubmit.os.path.join('flop', 'notfound.txt')
flap = presubmit.os.path.join('boo', 'flap.h')
binary = 'binary.dll'
isdir = 'isdir'
f_blat = presubmit.os.path.join(self.fake_root_dir, blat)
f_notfound = presubmit.os.path.join(self.fake_root_dir, notfound)
f_flap = presubmit.os.path.join(self.fake_root_dir, flap)
f_binary = presubmit.os.path.join(self.fake_root_dir, binary)
f_isdir = presubmit.os.path.join(self.fake_root_dir, isdir)
presubmit.os.path.exists(f_blat).AndReturn(True)
presubmit.os.path.isdir(f_blat).AndReturn(False)
presubmit.os.path.exists(f_binary).AndReturn(True)
presubmit.os.path.isdir(f_binary).AndReturn(False)
presubmit.os.path.exists(f_isdir).AndReturn(True)
presubmit.os.path.isdir(f_isdir).AndReturn(True)
presubmit.os.path.exists(f_notfound).AndReturn(True)
presubmit.os.path.isdir(f_notfound).AndReturn(False)
presubmit.os.path.exists(f_flap).AndReturn(False)
presubmit.scm.SVN._CaptureInfo([flap], self.fake_root_dir
).AndReturn({'Node Kind': 'file'})
presubmit.scm.SVN.GetFileProperty(blat, 'svn:mime-type').AndReturn(None)
presubmit.scm.SVN.GetFileProperty(
binary, 'svn:mime-type').AndReturn('application/octet-stream')
blat, 'svn:mime-type', self.fake_root_dir).AndReturn(None)
presubmit.scm.SVN.GetFileProperty(
binary, 'svn:mime-type', self.fake_root_dir
).AndReturn('application/octet-stream')
presubmit.scm.SVN.GetFileProperty(
notfound, 'svn:mime-type').AndReturn('')
presubmit.scm.SVN.CaptureInfo(blat).AndReturn(
notfound, 'svn:mime-type', self.fake_root_dir).AndReturn('')
presubmit.scm.SVN._CaptureInfo([blat], self.fake_root_dir).AndReturn(
{'URL': 'svn:/foo/foo/blat.cc'})
presubmit.scm.SVN.CaptureInfo(binary).AndReturn(
presubmit.scm.SVN._CaptureInfo([binary], self.fake_root_dir).AndReturn(
{'URL': 'svn:/foo/binary.dll'})
presubmit.scm.SVN.CaptureInfo(notfound).AndReturn({})
presubmit.scm.SVN.CaptureInfo(flap).AndReturn(
presubmit.scm.SVN._CaptureInfo([notfound], self.fake_root_dir).AndReturn({})
presubmit.scm.SVN._CaptureInfo([flap], self.fake_root_dir).AndReturn(
{'URL': 'svn:/foo/boo/flap.h'})
presubmit.scm.SVN.GenerateDiff([blat]).AndReturn(self.presubmit_diffs)
presubmit.scm.SVN.GenerateDiff([notfound]).AndReturn(self.presubmit_diffs)
presubmit.scm.SVN.GenerateDiff([blat], self.fake_root_dir, False, None
).AndReturn(self.presubmit_diffs)
presubmit.scm.SVN.GenerateDiff([notfound], self.fake_root_dir, False, None
).AndReturn(self.presubmit_diffs)
self.mox.ReplayAll()
......@@ -846,9 +859,11 @@ class InputApiUnittest(PresubmitTestsBase):
members)
def testDepotToLocalPath(self):
presubmit.scm.SVN.CaptureInfo('svn://foo/smurf').AndReturn(
{'Path': 'prout'})
presubmit.scm.SVN.CaptureInfo('svn:/foo/notfound/burp').AndReturn({})
presubmit.scm.SVN._CaptureInfo(['svn://foo/smurf'], self.fake_root_dir
).AndReturn({'Path': 'prout'})
presubmit.scm.SVN._CaptureInfo(
['svn:/foo/notfound/burp'], self.fake_root_dir
).AndReturn({})
self.mox.ReplayAll()
path = presubmit.InputApi(
......@@ -861,8 +876,10 @@ class InputApiUnittest(PresubmitTestsBase):
self.failUnless(path == None)
def testLocalToDepotPath(self):
presubmit.scm.SVN.CaptureInfo('smurf').AndReturn({'URL': 'svn://foo'})
presubmit.scm.SVN.CaptureInfo('notfound-food').AndReturn({})
presubmit.scm.SVN._CaptureInfo(['smurf'], self.fake_root_dir
).AndReturn({'URL': 'svn://foo'})
presubmit.scm.SVN._CaptureInfo(['notfound-food'], self.fake_root_dir
).AndReturn({})
self.mox.ReplayAll()
path = presubmit.InputApi(
self.fake_change, './p', False, None, False).LocalToDepotPath(
......@@ -917,18 +934,34 @@ class InputApiUnittest(PresubmitTestsBase):
presubmit.os.path.exists(notfound).AndReturn(False)
presubmit.os.path.exists(flap).AndReturn(True)
presubmit.os.path.isdir(flap).AndReturn(False)
presubmit.scm.SVN.CaptureInfo(beingdeleted).AndReturn({})
presubmit.scm.SVN.CaptureInfo(notfound).AndReturn({})
presubmit.scm.SVN.GetFileProperty(blat, 'svn:mime-type').AndReturn(None)
presubmit.scm.SVN.GetFileProperty(readme, 'svn:mime-type').AndReturn(None)
presubmit.scm.SVN.GetFileProperty(binary, 'svn:mime-type').AndReturn(
'application/octet-stream')
presubmit.scm.SVN.GetFileProperty(weird, 'svn:mime-type').AndReturn(None)
presubmit.scm.SVN.GetFileProperty(another, 'svn:mime-type').AndReturn(None)
presubmit.scm.SVN.GetFileProperty(third_party, 'svn:mime-type'
presubmit.scm.SVN._CaptureInfo(
[files[6][1]], self.fake_root_dir).AndReturn({})
presubmit.scm.SVN._CaptureInfo(
[files[7][1]], self.fake_root_dir).AndReturn({})
presubmit.scm.SVN.GetFileProperty(
files[0][1], 'svn:mime-type', self.fake_root_dir
).AndReturn(None)
presubmit.scm.SVN.GetFileProperty(
files[1][1], 'svn:mime-type', self.fake_root_dir
).AndReturn(None)
presubmit.scm.SVN.GetFileProperty(
files[2][1], 'svn:mime-type', self.fake_root_dir
).AndReturn('application/octet-stream')
presubmit.scm.SVN.GetFileProperty(
files[3][1], 'svn:mime-type', self.fake_root_dir
).AndReturn(None)
presubmit.scm.SVN.GetFileProperty(
files[4][1], 'svn:mime-type', self.fake_root_dir
).AndReturn(None)
presubmit.scm.SVN.GetFileProperty(
files[5][1], 'svn:mime-type', self.fake_root_dir
).AndReturn(None)
presubmit.scm.SVN.GenerateDiff([blat]).AndReturn(self.presubmit_diffs)
presubmit.scm.SVN.GenerateDiff([another]).AndReturn(self.presubmit_diffs)
presubmit.scm.SVN.GenerateDiff(
[files[0][1]], self.fake_root_dir, False, None
).AndReturn(self.presubmit_diffs)
presubmit.scm.SVN.GenerateDiff(
[files[4][1]], self.fake_root_dir, False, None
).AndReturn(self.presubmit_diffs)
self.mox.ReplayAll()
......@@ -970,7 +1003,7 @@ class InputApiUnittest(PresubmitTestsBase):
def testDefaultWhiteListBlackListFilters(self):
def f(x):
return presubmit.AffectedFile(x, 'M')
return presubmit.AffectedFile(x, 'M', self.fake_root_dir)
files = [
(
[
......@@ -1051,10 +1084,11 @@ class InputApiUnittest(PresubmitTestsBase):
return 'a' in affected_file.LocalPath()
files = [('A', 'eeaee'), ('M', 'eeabee'), ('M', 'eebcee')]
for _, item in files:
item = presubmit.os.path.join(self.fake_root_dir, item)
presubmit.os.path.exists(item).AndReturn(True)
presubmit.os.path.isdir(item).AndReturn(False)
presubmit.scm.SVN.GetFileProperty(item, 'svn:mime-type').AndReturn(None)
full_item = presubmit.os.path.join(self.fake_root_dir, item)
presubmit.os.path.exists(full_item).AndReturn(True)
presubmit.os.path.isdir(full_item).AndReturn(False)
presubmit.scm.SVN.GetFileProperty(
item, 'svn:mime-type', self.fake_root_dir).AndReturn(None)
self.mox.ReplayAll()
change = presubmit.SvnChange(
......@@ -1073,10 +1107,11 @@ class InputApiUnittest(PresubmitTestsBase):
black_list = [r".*?b.*?"]
files = [('A', 'eeaee'), ('M', 'eeabee'), ('M', 'eebcee'), ('M', 'eecaee')]
for _, item in files:
item = presubmit.os.path.join(self.fake_root_dir, item)
presubmit.os.path.exists(item).AndReturn(True)
presubmit.os.path.isdir(item).AndReturn(False)
presubmit.scm.SVN.GetFileProperty(item, 'svn:mime-type').AndReturn(None)
full_item = presubmit.os.path.join(self.fake_root_dir, item)
presubmit.os.path.exists(full_item).AndReturn(True)
presubmit.os.path.isdir(full_item).AndReturn(False)
presubmit.scm.SVN.GetFileProperty(
item, 'svn:mime-type', self.fake_root_dir).AndReturn(None)
self.mox.ReplayAll()
change = presubmit.SvnChange(
......@@ -1268,36 +1303,42 @@ class AffectedFileUnittest(PresubmitTestsBase):
'OldFileTempPath', 'Property', 'ServerPath',
]
# If this test fails, you should add the relevant test.
self.compareMembers(presubmit.AffectedFile('a', 'b'), members)
self.compareMembers(presubmit.SvnAffectedFile('a', 'b'), members)
self.compareMembers(
presubmit.AffectedFile('a', 'b', self.fake_root_dir), members)
self.compareMembers(
presubmit.SvnAffectedFile('a', 'b', self.fake_root_dir), members)
def testAffectedFile(self):
path = presubmit.os.path.join('foo', 'blat.cc')
presubmit.os.path.exists(path).AndReturn(True)
presubmit.os.path.isdir(path).AndReturn(False)
presubmit.gclient_utils.FileRead(path, 'rU').AndReturn('whatever\ncookie')
presubmit.scm.SVN.CaptureInfo(path).AndReturn(
f_path = presubmit.os.path.join(self.fake_root_dir, path)
presubmit.os.path.exists(f_path).AndReturn(True)
presubmit.os.path.isdir(f_path).AndReturn(False)
presubmit.gclient_utils.FileRead(f_path, 'rU').AndReturn('whatever\ncookie')
presubmit.scm.SVN._CaptureInfo([path], self.fake_root_dir).AndReturn(
{'URL': 'svn:/foo/foo/blat.cc'})
self.mox.ReplayAll()
af = presubmit.SvnAffectedFile('foo/blat.cc', 'M')
af = presubmit.SvnAffectedFile('foo/blat.cc', 'M', self.fake_root_dir)
self.assertEquals('svn:/foo/foo/blat.cc', af.ServerPath())
self.assertEquals(presubmit.normpath('foo/blat.cc'), af.LocalPath())
self.assertEquals('M', af.Action())
self.assertEquals(['whatever', 'cookie'], af.NewContents())
def testAffectedFileNotExists(self):
presubmit.os.path.exists('notfound.cc').AndReturn(False)
presubmit.gclient_utils.FileRead('notfound.cc', 'rU').AndRaise(IOError)
notfound = 'notfound.cc'
f_notfound = presubmit.os.path.join(self.fake_root_dir, notfound)
presubmit.os.path.exists(f_notfound).AndReturn(False)
presubmit.gclient_utils.FileRead(f_notfound, 'rU').AndRaise(IOError)
self.mox.ReplayAll()
af = presubmit.AffectedFile('notfound.cc', 'A')
af = presubmit.AffectedFile(notfound, 'A', self.fake_root_dir)
self.assertEquals('', af.ServerPath())
self.assertEquals([], af.NewContents())
def testProperty(self):
presubmit.scm.SVN.GetFileProperty('foo.cc', 'svn:secret-property'
presubmit.scm.SVN.GetFileProperty(
'foo.cc', 'svn:secret-property', self.fake_root_dir
).AndReturn('secret-property-value')
self.mox.ReplayAll()
affected_file = presubmit.SvnAffectedFile('foo.cc', 'A')
affected_file = presubmit.SvnAffectedFile('foo.cc', 'A', self.fake_root_dir)
# Verify cache coherency.
self.assertEquals('secret-property-value',
affected_file.Property('svn:secret-property'))
......@@ -1305,35 +1346,44 @@ class AffectedFileUnittest(PresubmitTestsBase):
affected_file.Property('svn:secret-property'))
def testIsDirectoryNotExists(self):
presubmit.os.path.exists('foo.cc').AndReturn(False)
presubmit.scm.SVN.CaptureInfo('foo.cc').AndReturn({})
filename = 'foo.cc'
f_filename = presubmit.os.path.join(self.fake_root_dir, filename)
presubmit.os.path.exists(f_filename).AndReturn(False)
presubmit.scm.SVN._CaptureInfo([filename], self.fake_root_dir).AndReturn({})
self.mox.ReplayAll()
affected_file = presubmit.SvnAffectedFile('foo.cc', 'A')
affected_file = presubmit.SvnAffectedFile(filename, 'A', self.fake_root_dir)
# Verify cache coherency.
self.failIf(affected_file.IsDirectory())
self.failIf(affected_file.IsDirectory())
def testIsDirectory(self):
presubmit.os.path.exists('foo.cc').AndReturn(True)
presubmit.os.path.isdir('foo.cc').AndReturn(True)
filename = 'foo.cc'
f_filename = presubmit.os.path.join(self.fake_root_dir, filename)
presubmit.os.path.exists(f_filename).AndReturn(True)
presubmit.os.path.isdir(f_filename).AndReturn(True)
self.mox.ReplayAll()
affected_file = presubmit.SvnAffectedFile('foo.cc', 'A')
affected_file = presubmit.SvnAffectedFile(filename, 'A', self.fake_root_dir)
# Verify cache coherency.
self.failUnless(affected_file.IsDirectory())
self.failUnless(affected_file.IsDirectory())
def testIsTextFile(self):
files = [presubmit.SvnAffectedFile('foo/blat.txt', 'M'),
presubmit.SvnAffectedFile('foo/binary.blob', 'M'),
presubmit.SvnAffectedFile('blat/flop.txt', 'D')]
files = [
presubmit.SvnAffectedFile('foo/blat.txt', 'M', self.fake_root_dir),
presubmit.SvnAffectedFile('foo/binary.blob', 'M', self.fake_root_dir),
presubmit.SvnAffectedFile('blat/flop.txt', 'D', self.fake_root_dir)
]
blat = presubmit.os.path.join('foo', 'blat.txt')
blob = presubmit.os.path.join('foo', 'binary.blob')
presubmit.os.path.exists(blat).AndReturn(True)
presubmit.os.path.isdir(blat).AndReturn(False)
presubmit.os.path.exists(blob).AndReturn(True)
presubmit.os.path.isdir(blob).AndReturn(False)
presubmit.scm.SVN.GetFileProperty(blat, 'svn:mime-type').AndReturn(None)
presubmit.scm.SVN.GetFileProperty(blob, 'svn:mime-type'
f_blat = presubmit.os.path.join(self.fake_root_dir, blat)
f_blob = presubmit.os.path.join(self.fake_root_dir, blob)
presubmit.os.path.exists(f_blat).AndReturn(True)
presubmit.os.path.isdir(f_blat).AndReturn(False)
presubmit.os.path.exists(f_blob).AndReturn(True)
presubmit.os.path.isdir(f_blob).AndReturn(False)
presubmit.scm.SVN.GetFileProperty(blat, 'svn:mime-type', self.fake_root_dir
).AndReturn(None)
presubmit.scm.SVN.GetFileProperty(blob, 'svn:mime-type', self.fake_root_dir
).AndReturn('application/octet-stream')
self.mox.ReplayAll()
......@@ -1530,33 +1580,37 @@ class CannedChecksUnittest(PresubmitTestsBase):
'mychange', '', self.fake_root_dir, [], 0, 0, None)
input_api1 = self.MockInputApi(change1, committing)
files1 = [
presubmit.SvnAffectedFile('foo/bar.cc', 'A'),
presubmit.SvnAffectedFile('foo.cc', 'M'),
presubmit.SvnAffectedFile('foo/bar.cc', 'A', self.fake_root_dir),
presubmit.SvnAffectedFile('foo.cc', 'M', self.fake_root_dir),
]
if use_source_file:
input_api1.AffectedSourceFiles(None).AndReturn(files1)
else:
input_api1.AffectedFiles(include_deleted=False).AndReturn(files1)
presubmit.scm.SVN.GetFileProperty(presubmit.normpath('foo/bar.cc'),
property_name).AndReturn(value1)
presubmit.scm.SVN.GetFileProperty(presubmit.normpath('foo.cc'),
property_name).AndReturn(value1)
presubmit.scm.SVN.GetFileProperty(
presubmit.normpath('foo/bar.cc'), property_name, self.fake_root_dir
).AndReturn(value1)
presubmit.scm.SVN.GetFileProperty(
presubmit.normpath('foo.cc'), property_name, self.fake_root_dir
).AndReturn(value1)
change2 = presubmit.SvnChange(
'mychange', '', self.fake_root_dir, [], 0, 0, None)
input_api2 = self.MockInputApi(change2, committing)
files2 = [
presubmit.SvnAffectedFile('foo/bar.cc', 'A'),
presubmit.SvnAffectedFile('foo.cc', 'M'),
presubmit.SvnAffectedFile('foo/bar.cc', 'A', self.fake_root_dir),
presubmit.SvnAffectedFile('foo.cc', 'M', self.fake_root_dir),
]
if use_source_file:
input_api2.AffectedSourceFiles(None).AndReturn(files2)
else:
input_api2.AffectedFiles(include_deleted=False).AndReturn(files2)
presubmit.scm.SVN.GetFileProperty(presubmit.normpath('foo/bar.cc'),
property_name).AndReturn(value2)
presubmit.scm.SVN.GetFileProperty(presubmit.normpath('foo.cc'),
property_name).AndReturn(value2)
presubmit.scm.SVN.GetFileProperty(
presubmit.normpath('foo/bar.cc'), property_name, self.fake_root_dir
).AndReturn(value2)
presubmit.scm.SVN.GetFileProperty(
presubmit.normpath('foo.cc'), property_name, self.fake_root_dir
).AndReturn(value2)
self.mox.ReplayAll()
results1 = check(input_api1, presubmit.OutputApi, None)
......@@ -1685,7 +1739,6 @@ class CannedChecksUnittest(PresubmitTestsBase):
self.assertEquals(len(results1), 1)
self.assertEquals(results1[0].__class__,
presubmit.OutputApi.PresubmitPromptWarning)
# pylint: disable=W0212
self.assertEquals(results1[0]._long_text,
'makefile.foo, line 46')
......@@ -1836,7 +1889,7 @@ class CannedChecksUnittest(PresubmitTestsBase):
self.mox.StubOutWithMock(presubmit_canned_checks, 'CheckSvnProperty')
input_api = self.MockInputApi(None, False)
output_api = presubmit.OutputApi()
A = lambda x: presubmit.AffectedFile(x, 'M')
A = lambda x: presubmit.AffectedFile(x, 'M', self.fake_root_dir)
files = [
A('a.pdf'), A('b.bmp'), A('c.gif'), A('d.png'), A('e.jpg'), A('f.jpe'),
A('random'), A('g.jpeg'), A('h.ico'),
......@@ -1975,7 +2028,6 @@ class CannedChecksUnittest(PresubmitTestsBase):
self.assertEquals(len(results), 1)
self.assertEquals(results[0].__class__,
presubmit.OutputApi.PresubmitNotifyResult)
# pylint: disable=W0212
self.assertEquals('test_module failed!\nfoo', results[0]._message)
def testRunPythonUnitTestsFailureCommitting(self):
......@@ -1990,7 +2042,6 @@ class CannedChecksUnittest(PresubmitTestsBase):
input_api, presubmit.OutputApi, ['test_module'])
self.assertEquals(len(results), 1)
self.assertEquals(results[0].__class__, presubmit.OutputApi.PresubmitError)
# pylint: disable=W0212
self.assertEquals('test_module failed!\nfoo', results[0]._message)
def testRunPythonUnitTestsSuccess(self):
......@@ -2231,7 +2282,6 @@ class CannedChecksUnittest(PresubmitTestsBase):
project_name=None,
owners_check=True)
self.assertEqual(1, len(results))
# pylint: disable=W0212
self.assertEqual(
'Found line ending with white spaces in:', results[0]._message)
self.checkstdout('')
......
......@@ -20,6 +20,10 @@ import scm
import subprocess2
# Access to a protected member XXX of a client class
# pylint: disable=W0212
class BaseTestCase(SuperMoxTestBase):
# Like unittest's assertRaises, but checks for Gclient.Error.
def assertRaisesError(self, msg, fn, *args, **kwargs):
......@@ -94,7 +98,8 @@ class SVNTestCase(BaseSCMTestCase):
def testMembersChanged(self):
self.mox.ReplayAll()
members = [
'AssertVersion', 'Capture', 'CaptureRevision', 'CaptureInfo',
'AssertVersion', 'Capture', 'CaptureRevision', 'CaptureLocalInfo',
'CaptureRemoteInfo',
'CaptureStatus', 'current_version', 'DiffItem', 'GenerateDiff',
'GetCheckoutRoot', 'GetEmail', 'GetFileProperty', 'IsMoved',
'IsMovedInfo', 'ReadSimpleAuth', 'Revert', 'RunAndGetFileList',
......@@ -104,19 +109,19 @@ class SVNTestCase(BaseSCMTestCase):
def testGetCheckoutRoot(self):
# pylint: disable=E1103
self.mox.StubOutWithMock(scm.SVN, 'CaptureInfo')
self.mox.StubOutWithMock(scm.SVN, '_CaptureInfo')
self.mox.StubOutWithMock(scm, 'GetCasedPath')
scm.os.path.abspath = lambda x: x
scm.GetCasedPath = lambda x: x
scm.SVN.CaptureInfo(self.root_dir + '/foo/bar').AndReturn({
scm.SVN._CaptureInfo([], self.root_dir + '/foo/bar').AndReturn({
'Repository Root': 'svn://svn.chromium.org/chrome',
'URL': 'svn://svn.chromium.org/chrome/trunk/src',
})
scm.SVN.CaptureInfo(self.root_dir + '/foo').AndReturn({
scm.SVN._CaptureInfo([], self.root_dir + '/foo').AndReturn({
'Repository Root': 'svn://svn.chromium.org/chrome',
'URL': 'svn://svn.chromium.org/chrome/trunk',
})
scm.SVN.CaptureInfo(self.root_dir).AndReturn({
scm.SVN._CaptureInfo([], self.root_dir).AndReturn({
'Repository Root': 'svn://svn.chromium.org/chrome',
'URL': 'svn://svn.chromium.org/chrome/trunk/tools/commit-queue/workdir',
})
......@@ -140,7 +145,7 @@ class SVNTestCase(BaseSCMTestCase):
</entry>
</info>
""" % self.url
scm.SVN.Capture(['info', '--xml', self.url]).AndReturn(xml_text)
scm.SVN.Capture(['info', '--xml', self.url], None).AndReturn(xml_text)
expected = {
'URL': 'http://src.chromium.org/svn/trunk/src/chrome/app/d',
'UUID': None,
......@@ -154,7 +159,7 @@ class SVNTestCase(BaseSCMTestCase):
'Node Kind': 'file',
}
self.mox.ReplayAll()
file_info = scm.SVN.CaptureInfo(self.url)
file_info = scm.SVN._CaptureInfo([self.url], None)
self.assertEquals(sorted(file_info.items()), sorted(expected.items()))
def testCaptureInfo(self):
......@@ -181,9 +186,9 @@ class SVNTestCase(BaseSCMTestCase):
</entry>
</info>
""" % (self.url, self.root_dir)
scm.SVN.Capture(['info', '--xml', self.url]).AndReturn(xml_text)
scm.SVN.Capture(['info', '--xml', self.url], None).AndReturn(xml_text)
self.mox.ReplayAll()
file_info = scm.SVN.CaptureInfo(self.url)
file_info = scm.SVN._CaptureInfo([self.url], None)
expected = {
'URL': self.url,
'UUID': '7b9385f5-0452-0410-af26-ad4892b7a1fb',
......@@ -235,10 +240,10 @@ class SVNTestCase(BaseSCMTestCase):
</target>
</status>
"""
scm.SVN.Capture(['status', '--xml', '.']).AndReturn(text)
scm.SVN.Capture(['status', '--xml'], '.').AndReturn(text)
self.mox.ReplayAll()
info = scm.SVN.CaptureStatus('.')
info = scm.SVN.CaptureStatus(None, '.')
expected = [
('? ', 'unversionned_file.txt'),
('M ', 'build\\internal\\essential.vsprops'),
......@@ -255,9 +260,9 @@ class SVNTestCase(BaseSCMTestCase):
path="perf">
</target>
</status>"""
scm.SVN.Capture(['status', '--xml']).AndReturn(text)
scm.SVN.Capture(['status', '--xml'], None).AndReturn(text)
self.mox.ReplayAll()
info = scm.SVN.CaptureStatus(None)
info = scm.SVN.CaptureStatus(None, None)
self.assertEquals(info, [])
......
......@@ -244,11 +244,7 @@ class SVN(SCM):
return data
def CaptureStatus(self):
previous_cwd = os.getcwd()
os.chdir(self.checkout_root)
result = scm.SVN.CaptureStatus(self.checkout_root)
os.chdir(previous_cwd)
return result
return scm.SVN.CaptureStatus(None, self.checkout_root)
def GenerateDiff(self):
"""Returns a string containing the diff for the given file list.
......@@ -468,8 +464,9 @@ def GuessVCS(options, path, file_list):
# 128 = git error code when not in a repo.
logging.warning('Unexpected error code: %s' % e.returncode)
raise
raise NoTryServerAccess("Could not guess version control system. "
"Are you in a working copy directory?")
raise NoTryServerAccess(
( 'Could not guess version control system for %s.\n'
'Are you in a working copy directory?') % path)
def GetMungedDiff(path_diff, diff):
......
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