diff --git a/gclient_scm.py b/gclient_scm.py index e8c1711f8..1beaae8b4 100644 --- a/gclient_scm.py +++ b/gclient_scm.py @@ -85,7 +85,10 @@ def CreateSCM(url, root_dir=None, relpath=None): scm_name = GetScmName(url) if not scm_name in SCM_MAP: raise gclient_utils.Error('No SCM found for url %s' % url) - return SCM_MAP[scm_name](url, root_dir, relpath) + scm_class = SCM_MAP[scm_name] + if not scm_class.BinaryExists(): + raise gclient_utils.Error('%s command not found' % scm_name) + return scm_class(url, root_dir, relpath) # SCMWrapper base class @@ -133,6 +136,18 @@ class GitWrapper(SCMWrapper): url = url[4:] SCMWrapper.__init__(self, url, root_dir, relpath) + @staticmethod + def BinaryExists(): + """Returns true if the command exists.""" + try: + # We assume git is newer than 1.7. See: crbug.com/114483 + result, version = scm.GIT.AssertVersion('1.7') + if not result: + raise gclient_utils.Error('Git version is older than 1.7: %s' % version) + return result + except OSError: + return False + def GetRevisionDate(self, revision): """Returns the given revision's date in ISO-8601 format (which contains the time zone).""" @@ -775,6 +790,17 @@ class GitWrapper(SCMWrapper): class SVNWrapper(SCMWrapper): """ Wrapper for SVN """ + @staticmethod + def BinaryExists(): + """Returns true if the command exists.""" + try: + result, version = scm.SVN.AssertVersion('1.4') + if not result: + raise gclient_utils.Error('SVN version is older than 1.4: %s' % version) + return result + except OSError: + return False + def GetRevisionDate(self, revision): """Returns the given revision's date in ISO-8601 format (which contains the time zone).""" diff --git a/tests/gclient_scm_test.py b/tests/gclient_scm_test.py index 94ab4203a..ebe5e45dc 100755 --- a/tests/gclient_scm_test.py +++ b/tests/gclient_scm_test.py @@ -64,11 +64,17 @@ class BaseTestCase(GCBaseTestCase, SuperMoxTestBase): self.mox.StubOutWithMock(subprocess2, 'Popen') self._scm_wrapper = gclient_scm.CreateSCM gclient_scm.scm.SVN.current_version = None + self._original_SVNBinaryExists = gclient_scm.SVNWrapper.BinaryExists + self._original_GitBinaryExists = gclient_scm.GitWrapper.BinaryExists + gclient_scm.SVNWrapper.BinaryExists = staticmethod(lambda : True) + gclient_scm.GitWrapper.BinaryExists = staticmethod(lambda : True) # Absolute path of the fake checkout directory. self.base_path = join(self.root_dir, self.relpath) def tearDown(self): SuperMoxTestBase.tearDown(self) + gclient_scm.SVNWrapper.BinaryExists = self._original_SVNBinaryExists + gclient_scm.GitWrapper.BinaryExists = self._original_GitBinaryExists class SVNWrapperTestCase(BaseTestCase): @@ -94,6 +100,7 @@ class SVNWrapperTestCase(BaseTestCase): def testDir(self): members = [ + 'BinaryExists', 'FullUrlForRelativeUrl', 'GetRevisionDate', 'GetUsableRev', @@ -750,16 +757,23 @@ from :3 self.base_path = join(self.root_dir, self.relpath) self.enabled = self.CreateGitRepo(self.sample_git_import, self.base_path) StdoutCheck.setUp(self) + self._original_GitBinaryExists = gclient_scm.GitWrapper.BinaryExists + self._original_SVNBinaryExists = gclient_scm.SVNWrapper.BinaryExists + gclient_scm.GitWrapper.BinaryExists = staticmethod(lambda : True) + gclient_scm.SVNWrapper.BinaryExists = staticmethod(lambda : True) def tearDown(self): StdoutCheck.tearDown(self) TestCaseUtils.tearDown(self) unittest.TestCase.tearDown(self) rmtree(self.root_dir) + gclient_scm.GitWrapper.BinaryExists = self._original_GitBinaryExists + gclient_scm.SVNWrapper.BinaryExists = self._original_SVNBinaryExists class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): def testDir(self): members = [ + 'BinaryExists', 'FullUrlForRelativeUrl', 'GetRevisionDate', 'GetUsableRev',