diff --git a/gclient.py b/gclient.py index 86b742f59..8dcb93b6a 100755 --- a/gclient.py +++ b/gclient.py @@ -1044,6 +1044,40 @@ solutions = [ self._root_dir = root_dir self.config_content = None + def _CheckConfig(self): + """Verify that the config matches the state of the existing checked-out + solutions.""" + for dep in self.dependencies: + if dep.managed and dep.url: + scm = gclient_scm.CreateSCM(dep.url, self.root_dir, dep.name) + actual_url = scm.GetActualRemoteURL() + if actual_url and not scm.DoesRemoteURLMatch(): + print >> sys.stderr, (''' +################################################################################ +################################### WARNING! ################################### +################################################################################ + +Your .gclient file seems to be broken. The requested URL is different from what +is actually checked out in %(checkout_path)s. In the future this will be an +error. + +Expected: %(expected_url)s (%(expected_scm)s) +Actual: %(actual_url)s (%(actual_scm)s) + +You should ensure that the URL listed in .gclient is correct and either change +it or fix the checkout. If you're managing your own git checkout in +%(checkout_path)s but the URL in .gclient is for an svn repository, you probably +want to set 'managed': False in .gclient. + +################################################################################ +################################################################################ +################################################################################ +''' % {'checkout_path': os.path.join(self.root_dir, dep.name), + 'expected_url': dep.url, + 'expected_scm': gclient_scm.GetScmName(dep.url), + 'actual_url': actual_url, + 'actual_scm': gclient_scm.GetScmName(actual_url)}) + def SetConfig(self, content): assert not self.dependencies config_dict = {} @@ -1294,6 +1328,7 @@ solutions = [ gclient_utils.rmtree(e_dir) # record the current list of entries for next time self._SaveEntries() + self._CheckConfig() return 0 def PrintRevInfo(self): diff --git a/gclient_scm.py b/gclient_scm.py index e8ab1409a..76b4d8dd2 100644 --- a/gclient_scm.py +++ b/gclient_scm.py @@ -8,6 +8,7 @@ import logging import os import posixpath import re +import shlex import sys import tempfile import traceback @@ -139,6 +140,34 @@ class SCMWrapper(object): return getattr(self, command)(options, args, file_list) + def GetActualRemoteURL(self): + """Attempt to determine the remote URL for this SCMWrapper.""" + try: + return shlex.split(scm.GIT.Capture( + ['config', '--local', '--get-regexp', r'remote.*.url'], + self.checkout_path))[1] + except Exception: + pass + try: + return scm.SVN.CaptureLocalInfo([], self.checkout_path)['URL'] + except Exception: + pass + return None + + def DoesRemoteURLMatch(self): + """Determine whether the remote URL of this checkout is the expected URL.""" + if not os.path.exists(self.checkout_path): + # A checkout which doesn't exist can't be broken. + return True + + actual_remote_url = self.GetActualRemoteURL() + if actual_remote_url: + return actual_remote_url.rstrip('/') == self.url.rstrip('/') + else: + # This may occur if the self.checkout_path exists but does not contain a + # valid git or svn checkout. + return False + class GitWrapper(SCMWrapper): """Wrapper for Git""" diff --git a/tests/gclient_test.py b/tests/gclient_test.py index b758718cc..18876cc86 100755 --- a/tests/gclient_test.py +++ b/tests/gclient_test.py @@ -44,6 +44,13 @@ class SCMMock(object): def FullUrlForRelativeUrl(self, url): return self.url + url + # pylint: disable=R0201 + def DoesRemoteURLMatch(self): + return True + + def GetActualRemoteURL(self): + return self.url + class GclientTest(trial_dir.TestCase): def setUp(self): @@ -250,7 +257,7 @@ class GclientTest(trial_dir.TestCase): topdir = self.root_dir gclient_fn = os.path.join(topdir, '.gclient') fh = open(gclient_fn, 'w') - print >> fh, 'solutions = [{"name":"top","url":"svn://svn.top.com/top"}]' + print >> fh, 'solutions = [{"name":"top","url":"svn://example.com/top"}]' fh.close() subdir_fn = os.path.join(topdir, 'top') os.mkdir(subdir_fn) @@ -281,9 +288,9 @@ class GclientTest(trial_dir.TestCase): gclient_fn = os.path.join(topdir, '.gclient') fh = open(gclient_fn, 'w') extra_hooks = [{'name': 'append', 'pattern':'.', 'action':['supercmd']}] - print >> fh, ('solutions = [{"name":"top","url":"svn://svn.top.com/top",' + print >> fh, ('solutions = [{"name":"top","url":"svn://example.com/top",' '"custom_hooks": %s},' ) % repr(extra_hooks + [{'name': 'skip'}]) - print >> fh, '{"name":"bottom","url":"svn://svn.top.com/bottom"}]' + print >> fh, '{"name":"bottom","url":"svn://example.com/bottom"}]' fh.close() subdir_fn = os.path.join(topdir, 'top') os.mkdir(subdir_fn)