Commit 54019f3c authored by maruel@chromium.org's avatar maruel@chromium.org

Change scm.SVN.Capture to redirect stderr and throw an exception on call failure.

Added try/except to the places where errors are tolerated.

Renamed scm.SVN.CaptureBaseRevision to CaptureRevision and removed CaptureHeadRevision.

BUG=54084
TEST=none

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@58932 0039d316-1c4b-4281-b951-d872f2087c98
parent 7aae8fb1
...@@ -742,12 +742,12 @@ class SVNWrapper(SCMWrapper): ...@@ -742,12 +742,12 @@ class SVNWrapper(SCMWrapper):
return return
# Get the existing scm url and the revision number of the current checkout. # Get the existing scm url and the revision number of the current checkout.
from_info = scm.SVN.CaptureInfo(os.path.join(self.checkout_path, '.'), '.') try:
if not from_info: from_info = scm.SVN.CaptureInfo(os.path.join(self.checkout_path, '.'))
raise gclient_utils.Error(('Can\'t update/checkout %r if an unversioned ' except gclient_utils.Error:
'directory is present. Delete the directory ' raise gclient_utils.Error(
'and try again.') % ('Can\'t update/checkout %s if an unversioned directory is present. '
self.checkout_path) 'Delete the directory and try again.') % self.checkout_path)
# Look for locked directories. # Look for locked directories.
dir_info = scm.SVN.CaptureStatus(os.path.join(self.checkout_path, '.')) dir_info = scm.SVN.CaptureStatus(os.path.join(self.checkout_path, '.'))
...@@ -758,14 +758,15 @@ class SVNWrapper(SCMWrapper): ...@@ -758,14 +758,15 @@ class SVNWrapper(SCMWrapper):
# Retrieve the current HEAD version because svn is slow at null updates. # Retrieve the current HEAD version because svn is slow at null updates.
if options.manually_grab_svn_rev and not revision: if options.manually_grab_svn_rev and not revision:
from_info_live = scm.SVN.CaptureInfo(from_info['URL'], '.') from_info_live = scm.SVN.CaptureInfo(from_info['URL'])
revision = str(from_info_live['Revision']) revision = str(from_info_live['Revision'])
rev_str = ' at %s' % revision rev_str = ' at %s' % revision
if from_info['URL'] != base_url: if from_info['URL'] != base_url:
# The repository url changed, need to switch. # The repository url changed, need to switch.
to_info = scm.SVN.CaptureInfo(url, '.') try:
if not to_info.get('Repository Root') or not to_info.get('UUID'): to_info = scm.SVN.CaptureInfo(url)
except gclient_utils.Error:
# The url is invalid or the server is not accessible, it's safer to bail # The url is invalid or the server is not accessible, it's safer to bail
# out right now. # out right now.
raise gclient_utils.Error('This url is unreachable: %s' % url) raise gclient_utils.Error('This url is unreachable: %s' % url)
...@@ -919,7 +920,10 @@ class SVNWrapper(SCMWrapper): ...@@ -919,7 +920,10 @@ class SVNWrapper(SCMWrapper):
def revinfo(self, options, args, file_list): def revinfo(self, options, args, file_list):
"""Display revision""" """Display revision"""
return scm.SVN.CaptureBaseRevision(self.checkout_path) try:
return scm.SVN.CaptureRevision(self.checkout_path)
except gclient_utils.Error:
return None
def runhooks(self, options, args, file_list): def runhooks(self, options, args, file_list):
self.status(options, args, file_list) self.status(options, args, file_list)
......
...@@ -306,21 +306,12 @@ class SVN(object): ...@@ -306,21 +306,12 @@ class SVN(object):
current_version = None current_version = None
@staticmethod @staticmethod
def Capture(args, in_directory=None, print_error=True): def Capture(args, **kwargs):
"""Runs svn, capturing output sent to stdout as a string. """Always redirect stderr.
Args: Throws an exception if non-0 is returned."""
args: A sequence of command line parameters to be passed to svn. return gclient_utils.CheckCall(['svn'] + args, print_error=False,
in_directory: The directory where svn is to be run. **kwargs)[0]
Returns:
The output sent to stdout as a string.
"""
stderr = None
if not print_error:
stderr = subprocess.PIPE
return gclient_utils.Popen(['svn'] + args, cwd=in_directory,
stdout=subprocess.PIPE, stderr=stderr).communicate()[0]
@staticmethod @staticmethod
def RunAndGetFileList(verbose, args, cwd, file_list, stdout=None): def RunAndGetFileList(verbose, args, cwd, file_list, stdout=None):
...@@ -425,15 +416,11 @@ class SVN(object): ...@@ -425,15 +416,11 @@ class SVN(object):
break break
@staticmethod @staticmethod
def CaptureInfo(relpath, in_directory=None, print_error=True): def CaptureInfo(cwd):
"""Returns a dictionary from the svn info output for the given file. """Returns a dictionary from the svn info output for the given file.
Args: Throws an exception if svn info fails."""
relpath: The directory where the working copy resides relative to output = SVN.Capture(['info', '--xml', cwd])
the directory given by in_directory.
in_directory: The directory where svn is to be run.
"""
output = SVN.Capture(["info", "--xml", relpath], in_directory, print_error)
dom = gclient_utils.ParseXML(output) dom = gclient_utils.ParseXML(output)
result = {} result = {}
if dom: if dom:
...@@ -468,24 +455,13 @@ class SVN(object): ...@@ -468,24 +455,13 @@ class SVN(object):
return result return result
@staticmethod @staticmethod
def CaptureHeadRevision(url): def CaptureRevision(cwd):
"""Get the head revision of a SVN repository.
Returns:
Int head revision
"""
info = SVN.Capture(["info", "--xml", url], os.getcwd())
dom = xml.dom.minidom.parseString(info)
return dom.getElementsByTagName('entry')[0].getAttribute('revision')
@staticmethod
def CaptureBaseRevision(cwd):
"""Get the base revision of a SVN repository. """Get the base revision of a SVN repository.
Returns: Returns:
Int base revision Int base revision
""" """
info = SVN.Capture(["info", "--xml"], cwd) info = SVN.Capture(['info', '--xml'], cwd=cwd)
dom = xml.dom.minidom.parseString(info) dom = xml.dom.minidom.parseString(info)
return dom.getElementsByTagName('entry')[0].getAttribute('revision') return dom.getElementsByTagName('entry')[0].getAttribute('revision')
...@@ -539,8 +515,9 @@ class SVN(object): ...@@ -539,8 +515,9 @@ class SVN(object):
if xml_item_status in status_letter: if xml_item_status in status_letter:
statuses[0] = status_letter[xml_item_status] statuses[0] = status_letter[xml_item_status]
else: else:
raise Exception('Unknown item status "%s"; please implement me!' % raise gclient_utils.Error(
xml_item_status) 'Unknown item status "%s"; please implement me!' %
xml_item_status)
# Col 1 # Col 1
xml_props_status = wc_status[0].getAttribute('props') xml_props_status = wc_status[0].getAttribute('props')
if xml_props_status == 'modified': if xml_props_status == 'modified':
...@@ -551,8 +528,9 @@ class SVN(object): ...@@ -551,8 +528,9 @@ class SVN(object):
xml_props_status == 'normal'): xml_props_status == 'normal'):
pass pass
else: else:
raise Exception('Unknown props status "%s"; please implement me!' % raise gclient_utils.Error(
xml_props_status) 'Unknown props status "%s"; please implement me!' %
xml_props_status)
# Col 2 # Col 2
if wc_status[0].getAttribute('wc-locked') == 'true': if wc_status[0].getAttribute('wc-locked') == 'true':
statuses[2] = 'L' statuses[2] = 'L'
...@@ -592,12 +570,10 @@ class SVN(object): ...@@ -592,12 +570,10 @@ class SVN(object):
is not set on the file. If the file is not under version control, the is not set on the file. If the file is not under version control, the
empty string is also returned. empty string is also returned.
""" """
output = SVN.Capture(["propget", property_name, filename]) try:
if (output.startswith("svn: ") and return SVN.Capture(['propget', property_name, filename])
output.endswith("is not under version control")): except gclient_utils.Error:
return "" return ''
else:
return output
@staticmethod @staticmethod
def DiffItem(filename, full_move=False, revision=None): def DiffItem(filename, full_move=False, revision=None):
...@@ -662,7 +638,7 @@ class SVN(object): ...@@ -662,7 +638,7 @@ class SVN(object):
else: else:
if info.get("Node Kind") != "directory": if info.get("Node Kind") != "directory":
# svn diff on a mv/cp'd file outputs nothing if there was no change. # svn diff on a mv/cp'd file outputs nothing if there was no change.
data = SVN.Capture(command, None) data = SVN.Capture(command)
if not data: if not data:
# We put in an empty Index entry so upload.py knows about them. # We put in an empty Index entry so upload.py knows about them.
data = "Index: %s\n" % filename.replace(os.sep, '/') data = "Index: %s\n" % filename.replace(os.sep, '/')
...@@ -670,7 +646,7 @@ class SVN(object): ...@@ -670,7 +646,7 @@ class SVN(object):
else: else:
if info.get("Node Kind") != "directory": if info.get("Node Kind") != "directory":
# Normal simple case. # Normal simple case.
data = SVN.Capture(command, None) data = SVN.Capture(command)
# Otherwise silently ignore directories. # Otherwise silently ignore directories.
return data return data
...@@ -761,14 +737,15 @@ class SVN(object): ...@@ -761,14 +737,15 @@ class SVN(object):
@staticmethod @staticmethod
def GetEmail(repo_root): def GetEmail(repo_root):
"""Retrieves the svn account which we assume is an email address.""" """Retrieves the svn account which we assume is an email address."""
infos = SVN.CaptureInfo(repo_root) try:
uuid = infos.get('UUID') infos = SVN.CaptureInfo(repo_root)
root = infos.get('Repository Root') except gclient_utils.Error:
if not root:
return None return None
# Should check for uuid but it is incorrectly saved for https creds. # Should check for uuid but it is incorrectly saved for https creds.
root = infos['Repository Root']
realm = root.rsplit('/', 1)[0] realm = root.rsplit('/', 1)[0]
uuid = infos['UUID']
if root.startswith('https') or not uuid: if root.startswith('https') or not uuid:
regexp = re.compile(r'<%s:\d+>.*' % realm) regexp = re.compile(r'<%s:\d+>.*' % realm)
else: else:
...@@ -820,15 +797,16 @@ class SVN(object): ...@@ -820,15 +797,16 @@ class SVN(object):
The directory is returned as an absolute path. The directory is returned as an absolute path.
""" """
directory = os.path.abspath(directory) directory = os.path.abspath(directory)
infos = SVN.CaptureInfo(directory, print_error=False) try:
cur_dir_repo_root = infos.get("Repository Root") cur_dir_repo_root = SVN.CaptureInfo(directory)['Repository Root']
if not cur_dir_repo_root: except gclient_utils.Error:
return None return None
while True: while True:
parent = os.path.dirname(directory) parent = os.path.dirname(directory)
if (SVN.CaptureInfo(parent, print_error=False).get( try:
"Repository Root") != cur_dir_repo_root): if SVN.CaptureInfo(parent)['Repository Root'] != cur_dir_repo_root:
break
except gclient_utils.Error:
break break
directory = parent directory = parent
return GetCasedPath(directory) return GetCasedPath(directory)
......
This diff is collapsed.
...@@ -28,9 +28,10 @@ class BaseTestCase(SuperMoxTestBase): ...@@ -28,9 +28,10 @@ class BaseTestCase(SuperMoxTestBase):
class BaseSCMTestCase(BaseTestCase): class BaseSCMTestCase(BaseTestCase):
def setUp(self): def setUp(self):
BaseTestCase.setUp(self) BaseTestCase.setUp(self)
self.mox.StubOutWithMock(scm.gclient_utils, 'Popen') self.mox.StubOutWithMock(scm.gclient_utils, 'CheckCall')
self.mox.StubOutWithMock(scm.gclient_utils, 'CheckCallAndFilter') self.mox.StubOutWithMock(scm.gclient_utils, 'CheckCallAndFilter')
self.mox.StubOutWithMock(scm.gclient_utils, 'CheckCallAndFilterAndHeader') self.mox.StubOutWithMock(scm.gclient_utils, 'CheckCallAndFilterAndHeader')
self.mox.StubOutWithMock(scm.gclient_utils, 'Popen')
class RootTestCase(BaseSCMTestCase): class RootTestCase(BaseSCMTestCase):
...@@ -153,13 +154,13 @@ class SVNTestCase(BaseSCMTestCase): ...@@ -153,13 +154,13 @@ class SVNTestCase(BaseSCMTestCase):
self.args = self.Args() self.args = self.Args()
self.url = self.Url() self.url = self.Url()
self.relpath = 'asf' self.relpath = 'asf'
self.mox.StubOutWithMock(scm.SVN, 'Capture')
def testMembersChanged(self): def testMembersChanged(self):
self.mox.ReplayAll() self.mox.ReplayAll()
members = [ members = [
'AssertVersion', 'Capture', 'CaptureBaseRevision', 'AssertVersion', 'Capture', 'CaptureRevision', 'CaptureInfo',
'CaptureHeadRevision', 'CaptureInfo', 'CaptureStatus', 'CaptureStatus', 'current_version', 'DiffItem', 'GenerateDiff',
'current_version', 'DiffItem', 'GenerateDiff',
'GetCheckoutRoot', 'GetEmail', 'GetFileProperty', 'IsMoved', 'GetCheckoutRoot', 'GetEmail', 'GetFileProperty', 'IsMoved',
'IsMovedInfo', 'ReadSimpleAuth', 'RunAndGetFileList', 'IsMovedInfo', 'ReadSimpleAuth', 'RunAndGetFileList',
] ]
...@@ -172,10 +173,10 @@ class SVNTestCase(BaseSCMTestCase): ...@@ -172,10 +173,10 @@ class SVNTestCase(BaseSCMTestCase):
scm.os.path.abspath(self.root_dir + 'x').AndReturn(self.root_dir) scm.os.path.abspath(self.root_dir + 'x').AndReturn(self.root_dir)
scm.GetCasedPath(self.root_dir).AndReturn(self.root_dir) scm.GetCasedPath(self.root_dir).AndReturn(self.root_dir)
result1 = { "Repository Root": "Some root" } result1 = { "Repository Root": "Some root" }
scm.SVN.CaptureInfo(self.root_dir, print_error=False).AndReturn(result1) scm.SVN.CaptureInfo(self.root_dir).AndReturn(result1)
results2 = { "Repository Root": "A different root" } results2 = { "Repository Root": "A different root" }
scm.SVN.CaptureInfo(scm.os.path.dirname(self.root_dir), scm.SVN.CaptureInfo(
print_error=False).AndReturn(results2) scm.os.path.dirname(self.root_dir)).AndReturn(results2)
self.mox.ReplayAll() self.mox.ReplayAll()
self.assertEquals(scm.SVN.GetCheckoutRoot(self.root_dir + 'x'), self.assertEquals(scm.SVN.GetCheckoutRoot(self.root_dir + 'x'),
self.root_dir) self.root_dir)
...@@ -196,8 +197,7 @@ class SVNTestCase(BaseSCMTestCase): ...@@ -196,8 +197,7 @@ class SVNTestCase(BaseSCMTestCase):
</entry> </entry>
</info> </info>
""" % self.url """ % self.url
self.mox.StubOutWithMock(scm.SVN, 'Capture') scm.SVN.Capture(['info', '--xml', self.url]).AndReturn(xml_text)
scm.SVN.Capture(['info', '--xml', self.url], '.', True).AndReturn(xml_text)
expected = { expected = {
'URL': 'http://src.chromium.org/svn/trunk/src/chrome/app/d', 'URL': 'http://src.chromium.org/svn/trunk/src/chrome/app/d',
'UUID': None, 'UUID': None,
...@@ -211,7 +211,7 @@ class SVNTestCase(BaseSCMTestCase): ...@@ -211,7 +211,7 @@ class SVNTestCase(BaseSCMTestCase):
'Node Kind': 'file', 'Node Kind': 'file',
} }
self.mox.ReplayAll() self.mox.ReplayAll()
file_info = scm.SVN.CaptureInfo(self.url, '.', True) file_info = scm.SVN.CaptureInfo(self.url)
self.assertEquals(sorted(file_info.items()), sorted(expected.items())) self.assertEquals(sorted(file_info.items()), sorted(expected.items()))
def testCaptureInfo(self): def testCaptureInfo(self):
...@@ -238,10 +238,9 @@ class SVNTestCase(BaseSCMTestCase): ...@@ -238,10 +238,9 @@ class SVNTestCase(BaseSCMTestCase):
</entry> </entry>
</info> </info>
""" % (self.url, self.root_dir) """ % (self.url, self.root_dir)
self.mox.StubOutWithMock(scm.SVN, 'Capture') scm.SVN.Capture(['info', '--xml', self.url]).AndReturn(xml_text)
scm.SVN.Capture(['info', '--xml', self.url], '.', True).AndReturn(xml_text)
self.mox.ReplayAll() self.mox.ReplayAll()
file_info = scm.SVN.CaptureInfo(self.url, '.', True) file_info = scm.SVN.CaptureInfo(self.url)
expected = { expected = {
'URL': self.url, 'URL': self.url,
'UUID': '7b9385f5-0452-0410-af26-ad4892b7a1fb', 'UUID': '7b9385f5-0452-0410-af26-ad4892b7a1fb',
...@@ -293,12 +292,7 @@ class SVNTestCase(BaseSCMTestCase): ...@@ -293,12 +292,7 @@ class SVNTestCase(BaseSCMTestCase):
</target> </target>
</status> </status>
""" """
proc = self.mox.CreateMockAnything() scm.SVN.Capture(['status', '--xml', '.']).AndReturn(text)
scm.gclient_utils.Popen(['svn', 'status', '--xml', '.'],
cwd=None,
stderr=None,
stdout=scm.subprocess.PIPE).AndReturn(proc)
proc.communicate().AndReturn((text, 0))
self.mox.ReplayAll() self.mox.ReplayAll()
info = scm.SVN.CaptureStatus('.') info = scm.SVN.CaptureStatus('.')
...@@ -318,12 +312,7 @@ class SVNTestCase(BaseSCMTestCase): ...@@ -318,12 +312,7 @@ class SVNTestCase(BaseSCMTestCase):
path="perf"> path="perf">
</target> </target>
</status>""" </status>"""
proc = self.mox.CreateMockAnything() scm.SVN.Capture(['status', '--xml']).AndReturn(text)
scm.gclient_utils.Popen(['svn', 'status', '--xml'],
cwd=None,
stderr=None,
stdout=scm.subprocess.PIPE).AndReturn(proc)
proc.communicate().AndReturn((text, 0))
self.mox.ReplayAll() self.mox.ReplayAll()
info = scm.SVN.CaptureStatus(None) info = scm.SVN.CaptureStatus(None)
self.assertEquals(info, []) self.assertEquals(info, [])
......
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