From 07ab60e26f232b6b755b2c48286f86ce4a4aea95 Mon Sep 17 00:00:00 2001 From: "maruel@chromium.org" Date: Tue, 8 Feb 2011 21:54:00 +0000 Subject: [PATCH] Move reverting code from gclient_scm to scm to be able to reuse the code. There is 2 changes while moving the code: - Making externals handling an option. - Not trapping EnvironmentError. This code will be reused by the commit queue. TEST=unit tests BUG=none Review URL: http://codereview.chromium.org/6250177 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@74181 0039d316-1c4b-4281-b951-d872f2087c98 --- gclient_scm.py | 41 ++++++--------------------------- presubmit_canned_checks.py | 2 +- scm.py | 46 ++++++++++++++++++++++++++++++++++++++ tests/scm_unittest.py | 4 ++-- 4 files changed, 56 insertions(+), 37 deletions(-) diff --git a/gclient_scm.py b/gclient_scm.py index 0a1bbf12d..c460a76d6 100644 --- a/gclient_scm.py +++ b/gclient_scm.py @@ -838,49 +838,22 @@ class SVNWrapper(SCMWrapper): # Don't reuse the args. return self.update(options, [], file_list) - for file_status in scm.SVN.CaptureStatus(self.checkout_path): - file_path = os.path.join(self.checkout_path, file_status[1]) - # Temporarily forcibly delete externals to make sure chromium can build - # without svn:external's. - #if file_status[0][0] == 'X': - # # Ignore externals. - # logging.info('Ignoring external %s' % file_path) - # continue - + def printcb(file_status): + file_list.append(file_status[1]) if logging.getLogger().isEnabledFor(logging.INFO): - logging.info('%s%s' % (file[0], file[1])) + logging.info('%s%s' % (file_status[0], file_status[1])) else: - print(file_path) - - if file_status[0].isspace(): - logging.error('No idea what is the status of %s.\n' - 'You just found a bug in gclient, please ping ' - 'maruel@chromium.org ASAP!' % file_path) - # svn revert is really stupid. It fails on inconsistent line-endings, - # on switched directories, etc. So take no chance and delete everything! - try: - if not os.path.exists(file_path): - pass - elif os.path.isfile(file_path) or os.path.islink(file_path): - logging.info('os.remove(%s)' % file_path) - os.remove(file_path) - elif os.path.isdir(file_path): - logging.info('gclient_utils.RemoveDirectory(%s)' % file_path) - gclient_utils.RemoveDirectory(file_path) - else: - logging.error('no idea what is %s.\nYou just found a bug in gclient' - ', please ping maruel@chromium.org ASAP!' % file_path) - except EnvironmentError: - logging.error('Failed to remove %s.' % file_path) + print(os.path.join(self.checkout_path, file_status[1])) + scm.SVN.Revert(self.checkout_path, callback=printcb) try: # svn revert is so broken we don't even use it. Using # "svn up --revision BASE" achieve the same effect. + # file_list will contain duplicates. self._RunAndGetFileList(['update', '--revision', 'BASE'], options, file_list) except OSError, e: - # Maybe the directory disapeared meanwhile. We don't want it to throw an - # exception. + # Maybe the directory disapeared meanwhile. Do not throw an exception. logging.error('Failed to update:\n%s' % str(e)) def revinfo(self, options, args, file_list): diff --git a/presubmit_canned_checks.py b/presubmit_canned_checks.py index 5c268ef08..79e030918 100644 --- a/presubmit_canned_checks.py +++ b/presubmit_canned_checks.py @@ -237,7 +237,7 @@ def CheckChangeHasNoTabs(input_api, output_api, source_file_filter=None): def CheckChangeTodoHasOwner(input_api, output_api, source_file_filter=None): """Checks that the user didn't add TODO(name) without an owner.""" - unowned_todo = input_api.re.compile('TO' + 'DO[^(]'); + unowned_todo = input_api.re.compile('TO' + 'DO[^(]') for f, line_num, line in input_api.RightHandSideLines(source_file_filter): if unowned_todo.search(line): text = ('Found TO' + 'DO with no owner in %s, line %s' % diff --git a/scm.py b/scm.py index ea91c7b69..872b3fe05 100644 --- a/scm.py +++ b/scm.py @@ -6,6 +6,7 @@ import cStringIO import glob +import logging import os import re import shutil @@ -828,3 +829,48 @@ class SVN(object): elif ver > min_ver: return (True, SVN.current_version) return (True, SVN.current_version) + + @staticmethod + def Revert(repo_root, callback=None, ignore_externals=False): + """Reverts all svn modifications in repo_root, 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]) + if ignore_externals and file_status[0][0] == 'X': + # Ignore externals. + logging.info('Ignoring external %s' % file_status[1]) + continue + + if callback: + callback(file_status) + + if file_status[0].isspace(): + # Try reverting the file since it's probably a property change. + gclient_utils.CheckCall( + ['svn', 'revert', file_status[1]], cwd=repo_root) + + # svn revert is really stupid. It fails on inconsistent line-endings, + # on switched directories, etc. So take no chance and delete everything! + if file_status[0][0] == 'D': + # Deleted file requires manual intervention and require calling + # revert, like for properties. + gclient_utils.CheckCall( + ['svn', 'revert', file_status[1]], cwd=repo_root) + else: + if not os.path.exists(file_path): + pass + elif os.path.isfile(file_path) or os.path.islink(file_path): + logging.info('os.remove(%s)' % file_path) + os.remove(file_path) + elif os.path.isdir(file_path): + logging.info('gclient_utils.RemoveDirectory(%s)' % file_path) + gclient_utils.RemoveDirectory(file_path) + else: + logging.critical( + ('No idea what is %s.\nYou just found a bug in gclient' + ', please ping maruel@chromium.org ASAP!') % file_path) diff --git a/tests/scm_unittest.py b/tests/scm_unittest.py index 9d71d245f..7a3cbbb29 100755 --- a/tests/scm_unittest.py +++ b/tests/scm_unittest.py @@ -38,7 +38,7 @@ class RootTestCase(BaseSCMTestCase): self.mox.ReplayAll() members = [ 'GetCasedPath', 'GenFakeDiff', 'GIT', 'SVN', 'ValidateEmail', - 'cStringIO', 'gclient_utils', 'glob', 'os', 're', 'shutil', + 'cStringIO', 'gclient_utils', 'glob', 'logging', 'os', 're', 'shutil', 'subprocess', 'sys', 'tempfile', 'time', 'xml', ] # If this test fails, you should add the relevant test. @@ -77,7 +77,7 @@ class SVNTestCase(BaseSCMTestCase): 'AssertVersion', 'Capture', 'CaptureRevision', 'CaptureInfo', 'CaptureStatus', 'current_version', 'DiffItem', 'GenerateDiff', 'GetCheckoutRoot', 'GetEmail', 'GetFileProperty', 'IsMoved', - 'IsMovedInfo', 'ReadSimpleAuth', 'RunAndGetFileList', + 'IsMovedInfo', 'ReadSimpleAuth', 'Revert', 'RunAndGetFileList', ] # If this test fails, you should add the relevant test. self.compareMembers(scm.SVN, members)