diff --git a/gcl.py b/gcl.py index f6de1f7e92..bc4874da9f 100755 --- a/gcl.py +++ b/gcl.py @@ -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 diff --git a/gclient_scm.py b/gclient_scm.py index c78559076d..55aa1cca19 100644 --- a/gclient_scm.py +++ b/gclient_scm.py @@ -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 ' diff --git a/presubmit_support.py b/presubmit_support.py index 8adbd65d7d..52416d3fdd 100755 --- a/presubmit_support.py +++ b/presubmit_support.py @@ -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): diff --git a/scm.py b/scm.py index 261cb64917..56e795fcfe 100644 --- a/scm.py +++ b/scm.py @@ -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 diff --git a/testing_support/fake_repos.py b/testing_support/fake_repos.py index 8bc4547ddc..3c59b6e7eb 100755 --- a/testing_support/fake_repos.py +++ b/testing_support/fake_repos.py @@ -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] == '!': diff --git a/tests/gcl_unittest.py b/tests/gcl_unittest.py index 2333bf3bd5..e35cbac967 100755 --- a/tests/gcl_unittest.py +++ b/tests/gcl_unittest.py @@ -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') diff --git a/tests/gclient_scm_test.py b/tests/gclient_scm_test.py index a0e24aa11d..87d8acf7e7 100755 --- a/tests/gclient_scm_test.py +++ b/tests/gclient_scm_test.py @@ -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' diff --git a/tests/presubmit_unittest.py b/tests/presubmit_unittest.py index 83bbb6f2a3..a707294294 100755 --- a/tests/presubmit_unittest.py +++ b/tests/presubmit_unittest.py @@ -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('') diff --git a/tests/scm_unittest.py b/tests/scm_unittest.py index 78d5d4dc99..2fbfe3dcfe 100755 --- a/tests/scm_unittest.py +++ b/tests/scm_unittest.py @@ -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): """ % 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): """ % (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): """ - 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"> """ - 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, []) diff --git a/trychange.py b/trychange.py index 12aa948993..cdd17ad32d 100755 --- a/trychange.py +++ b/trychange.py @@ -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):