Commit 7ff04292 authored by borenet@google.com's avatar borenet@google.com

Another attempt: gclient: delete mismatching checkouts

Review URL: https://codereview.chromium.org/183283003

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@255930 0039d316-1c4b-4281-b951-d872f2087c98
parent 0d23d776
......@@ -300,6 +300,21 @@ class GitWrapper(SCMWrapper):
if (not os.path.exists(self.checkout_path) or
(os.path.isdir(self.checkout_path) and
not os.path.exists(os.path.join(self.checkout_path, '.git')))):
if (os.path.isdir(self.checkout_path) and
not os.path.exists(os.path.join(self.checkout_path, '.git'))):
if options.force:
# Delete and re-sync.
print('_____ Conflicting directory found in %s. Removing.'
% self.checkout_path)
gclient_utils.rmtree(self.checkout_path)
else:
raise gclient_utils.Error('\n____ %s%s\n'
'\tPath is not a git repo. No .git dir.\n'
'\tTo resolve:\n'
'\t\trm -rf %s\n'
'\tAnd run gclient sync again\n'
'\tOr run with --force\n'
% (self.relpath, rev_str, self.relpath))
self._Clone(revision, url, options)
self.UpdateSubmoduleConfig()
if file_list is not None:
......@@ -317,14 +332,6 @@ class GitWrapper(SCMWrapper):
print ('________ unmanaged solution; skipping %s' % self.relpath)
return self._Capture(['rev-parse', '--verify', 'HEAD'])
if not os.path.exists(os.path.join(self.checkout_path, '.git')):
raise gclient_utils.Error('\n____ %s%s\n'
'\tPath is not a git repo. No .git dir.\n'
'\tTo resolve:\n'
'\t\trm -rf %s\n'
'\tAnd run gclient sync again\n'
% (self.relpath, rev_str, self.relpath))
# See if the url has changed (the unittests use git://foo for the url, let
# that through).
current_url = self._Capture(['config', 'remote.%s.url' % self.remote])
......@@ -334,7 +341,7 @@ class GitWrapper(SCMWrapper):
# Skip url auto-correction if remote.origin.gclient-auto-fix-url is set.
# This allows devs to use experimental repos which have a different url
# but whose branch(s) are the same as official repos.
if (current_url != url and
if (current_url.rstrip('/') != url.rstrip('/') and
url != 'git://foo' and
subprocess2.capture(
['git', 'config', 'remote.%s.gclient-auto-fix-url' % self.remote],
......@@ -999,12 +1006,7 @@ class SVNWrapper(SCMWrapper):
Raises:
Error: if can't get URL for relative path.
"""
# Only update if git or hg is not controlling the directory.
git_path = os.path.join(self.checkout_path, '.git')
if os.path.exists(git_path):
print('________ found .git directory; skipping %s' % self.relpath)
return
# Only update if hg is not controlling the directory.
hg_path = os.path.join(self.checkout_path, '.hg')
if os.path.exists(hg_path):
print('________ found .hg directory; skipping %s' % self.relpath)
......@@ -1035,14 +1037,26 @@ class SVNWrapper(SCMWrapper):
forced_revision = False
rev_str = ''
# Get the existing scm url and the revision number of the current checkout.
exists = os.path.exists(self.checkout_path)
if exists and managed:
# Git is only okay if it's a git-svn checkout of the right repo.
if scm.GIT.IsGitSvn(self.checkout_path):
remote_url = scm.GIT.Capture(['config', '--local', '--get',
'svn-remote.svn.url'],
cwd=self.checkout_path).rstrip()
if remote_url.rstrip('/') == base_url.rstrip('/'):
print('\n_____ %s looks like a git-svn checkout. Skipping.'
% self.relpath)
return # TODO(borenet): Get the svn revision number?
# Get the existing scm url and the revision number of the current checkout.
if exists and managed:
try:
from_info = scm.SVN.CaptureLocalInfo(
[], os.path.join(self.checkout_path, '.'))
except (gclient_utils.Error, subprocess2.CalledProcessError):
if options.reset and options.delete_unversioned_trees:
if (options.force or
(options.reset and options.delete_unversioned_trees)):
print 'Removing troublesome path %s' % self.checkout_path
gclient_utils.rmtree(self.checkout_path)
exists = False
......@@ -1129,7 +1143,9 @@ class SVNWrapper(SCMWrapper):
if not managed:
print ('________ unmanaged solution; skipping %s' % self.relpath)
return self.Svnversion()
if not scm.GIT.IsGitSvn(self.checkout_path):
return self.Svnversion()
return
if 'URL' not in from_info:
raise gclient_utils.Error(
......@@ -1172,7 +1188,7 @@ class SVNWrapper(SCMWrapper):
revision = str(from_info_live['Revision'])
rev_str = ' at %s' % revision
if from_info['URL'] != base_url:
if from_info['URL'].rstrip('/') != base_url.rstrip('/'):
# The repository url changed, need to switch.
try:
to_info = scm.SVN.CaptureRemoteInfo(url)
......
......@@ -167,7 +167,7 @@ class GIT(object):
@staticmethod
def IsGitSvn(cwd):
"""Returns true if this repo looks like it's using git-svn."""
"""Returns True if this repo looks like it's using git-svn."""
# If you have any "svn-remote.*" config keys, we think you're using svn.
try:
GIT.Capture(['config', '--local', '--get-regexp', r'^svn-remote\.'],
......
......@@ -752,6 +752,82 @@ class FakeRepoTransitive(FakeReposBase):
pass
class FakeRepoSkiaDEPS(FakeReposBase):
"""Simulates the Skia DEPS transition in Chrome."""
NB_GIT_REPOS = 5
DEPS_svn_pre = """deps = {
'src/third_party/skia/gyp': '%(svn_base)sskia/gyp',
'src/third_party/skia/include': '%(svn_base)sskia/include',
'src/third_party/skia/src': '%(svn_base)sskia/src',
}"""
DEPS_git_pre = """deps = {
'src/third_party/skia/gyp': '%(git_base)srepo_3',
'src/third_party/skia/include': '%(git_base)srepo_4',
'src/third_party/skia/src': '%(git_base)srepo_5',
}"""
DEPS_post = """deps = {
'src/third_party/skia': '%(git_base)srepo_1',
}"""
def populateSvn(self):
"""Create revisions which simulate the Skia DEPS transition in Chrome."""
subprocess2.check_call(
['svn', 'checkout', self.svn_base, self.svn_checkout,
'-q', '--non-interactive', '--no-auth-cache',
'--username', self.USERS[0][0], '--password', self.USERS[0][1]])
assert os.path.isdir(join(self.svn_checkout, '.svn'))
# Skia repo.
self._commit_svn({
'skia/skia_base_file': 'root-level file.',
'skia/gyp/gyp_file': 'file in the gyp directory',
'skia/include/include_file': 'file in the include directory',
'skia/src/src_file': 'file in the src directory',
})
# Chrome repo.
self._commit_svn({
'trunk/src/DEPS': self.DEPS_svn_pre % {'svn_base': self.svn_base},
'trunk/src/myfile': 'svn/trunk/src@1'
})
self._commit_svn({
'trunk/src/DEPS': self.DEPS_post % {'git_base': self.git_base},
'trunk/src/myfile': 'svn/trunk/src@2'
})
def populateGit(self):
# Skia repo.
self._commit_git('repo_1', {
'skia_base_file': 'root-level file.',
'gyp/gyp_file': 'file in the gyp directory',
'include/include_file': 'file in the include directory',
'src/src_file': 'file in the src directory',
})
self._commit_git('repo_3', { # skia/gyp
'gyp_file': 'file in the gyp directory',
})
self._commit_git('repo_4', { # skia/include
'include_file': 'file in the include directory',
})
self._commit_git('repo_5', { # skia/src
'src_file': 'file in the src directory',
})
# Chrome repo.
self._commit_git('repo_2', {
'DEPS': self.DEPS_git_pre % {'git_base': self.git_base},
'myfile': 'svn/trunk/src@1'
})
self._commit_git('repo_2', {
'DEPS': self.DEPS_post % {'git_base': self.git_base},
'myfile': 'svn/trunk/src@2'
})
class FakeReposTestBase(trial_dir.TestCase):
"""This is vaguely inspired by twisted."""
# Static FakeRepos instances. Lazy loaded.
......
This diff is collapsed.
......@@ -21,9 +21,11 @@ ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, ROOT_DIR)
from testing_support.fake_repos import join, write
from testing_support.fake_repos import FakeReposTestBase, FakeRepoTransitive
from testing_support.fake_repos import FakeReposTestBase, FakeRepoTransitive, \
FakeRepoSkiaDEPS
import gclient_utils
import scm as gclient_scm
import subprocess2
......@@ -1397,6 +1399,170 @@ class GClientSmokeBoth(GClientSmokeBase):
self.assertEquals(sorted(entries), sorted(expected))
class SkiaDEPSTransitionSmokeTest(GClientSmokeBase):
"""Simulate the behavior of bisect bots as they transition across the Skia
DEPS change."""
FAKE_REPOS_CLASS = FakeRepoSkiaDEPS
def setUp(self):
super(SkiaDEPSTransitionSmokeTest, self).setUp()
self.enabled = self.FAKE_REPOS.set_up_git() and self.FAKE_REPOS.set_up_svn()
def testSkiaDEPSChangeSVN(self):
if not self.enabled:
return
# Create an initial checkout:
# - Single checkout at the root.
# - Multiple checkouts in a shared subdirectory.
self.gclient(['config', '--spec',
'solutions=['
'{"name": "src",'
' "url": "' + self.svn_base + 'trunk/src/",'
'}]'])
checkout_path = os.path.join(self.root_dir, 'src')
skia = os.path.join(checkout_path, 'third_party', 'skia')
skia_gyp = os.path.join(skia, 'gyp')
skia_include = os.path.join(skia, 'include')
skia_src = os.path.join(skia, 'src')
gyp_svn_url = self.svn_base + 'skia/gyp'
include_svn_url = self.svn_base + 'skia/include'
src_svn_url = self.svn_base + 'skia/src'
skia_git_url = self.git_base + 'repo_1'
# Initial sync. Verify that we get the expected checkout.
res = self.gclient(['sync', '--deps', 'mac', '--revision', 'src@2'])
self.assertEqual(res[2], 0, 'Initial sync failed.')
self.assertEqual(gclient_scm.SVN.CaptureLocalInfo([], skia_gyp)['URL'],
gyp_svn_url)
self.assertEqual(gclient_scm.SVN.CaptureLocalInfo([], skia_include)['URL'],
include_svn_url)
self.assertEqual(gclient_scm.SVN.CaptureLocalInfo([], skia_src)['URL'],
src_svn_url)
# Try to sync the new DEPS. Verify that the sync fails without --force.
res = self.gclient(['sync', '--deps', 'mac', '--revision', 'src@3'])
self.assertEquals(res[2], 1, 'New DEPS sync succeeded unexpectedly.')
# Verify that the sync succeeds with --force. Verify that we have the
# expected merged checkout.
res = self.gclient(['sync', '--deps', 'mac', '--revision', 'src@3',
'--force'])
self.assertEqual(res[2], 0, 'DEPS change sync failed with --force.')
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia), skia_git_url)
# Sync again. Verify that we still have the expected merged checkout.
res = self.gclient(['sync', '--deps', 'mac', '--revision', 'src@3'])
self.assertEqual(res[2], 0, 'Subsequent sync failed.')
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia), skia_git_url)
# Sync back to the original DEPS. Verify that we get the original structure.
res = self.gclient(['sync', '--deps', 'mac', '--revision', 'src@2',
'--force'])
self.assertEqual(res[2], 0, 'Reverse sync failed.')
self.assertEqual(gclient_scm.SVN.CaptureLocalInfo([], skia_gyp)['URL'],
gyp_svn_url)
self.assertEqual(gclient_scm.SVN.CaptureLocalInfo([], skia_include)['URL'],
include_svn_url)
self.assertEqual(gclient_scm.SVN.CaptureLocalInfo([], skia_src)['URL'],
src_svn_url)
# Sync again. Verify that we still have the original structure.
res = self.gclient(['sync', '--deps', 'mac', '--revision', 'src@2'])
self.assertEqual(res[2], 0, 'Subsequent sync #2 failed.')
self.assertEqual(gclient_scm.SVN.CaptureLocalInfo([], skia_gyp)['URL'],
gyp_svn_url)
self.assertEqual(gclient_scm.SVN.CaptureLocalInfo([], skia_include)['URL'],
include_svn_url)
self.assertEqual(gclient_scm.SVN.CaptureLocalInfo([], skia_src)['URL'],
src_svn_url)
def testSkiaDEPSChangeGit(self):
if not self.enabled:
return
# Create an initial checkout:
# - Single checkout at the root.
# - Multiple checkouts in a shared subdirectory.
self.gclient(['config', '--spec',
'solutions=['
'{"name": "src",'
' "url": "' + self.git_base + 'repo_2",'
'}]'])
checkout_path = os.path.join(self.root_dir, 'src')
skia = os.path.join(checkout_path, 'third_party', 'skia')
skia_gyp = os.path.join(skia, 'gyp')
skia_include = os.path.join(skia, 'include')
skia_src = os.path.join(skia, 'src')
gyp_git_url = self.git_base + 'repo_3'
include_git_url = self.git_base + 'repo_4'
src_git_url = self.git_base + 'repo_5'
skia_git_url = self.FAKE_REPOS.git_base + 'repo_1'
pre_hash = self.githash('repo_2', 1)
post_hash = self.githash('repo_2', 2)
# Initial sync. Verify that we get the expected checkout.
res = self.gclient(['sync', '--deps', 'mac', '--revision',
'src@%s' % pre_hash])
self.assertEqual(res[2], 0, 'Initial sync failed.')
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia_gyp), gyp_git_url)
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia_include), include_git_url)
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia_src), src_git_url)
# Try to sync the new DEPS. Verify that the sync fails without --force.
res = self.gclient(['sync', '--deps', 'mac', '--revision',
'src@%s' % post_hash])
self.assertEquals(res[2], 1, 'New DEPS sync succeeded unexpectedly.')
# Verify that the sync succeeds with --force. Verify that we have the
# expected merged checkout.
res = self.gclient(['sync', '--deps', 'mac', '--revision',
'src@%s' % post_hash, '--force'])
self.assertEqual(res[2], 0, 'DEPS change sync failed with --force.')
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia), skia_git_url)
# Sync again. Verify that we still have the expected merged checkout.
res = self.gclient(['sync', '--deps', 'mac', '--revision',
'src@%s' % post_hash])
self.assertEqual(res[2], 0, 'Subsequent sync failed.')
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia), skia_git_url)
# Sync back to the original DEPS. Verify that we get the original structure.
res = self.gclient(['sync', '--deps', 'mac', '--revision',
'src@%s' % pre_hash, '--force'])
self.assertEqual(res[2], 0, 'Reverse sync failed.')
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia_gyp), gyp_git_url)
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia_include), include_git_url)
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia_src), src_git_url)
# Sync again. Verify that we still have the original structure.
res = self.gclient(['sync', '--deps', 'mac', '--revision',
'src@%s' % pre_hash])
self.assertEqual(res[2], 0, 'Subsequent sync #2 failed.')
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia_gyp), gyp_git_url)
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia_include), include_git_url)
self.assertEqual(gclient_scm.GIT.Capture(['config', 'remote.origin.url'],
skia_src), src_git_url)
class GClientSmokeFromCheckout(GClientSmokeBase):
# WebKit abuses this. It has a .gclient and a DEPS from a checkout.
def setUp(self):
......
......@@ -169,6 +169,18 @@ class RealGitSvnTest(fake_repos.FakeReposTestBase):
self._capture(['reset', '--hard', 'HEAD^'])
self.assertEquals(scm.GIT.GetGitSvnHeadRev(cwd=self.clone_dir), 1)
def testIsGitSvn(self):
if not self.enabled:
return
# Git-svn
self.assertTrue(scm.GIT.IsGitSvn(self.clone_dir))
# Pure git
git_dir = scm.os.path.join(self.FAKE_REPOS.git_root, 'repo_1')
self.assertFalse(scm.GIT.IsGitSvn(git_dir))
# Pure svn
svn_dir = scm.os.path.join(self.FAKE_REPOS.svn_checkout, 'trunk')
self.assertFalse(scm.GIT.IsGitSvn(svn_dir))
def testParseGitSvnSha1(self):
test_sha1 = 'a5c63ce8671922e5c59c0dea49ef4f9d4a3020c9'
expected_output = test_sha1 + '\n'
......
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