mirror of
https://chromium.googlesource.com/chromium/tools/depot_tools.git
synced 2026-01-11 18:51:29 +00:00
Re-re-land gclient deletion of mismatching checkouts again
Review URL: https://codereview.chromium.org/164053003 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@253616 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
239
gclient_scm.py
239
gclient_scm.py
@@ -302,9 +302,56 @@ class GitWrapper(SCMWrapper):
|
||||
# hash is also a tag, only make a distinction at checkout
|
||||
rev_type = "hash"
|
||||
|
||||
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 not managed:
|
||||
self._UpdateBranchHeads(options, fetch=False)
|
||||
self.UpdateSubmoduleConfig()
|
||||
print ('________ unmanaged solution; skipping %s' % self.relpath)
|
||||
return self._Capture(['rev-parse', '--verify', 'HEAD'])
|
||||
|
||||
needs_delete = False
|
||||
exists = os.path.exists(self.checkout_path)
|
||||
if exists and not os.path.exists(os.path.join(self.checkout_path, '.git')):
|
||||
needs_delete = True
|
||||
|
||||
# See if the url has changed (the unittests use git://foo for the url, let
|
||||
# that through).
|
||||
return_early = False
|
||||
if exists and not needs_delete:
|
||||
current_url = self._Capture(['config', 'remote.%s.url' % self.remote])
|
||||
# TODO(maruel): Delete url != 'git://foo' since it's just to make the
|
||||
# unit test pass. (and update the comment above)
|
||||
# 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 url != 'git://foo'):
|
||||
auto_fix = 'True'
|
||||
try:
|
||||
auto_fix = self._Capture(
|
||||
['config', 'remote.%s.gclient-auto-fix-url' % self.remote],
|
||||
cwd=self.checkout_path).strip()
|
||||
except subprocess2.CalledProcessError:
|
||||
pass
|
||||
if auto_fix in ('1', 'true', 'True', 'yes', 'Yes', 'y', 'Y'):
|
||||
print('_____ switching %s to a new upstream' % self.relpath)
|
||||
# Make sure it's clean
|
||||
self._CheckClean(rev_str)
|
||||
# Switch over to the new upstream
|
||||
self._Run(['remote', 'set-url', self.remote, url], options)
|
||||
self._FetchAndReset(revision, file_list, options)
|
||||
return_early = True
|
||||
|
||||
if (needs_delete and
|
||||
gclient_utils.enable_deletion_of_conflicting_checkouts()):
|
||||
if options.force:
|
||||
print('Conflicting directory found in %s. Removing.'
|
||||
% self.checkout_path)
|
||||
gclient_utils.rmtree(self.checkout_path)
|
||||
else:
|
||||
raise gclient_utils.Error('Conflicting directory found in %s. Please '
|
||||
'delete it or run with --force.'
|
||||
% self.checkout_path)
|
||||
|
||||
if not os.path.exists(self.checkout_path):
|
||||
self._Clone(revision, url, options)
|
||||
self.UpdateSubmoduleConfig()
|
||||
if file_list is not None:
|
||||
@@ -316,42 +363,6 @@ class GitWrapper(SCMWrapper):
|
||||
print('')
|
||||
return self._Capture(['rev-parse', '--verify', 'HEAD'])
|
||||
|
||||
if not managed:
|
||||
self._UpdateBranchHeads(options, fetch=False)
|
||||
self.UpdateSubmoduleConfig()
|
||||
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])
|
||||
return_early = False
|
||||
# TODO(maruel): Delete url != 'git://foo' since it's just to make the
|
||||
# unit test pass. (and update the comment above)
|
||||
# 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
|
||||
url != 'git://foo' and
|
||||
subprocess2.capture(
|
||||
['git', 'config', 'remote.%s.gclient-auto-fix-url' % self.remote],
|
||||
cwd=self.checkout_path).strip() != 'False'):
|
||||
print('_____ switching %s to a new upstream' % self.relpath)
|
||||
# Make sure it's clean
|
||||
self._CheckClean(rev_str)
|
||||
# Switch over to the new upstream
|
||||
self._Run(['remote', 'set-url', self.remote, url], options)
|
||||
self._FetchAndReset(revision, file_list, options)
|
||||
return_early = True
|
||||
|
||||
# Need to do this in the normal path as well as in the post-remote-switch
|
||||
# path.
|
||||
self._PossiblySwitchCache(url, options)
|
||||
@@ -625,7 +636,7 @@ class GitWrapper(SCMWrapper):
|
||||
elif rev.isdigit() and len(rev) < 7:
|
||||
# Handles an SVN rev. As an optimization, only verify an SVN revision as
|
||||
# [0-9]{1,6} for now to avoid making a network request.
|
||||
if scm.GIT.IsGitSvn(cwd=self.checkout_path):
|
||||
if scm.GIT.IsGitSvn(self.checkout_path):
|
||||
local_head = scm.GIT.GetGitSvnHeadRev(cwd=self.checkout_path)
|
||||
if not local_head or local_head < int(rev):
|
||||
try:
|
||||
@@ -1104,17 +1115,6 @@ 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
|
||||
|
||||
hg_path = os.path.join(self.checkout_path, '.hg')
|
||||
if os.path.exists(hg_path):
|
||||
print('________ found .hg directory; skipping %s' % self.relpath)
|
||||
return
|
||||
|
||||
if args:
|
||||
raise gclient_utils.Error("Unsupported argument(s): %s" % ",".join(args))
|
||||
|
||||
@@ -1140,21 +1140,86 @@ class SVNWrapper(SCMWrapper):
|
||||
forced_revision = False
|
||||
rev_str = ''
|
||||
|
||||
if not managed:
|
||||
print ('________ unmanaged solution; skipping %s' % self.relpath)
|
||||
return self.Svnversion()
|
||||
|
||||
# Get the existing scm url and the revision number of the current checkout.
|
||||
exists = os.path.exists(self.checkout_path)
|
||||
if exists and managed:
|
||||
needs_delete = False
|
||||
from_info = None
|
||||
|
||||
if exists:
|
||||
# If there's a git-svn checkout, verify that the svn-remote is correct.
|
||||
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 != base_url:
|
||||
needs_delete = True
|
||||
else:
|
||||
print('\n_____ %s looks like a git-svn checkout. Skipping.'
|
||||
% self.relpath)
|
||||
return # TODO(borenet): Get the svn revision number?
|
||||
|
||||
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:
|
||||
print 'Removing troublesome path %s' % self.checkout_path
|
||||
gclient_utils.rmtree(self.checkout_path)
|
||||
exists = False
|
||||
else:
|
||||
msg = ('Can\'t update/checkout %s if an unversioned directory is '
|
||||
'present. Delete the directory and try again.')
|
||||
raise gclient_utils.Error(msg % self.checkout_path)
|
||||
if gclient_utils.enable_deletion_of_conflicting_checkouts():
|
||||
needs_delete = True
|
||||
else: # TODO(borenet): Remove this once we can get rid of the guard.
|
||||
if options.reset and options.delete_unversioned_trees:
|
||||
print 'Removing troublesome path %s' % self.checkout_path
|
||||
gclient_utils.rmtree(self.checkout_path)
|
||||
exists = False
|
||||
else:
|
||||
msg = ('Can\'t update/checkout %s if an unversioned directory is '
|
||||
'present. Delete the directory and try again.')
|
||||
raise gclient_utils.Error(msg % self.checkout_path)
|
||||
|
||||
# Switch the checkout if necessary.
|
||||
if not needs_delete and from_info and from_info['URL'] != base_url:
|
||||
# The repository url changed, need to switch.
|
||||
try:
|
||||
to_info = scm.SVN.CaptureRemoteInfo(url)
|
||||
except (gclient_utils.Error, subprocess2.CalledProcessError):
|
||||
# The url is invalid or the server is not accessible, it's safer to bail
|
||||
# out right now.
|
||||
raise gclient_utils.Error('This url is unreachable: %s' % url)
|
||||
can_switch = ((from_info['Repository Root'] != to_info['Repository Root'])
|
||||
and (from_info['UUID'] == to_info['UUID']))
|
||||
if can_switch:
|
||||
print('\n_____ relocating %s to a new checkout' % self.relpath)
|
||||
# We have different roots, so check if we can switch --relocate.
|
||||
# Subversion only permits this if the repository UUIDs match.
|
||||
# Perform the switch --relocate, then rewrite the from_url
|
||||
# to reflect where we "are now." (This is the same way that
|
||||
# Subversion itself handles the metadata when switch --relocate
|
||||
# is used.) This makes the checks below for whether we
|
||||
# can update to a revision or have to switch to a different
|
||||
# branch work as expected.
|
||||
# TODO(maruel): TEST ME !
|
||||
command = ['switch', '--relocate',
|
||||
from_info['Repository Root'],
|
||||
to_info['Repository Root'],
|
||||
self.relpath]
|
||||
self._Run(command, options, cwd=self._root_dir)
|
||||
from_info['URL'] = from_info['URL'].replace(
|
||||
from_info['Repository Root'],
|
||||
to_info['Repository Root'])
|
||||
else:
|
||||
needs_delete = True
|
||||
|
||||
if (needs_delete and
|
||||
gclient_utils.enable_deletion_of_conflicting_checkouts()):
|
||||
if options.force:
|
||||
gclient_utils.rmtree(self.checkout_path)
|
||||
exists = False
|
||||
else:
|
||||
raise gclient_utils.Error('Conflicting directory found in %s. Please '
|
||||
'delete it or run with --force.'
|
||||
% self.checkout_path)
|
||||
|
||||
BASE_URLS = {
|
||||
'/chrome/trunk/src': 'gs://chromium-svn-checkout/chrome/',
|
||||
@@ -1232,10 +1297,6 @@ class SVNWrapper(SCMWrapper):
|
||||
self._RunAndGetFileList(command, options, file_list, self._root_dir)
|
||||
return self.Svnversion()
|
||||
|
||||
if not managed:
|
||||
print ('________ unmanaged solution; skipping %s' % self.relpath)
|
||||
return self.Svnversion()
|
||||
|
||||
if 'URL' not in from_info:
|
||||
raise gclient_utils.Error(
|
||||
('gclient is confused. Couldn\'t get the url for %s.\n'
|
||||
@@ -1277,53 +1338,6 @@ class SVNWrapper(SCMWrapper):
|
||||
revision = str(from_info_live['Revision'])
|
||||
rev_str = ' at %s' % revision
|
||||
|
||||
if from_info['URL'] != base_url:
|
||||
# The repository url changed, need to switch.
|
||||
try:
|
||||
to_info = scm.SVN.CaptureRemoteInfo(url)
|
||||
except (gclient_utils.Error, subprocess2.CalledProcessError):
|
||||
# The url is invalid or the server is not accessible, it's safer to bail
|
||||
# out right now.
|
||||
raise gclient_utils.Error('This url is unreachable: %s' % url)
|
||||
can_switch = ((from_info['Repository Root'] != to_info['Repository Root'])
|
||||
and (from_info['UUID'] == to_info['UUID']))
|
||||
if can_switch:
|
||||
print('\n_____ relocating %s to a new checkout' % self.relpath)
|
||||
# We have different roots, so check if we can switch --relocate.
|
||||
# Subversion only permits this if the repository UUIDs match.
|
||||
# Perform the switch --relocate, then rewrite the from_url
|
||||
# to reflect where we "are now." (This is the same way that
|
||||
# Subversion itself handles the metadata when switch --relocate
|
||||
# is used.) This makes the checks below for whether we
|
||||
# can update to a revision or have to switch to a different
|
||||
# branch work as expected.
|
||||
# TODO(maruel): TEST ME !
|
||||
command = ['switch', '--relocate',
|
||||
from_info['Repository Root'],
|
||||
to_info['Repository Root'],
|
||||
self.relpath]
|
||||
self._Run(command, options, cwd=self._root_dir)
|
||||
from_info['URL'] = from_info['URL'].replace(
|
||||
from_info['Repository Root'],
|
||||
to_info['Repository Root'])
|
||||
else:
|
||||
if not options.force and not options.reset:
|
||||
# Look for local modifications but ignore unversioned files.
|
||||
for status in scm.SVN.CaptureStatus(None, self.checkout_path):
|
||||
if status[0][0] != '?':
|
||||
raise gclient_utils.Error(
|
||||
('Can\'t switch the checkout to %s; UUID don\'t match and '
|
||||
'there is local changes in %s. Delete the directory and '
|
||||
'try again.') % (url, self.checkout_path))
|
||||
# Ok delete it.
|
||||
print('\n_____ switching %s to a new checkout' % self.relpath)
|
||||
gclient_utils.rmtree(self.checkout_path)
|
||||
# We need to checkout.
|
||||
command = ['checkout', url, self.checkout_path]
|
||||
command = self._AddAdditionalUpdateFlags(command, options, revision)
|
||||
self._RunAndGetFileList(command, options, file_list, self._root_dir)
|
||||
return self.Svnversion()
|
||||
|
||||
# If the provided url has a revision number that matches the revision
|
||||
# number of the existing directory, then we don't need to bother updating.
|
||||
if not options.force and str(from_info['Revision']) == revision:
|
||||
@@ -1393,9 +1407,6 @@ class SVNWrapper(SCMWrapper):
|
||||
if os.path.isdir(os.path.join(self.checkout_path, '.git')):
|
||||
print('________ found .git directory; skipping %s' % self.relpath)
|
||||
return
|
||||
if os.path.isdir(os.path.join(self.checkout_path, '.hg')):
|
||||
print('________ found .hg directory; skipping %s' % self.relpath)
|
||||
return
|
||||
if not options.force:
|
||||
raise gclient_utils.Error('Invalid checkout path, aborting')
|
||||
print(
|
||||
|
||||
@@ -10,6 +10,7 @@ import os
|
||||
import pipes
|
||||
import Queue
|
||||
import re
|
||||
import socket
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -25,6 +26,20 @@ RETRY_MAX = 3
|
||||
RETRY_INITIAL_SLEEP = 0.5
|
||||
|
||||
|
||||
def enable_deletion_of_conflicting_checkouts():
|
||||
"""Determines whether to enable new checkout deletion behavior.
|
||||
|
||||
Initially, enables the experimental functionality on a small set of
|
||||
bots.
|
||||
"""
|
||||
# TODO(borenet): Remove this hack as soon as we've verified that it
|
||||
# doesn't cause the bots to break.
|
||||
if not os.environ.get('CHROME_HEADLESS'):
|
||||
return False
|
||||
return socket.gethostname() in ('vm859-m1', 'BUILD1-M1',
|
||||
'vm630-m1.golo.chromium.org')
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
"""gclient exception class."""
|
||||
def __init__(self, msg, *args, **kwargs):
|
||||
|
||||
9
scm.py
9
scm.py
@@ -166,12 +166,15 @@ class GIT(object):
|
||||
return GIT.ShortBranchName(GIT.GetBranchRef(cwd))
|
||||
|
||||
@staticmethod
|
||||
def IsGitSvn(cwd):
|
||||
def IsGitSvn(checkout_root):
|
||||
"""Returns true if this repo looks like it's using git-svn."""
|
||||
# A git-svn checkout has a .git directory.
|
||||
if not os.path.exists(os.path.join(checkout_root, '.git')):
|
||||
return False
|
||||
# If you have any "svn-remote.*" config keys, we think you're using svn.
|
||||
try:
|
||||
GIT.Capture(['config', '--local', '--get-regexp', r'^svn-remote\.'],
|
||||
cwd=cwd)
|
||||
cwd=checkout_root)
|
||||
return True
|
||||
except subprocess2.CalledProcessError:
|
||||
return False
|
||||
@@ -408,7 +411,7 @@ class GIT(object):
|
||||
@staticmethod
|
||||
def GetSha1ForSvnRev(cwd, rev):
|
||||
"""Returns a corresponding git sha1 for a SVN revision."""
|
||||
if not GIT.IsGitSvn(cwd=cwd):
|
||||
if not GIT.IsGitSvn(cwd):
|
||||
return None
|
||||
try:
|
||||
output = GIT.Capture(['svn', 'find-rev', 'r' + str(rev)], cwd=cwd)
|
||||
|
||||
@@ -161,8 +161,6 @@ class SVNWrapperTestCase(BaseTestCase):
|
||||
|
||||
def testRunCommandException(self):
|
||||
options = self.Options(verbose=False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
|
||||
@@ -182,8 +180,6 @@ class SVNWrapperTestCase(BaseTestCase):
|
||||
gclient_scm.scm.SVN.Capture(['--version', '--quiet'], None
|
||||
).AndReturn('1.5.1')
|
||||
# It'll to a checkout instead.
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
|
||||
# Checkout.
|
||||
gclient_scm.os.path.exists(self.base_path).AndReturn(False)
|
||||
parent = gclient_scm.os.path.dirname(self.base_path)
|
||||
@@ -212,10 +208,7 @@ class SVNWrapperTestCase(BaseTestCase):
|
||||
gclient_scm.os.path.isdir(self.base_path).AndReturn(True)
|
||||
gclient_scm.os.path.isdir(join(self.base_path, '.svn')).AndReturn(False)
|
||||
gclient_scm.os.path.isdir(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.isdir(join(self.base_path, '.hg')).AndReturn(False)
|
||||
# Checkout.
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(self.base_path).AndReturn(False)
|
||||
parent = gclient_scm.os.path.dirname(self.base_path)
|
||||
gclient_scm.os.path.exists(parent).AndReturn(False)
|
||||
@@ -340,8 +333,6 @@ class SVNWrapperTestCase(BaseTestCase):
|
||||
file_info.url = self.url
|
||||
file_info.uuid = 'ABC'
|
||||
file_info.revision = 42
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
|
||||
# Checkout.
|
||||
gclient_scm.os.path.exists(self.base_path).AndReturn(False)
|
||||
parent = gclient_scm.os.path.dirname(self.base_path)
|
||||
@@ -373,8 +364,8 @@ class SVNWrapperTestCase(BaseTestCase):
|
||||
'UUID': 'ABC',
|
||||
'Revision': 42,
|
||||
}
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
|
||||
self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'IsGitSvn', True)
|
||||
gclient_scm.scm.GIT.IsGitSvn(self.base_path).AndReturn(False)
|
||||
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
|
||||
|
||||
# Checkout or update.
|
||||
@@ -419,8 +410,8 @@ class SVNWrapperTestCase(BaseTestCase):
|
||||
'UUID': 'ABC',
|
||||
'Revision': 42,
|
||||
}
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
|
||||
self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'IsGitSvn', True)
|
||||
gclient_scm.scm.GIT.IsGitSvn(self.base_path).AndReturn(False)
|
||||
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
|
||||
|
||||
# Checkout or update.
|
||||
@@ -455,8 +446,8 @@ class SVNWrapperTestCase(BaseTestCase):
|
||||
'UUID': 'ABC',
|
||||
'Revision': 42,
|
||||
}
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
|
||||
self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'IsGitSvn', True)
|
||||
gclient_scm.scm.GIT.IsGitSvn(self.base_path).AndReturn(False)
|
||||
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
|
||||
|
||||
# Checkout or update.
|
||||
@@ -521,8 +512,8 @@ class SVNWrapperTestCase(BaseTestCase):
|
||||
file_list=files_list)
|
||||
|
||||
# Now we fall back on scm.update().
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
|
||||
self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'IsGitSvn', True)
|
||||
gclient_scm.scm.GIT.IsGitSvn(self.base_path).AndReturn(False)
|
||||
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
|
||||
gclient_scm.scm.SVN._CaptureInfo([], dotted_path).AndReturn(file_info)
|
||||
gclient_scm.scm.SVN._CaptureInfo([file_info['URL']], None
|
||||
@@ -591,8 +582,8 @@ class SVNWrapperTestCase(BaseTestCase):
|
||||
file_list=files_list)
|
||||
|
||||
# Now we fall back on scm.update().
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
|
||||
self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'IsGitSvn', True)
|
||||
gclient_scm.scm.GIT.IsGitSvn(self.base_path).AndReturn(False)
|
||||
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
|
||||
gclient_scm.scm.SVN._CaptureInfo(
|
||||
[], join(self.base_path, ".")).AndReturn(file_info)
|
||||
@@ -627,8 +618,8 @@ class SVNWrapperTestCase(BaseTestCase):
|
||||
|
||||
# Now we fall back on scm.update().
|
||||
files_list = self.mox.CreateMockAnything()
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(False)
|
||||
self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'IsGitSvn', True)
|
||||
gclient_scm.scm.GIT.IsGitSvn(self.base_path).AndReturn(False)
|
||||
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
|
||||
gclient_scm.scm.SVN._CaptureInfo(
|
||||
[], join(self.base_path, '.')).AndReturn(file_info)
|
||||
@@ -644,31 +635,23 @@ class SVNWrapperTestCase(BaseTestCase):
|
||||
scm.updatesingle(options, ['DEPS'], files_list)
|
||||
self.checkstdout('\n_____ %s at 42\n' % self.relpath)
|
||||
|
||||
def testUpdateGit(self):
|
||||
def testUpdateGitSvn(self):
|
||||
options = self.Options(verbose=True)
|
||||
file_path = gclient_scm.os.path.join(self.root_dir, self.relpath, '.git')
|
||||
gclient_scm.os.path.exists(file_path).AndReturn(True)
|
||||
|
||||
gclient_scm.os.path.exists(self.base_path).AndReturn(True)
|
||||
self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'IsGitSvn', True)
|
||||
gclient_scm.scm.GIT.IsGitSvn(self.base_path).AndReturn(True)
|
||||
self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'Capture', True)
|
||||
gclient_scm.scm.GIT.Capture(['config', '--local', '--get',
|
||||
'svn-remote.svn.url'],
|
||||
cwd=self.base_path).AndReturn(self.url)
|
||||
self.mox.ReplayAll()
|
||||
scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
|
||||
relpath=self.relpath)
|
||||
file_list = []
|
||||
scm.update(options, self.args, file_list)
|
||||
scm.update(options, [], file_list)
|
||||
self.checkstdout(
|
||||
('________ found .git directory; skipping %s\n' % self.relpath))
|
||||
|
||||
def testUpdateHg(self):
|
||||
options = self.Options(verbose=True)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.git')).AndReturn(False)
|
||||
gclient_scm.os.path.exists(join(self.base_path, '.hg')).AndReturn(True)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
|
||||
relpath=self.relpath)
|
||||
file_list = []
|
||||
scm.update(options, self.args, file_list)
|
||||
self.checkstdout(
|
||||
('________ found .hg directory; skipping %s\n' % self.relpath))
|
||||
('\n_____ %s looks like a git-svn checkout. Skipping.\n' % self.relpath)
|
||||
)
|
||||
|
||||
def testGetUsableRevSVN(self):
|
||||
# pylint: disable=E1101
|
||||
@@ -1162,7 +1145,7 @@ class ManagedGitWrapperTestCaseMox(BaseTestCase):
|
||||
).AndReturn(True)
|
||||
|
||||
self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'IsGitSvn', True)
|
||||
gclient_scm.scm.GIT.IsGitSvn(cwd=self.base_path).MultipleTimes(
|
||||
gclient_scm.scm.GIT.IsGitSvn(self.base_path).MultipleTimes(
|
||||
).AndReturn(False)
|
||||
|
||||
gclient_scm.scm.os.path.isdir(self.base_path).AndReturn(True)
|
||||
@@ -1211,7 +1194,7 @@ class ManagedGitWrapperTestCaseMox(BaseTestCase):
|
||||
gclient_scm.scm.GIT.Capture(['fetch', 'origin'], cwd=self.base_path)
|
||||
|
||||
self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'IsGitSvn', True)
|
||||
gclient_scm.scm.GIT.IsGitSvn(cwd=self.base_path).MultipleTimes(
|
||||
gclient_scm.scm.GIT.IsGitSvn(self.base_path).MultipleTimes(
|
||||
).AndReturn(True)
|
||||
|
||||
self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'IsValidRevision', True)
|
||||
|
||||
@@ -109,9 +109,11 @@ class GClientSmokeBase(FakeReposTestBase):
|
||||
not re.match(
|
||||
r'_____ [^ ]+ : Attempting rebase onto [0-9a-f]+...',
|
||||
line) and
|
||||
not re.match(r'_____ [^ ]+ at [^ ]+', line)):
|
||||
# The two regexp above are a bit too broad, they are necessary only
|
||||
# for git checkouts.
|
||||
not re.match(r'_____ [^ ]+ at [^ ]+', line) and not
|
||||
re.match(
|
||||
r'_____ (.*) looks like a git-svn checkout. Skipping.',
|
||||
line)):
|
||||
# The regexp above are a bit too broad.
|
||||
self.fail(line)
|
||||
else:
|
||||
results.append([[match.group(1), match.group(2), match.group(3)]])
|
||||
@@ -776,7 +778,59 @@ class GClientSmokeSVN(GClientSmokeBase):
|
||||
|
||||
# Cripple src/third_party/foo and make sure gclient still succeeds.
|
||||
gclient_utils.rmtree(join(third_party, 'foo', '.svn'))
|
||||
self.assertEquals(0, self.gclient(cmd)[-1])
|
||||
self.assertEquals(0, self.gclient(cmd + ['--force'])[-1])
|
||||
|
||||
def testSkipGitSvn(self):
|
||||
# Check that gclient skips git-svn checkouts.
|
||||
if not self.enabled:
|
||||
return
|
||||
|
||||
# Create the .gclient file.
|
||||
svn_url = self.svn_base + 'trunk/src'
|
||||
self.gclient(['config', svn_url], cwd=self.root_dir)
|
||||
|
||||
# Create a git-svn checkout.
|
||||
# Use check_output to hide the output from the subprocess.
|
||||
subprocess2.check_output(['git', 'svn', 'clone', svn_url],
|
||||
cwd=self.root_dir)
|
||||
|
||||
# Ensure that gclient skips the git-svn checkout.
|
||||
stdout, stderr, rc = self.gclient(['sync', '--jobs', '1'])
|
||||
self.assertEquals(rc, 0)
|
||||
self.assertFalse(stderr)
|
||||
self.assertTrue('_____ src looks like a git-svn checkout. Skipping.'
|
||||
in stdout)
|
||||
self.checkBlock(stdout, [
|
||||
['running', self.root_dir],
|
||||
['running', os.path.join(self.root_dir, 'src', 'file', 'other')],
|
||||
['running', self.root_dir],
|
||||
['running', self.root_dir],
|
||||
['running', self.root_dir],
|
||||
['running', self.root_dir],
|
||||
['running', self.root_dir],
|
||||
])
|
||||
|
||||
# But, we still need the DEPS to be checked out...
|
||||
foo_dir = os.path.join(self.root_dir, 'src', 'third_party', 'foo')
|
||||
foo_rev = subprocess2.check_output(['svnversion', foo_dir]).strip()
|
||||
self.assertEquals(foo_rev, '1')
|
||||
|
||||
other_dir = os.path.join(self.root_dir, 'src', 'other')
|
||||
other_rev = subprocess2.check_output(['svnversion', other_dir]).strip()
|
||||
self.assertEquals(other_rev, '2')
|
||||
|
||||
# Verify that the DEPS are NOT skipped on a second update.
|
||||
stdout, stderr, rc = self.gclient(['sync', '--jobs', '1'])
|
||||
self.assertFalse(stderr)
|
||||
self.assertTrue('_____ src looks like a git-svn checkout. Skipping.'
|
||||
in stdout)
|
||||
self.assertFalse(
|
||||
'_____ src/other looks like a git-svn checkout. Skipping.' in stdout,
|
||||
'Non git-svn checkout is incorrectly skipped.')
|
||||
self.assertFalse(
|
||||
'_____ src/third_party/foo looks like a git-svn checkout. Skipping.'
|
||||
in stdout,
|
||||
'Non git-svn checkout is incorrectly skipped.')
|
||||
|
||||
|
||||
class GClientSmokeSVNTransitive(GClientSmokeBase):
|
||||
@@ -1062,7 +1116,7 @@ class GClientSmokeGIT(GClientSmokeBase):
|
||||
self.assertTree(tree)
|
||||
|
||||
# Pre-DEPS hooks run when syncing with --nohooks.
|
||||
self.gclient(['sync', '--deps', 'mac', '--nohooks',
|
||||
self.gclient(['sync', '--deps', 'mac', '--nohooks', '--force',
|
||||
'--revision', 'src@' + self.githash('repo_5', 2)])
|
||||
tree = self.mangle_git_tree(('repo_5@2', 'src'),
|
||||
('repo_1@2', 'src/repo1'),
|
||||
@@ -1074,7 +1128,7 @@ class GClientSmokeGIT(GClientSmokeBase):
|
||||
os.remove(join(self.root_dir, 'src', 'git_pre_deps_hooked'))
|
||||
|
||||
# Pre-DEPS hooks don't run with --noprehooks
|
||||
self.gclient(['sync', '--deps', 'mac', '--noprehooks',
|
||||
self.gclient(['sync', '--deps', 'mac', '--noprehooks', '--force',
|
||||
'--revision', 'src@' + self.githash('repo_5', 2)])
|
||||
tree = self.mangle_git_tree(('repo_5@2', 'src'),
|
||||
('repo_1@2', 'src/repo1'),
|
||||
@@ -1396,6 +1450,78 @@ class GClientSmokeBoth(GClientSmokeBase):
|
||||
|
||||
self.assertEquals(sorted(entries), sorted(expected))
|
||||
|
||||
if gclient_utils.enable_deletion_of_conflicting_checkouts():
|
||||
def testDeleteConflictingCheckout(self):
|
||||
if not self.enabled:
|
||||
return
|
||||
|
||||
# Create an initial svn checkout.
|
||||
self.gclient(['config', '--spec',
|
||||
'solutions=['
|
||||
'{"name": "src",'
|
||||
' "url": "' + self.svn_base + 'trunk/src"},'
|
||||
']'
|
||||
])
|
||||
results = self.gclient(['sync', '--deps', 'mac'])
|
||||
self.assertEqual(results[2], 0, 'Sync failed!')
|
||||
|
||||
# Verify that we have the expected svn checkout.
|
||||
results = self.gclient(['revinfo', '--deps', 'mac'])
|
||||
actual = results[0].splitlines()
|
||||
expected = [
|
||||
'src: %strunk/src' % self.svn_base,
|
||||
'src/file/other: File("%strunk/other/DEPS")' % self.svn_base,
|
||||
'src/other: %strunk/other' % self.svn_base,
|
||||
'src/third_party/foo: %strunk/third_party/foo@1' % self.svn_base,
|
||||
]
|
||||
self.assertEquals(actual, expected)
|
||||
|
||||
# Change the desired checkout to git.
|
||||
self.gclient(['config', '--spec',
|
||||
'solutions=['
|
||||
'{"name": "src",'
|
||||
' "url": "' + self.git_base + 'repo_1"},'
|
||||
']'
|
||||
])
|
||||
|
||||
# Verify that the sync succeeds with --force.
|
||||
results = self.gclient(['sync', '--deps', 'mac', '--force'])
|
||||
self.assertEqual(results[2], 0, 'Sync failed!')
|
||||
|
||||
# Verify that we got the desired git checkout.
|
||||
results = self.gclient(['revinfo', '--deps', 'mac'])
|
||||
actual = results[0].splitlines()
|
||||
expected = [
|
||||
'src: %srepo_1' % self.git_base,
|
||||
'src/repo2: %srepo_2@%s' % (self.git_base,
|
||||
self.githash('repo_2', 1)[:7]),
|
||||
'src/repo2/repo_renamed: %srepo_3' % self.git_base,
|
||||
]
|
||||
self.assertEquals(actual, expected)
|
||||
|
||||
# Change the desired checkout back to svn.
|
||||
self.gclient(['config', '--spec',
|
||||
'solutions=['
|
||||
'{"name": "src",'
|
||||
' "url": "' + self.svn_base + 'trunk/src"},'
|
||||
']'
|
||||
])
|
||||
|
||||
# Verify that the sync succeeds.
|
||||
results = self.gclient(['sync', '--deps', 'mac', '--force'])
|
||||
self.assertEqual(results[2], 0, 'Sync failed!')
|
||||
|
||||
# Verify that we have the expected svn checkout.
|
||||
results = self.gclient(['revinfo', '--deps', 'mac'])
|
||||
actual = results[0].splitlines()
|
||||
expected = [
|
||||
'src: %strunk/src' % self.svn_base,
|
||||
'src/file/other: File("%strunk/other/DEPS")' % self.svn_base,
|
||||
'src/other: %strunk/other' % self.svn_base,
|
||||
'src/third_party/foo: %strunk/third_party/foo@1' % self.svn_base,
|
||||
]
|
||||
self.assertEquals(actual, expected)
|
||||
|
||||
|
||||
class GClientSmokeFromCheckout(GClientSmokeBase):
|
||||
# WebKit abuses this. It has a .gclient and a DEPS from a checkout.
|
||||
|
||||
@@ -29,7 +29,9 @@ class GclientUtilsUnittest(GclientUtilBase):
|
||||
def testMembersChanged(self):
|
||||
members = [
|
||||
'Annotated', 'AutoFlush', 'CheckCallAndFilter', 'CommandToStr',
|
||||
'CheckCallAndFilterAndHeader', 'Error', 'ExecutionQueue', 'FileRead',
|
||||
'CheckCallAndFilterAndHeader',
|
||||
'enable_deletion_of_conflicting_checkouts', # TODO(borenet): Remove!
|
||||
'Error', 'ExecutionQueue', 'FileRead',
|
||||
'FileWrite', 'FindFileUpwards', 'FindGclientRoot',
|
||||
'GetGClientRootAndEntries', 'GetEditor', 'GetExeSuffix',
|
||||
'GetMacWinOrLinux', 'GitFilter', 'IsDateRevision', 'MakeDateRevision',
|
||||
@@ -39,7 +41,9 @@ class GclientUtilsUnittest(GclientUtilBase):
|
||||
'GCLIENT_CHILDREN_LOCK', 'GClientChildren', 'SplitUrlRevision',
|
||||
'SyntaxErrorToError', 'UpgradeToHttps', 'Wrapper', 'WorkItem',
|
||||
'codecs', 'lockedmethod', 'logging', 'os', 'pipes', 'Queue', 're',
|
||||
'rmtree', 'safe_makedirs', 'safe_rename', 'stat', 'subprocess',
|
||||
'rmtree', 'safe_makedirs', 'safe_rename',
|
||||
'socket', # TODO(borenet): Remove!
|
||||
'stat', 'subprocess',
|
||||
'subprocess2', 'sys', 'tempfile', 'threading', 'time', 'urlparse',
|
||||
|
||||
]
|
||||
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user