Fix unpinned version to track upstream.

This is a serious bug, if a version is unpinned, it would become stuck at
whatever a local branch 'master' may point to. This is extremely bad when a
pinned dependency is unpinned on purpose, for example on a canary master. We
reproduced this problem on the chromium.swarm master by setting a custom_vars
swarming_revision to '', which then stopped syncing at the expected
origin/master commit but instead got stuck to what happened to be a local master
branch.

This happens on git dependencies if the main solution is using svn. This doesn't
happen on git checkouts using .DEPS.git due to bug 323233.

The issue looks like:
________ running 'git reset --hard HEAD' in '/path/src/tools/swarming_client'
HEAD is now at 4727bd5 Some commit
Checked out revision d908a546e28d1e9f85f5690cf6c3a080f06ba711

Note that HEAD and what is checked out do not match.

Also reduce the hardcoding of 'origin' by creating a variable named 'remote'.

R=petermayo@chromium.org
BUG=322961

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@237332 0039d316-1c4b-4281-b951-d872f2087c98
experimental/szager/collated-output
maruel@chromium.org 12 years ago
parent ff7ea00a6e
commit 1a60dca731

@ -188,6 +188,7 @@ class GitFilter(object):
class GitWrapper(SCMWrapper): class GitWrapper(SCMWrapper):
"""Wrapper for Git""" """Wrapper for Git"""
name = 'git' name = 'git'
remote = 'origin'
cache_dir = None cache_dir = None
# If a given cache is used in a solution more than once, prevent multiple # If a given cache is used in a solution more than once, prevent multiple
@ -230,7 +231,7 @@ class GitWrapper(SCMWrapper):
""" """
def diff(self, options, _args, _file_list): def diff(self, options, _args, _file_list):
merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) merge_base = self._Capture(['merge-base', 'HEAD', self.remote])
self._Run(['diff', merge_base], options) self._Run(['diff', merge_base], options)
def pack(self, _options, _args, _file_list): def pack(self, _options, _args, _file_list):
@ -240,7 +241,7 @@ class GitWrapper(SCMWrapper):
The patch file is generated from a diff of the merge base of HEAD and The patch file is generated from a diff of the merge base of HEAD and
its upstream branch. its upstream branch.
""" """
merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) merge_base = self._Capture(['merge-base', 'HEAD', self.remote])
gclient_utils.CheckCallAndFilter( gclient_utils.CheckCallAndFilter(
['git', 'diff', merge_base], ['git', 'diff', merge_base],
cwd=self.checkout_path, cwd=self.checkout_path,
@ -280,7 +281,7 @@ class GitWrapper(SCMWrapper):
self._UpdateBranchHeads(options, fetch=False) self._UpdateBranchHeads(options, fetch=False)
fetch_cmd = [ fetch_cmd = [
'-c', 'core.deltaBaseCacheLimit=2g', 'fetch', 'origin', '--prune'] '-c', 'core.deltaBaseCacheLimit=2g', 'fetch', self.remote, '--prune']
self._Run(fetch_cmd + quiet, options, retry=True) self._Run(fetch_cmd + quiet, options, retry=True)
self._Run(['reset', '--hard', revision] + quiet, options) self._Run(['reset', '--hard', revision] + quiet, options)
self.UpdateSubmoduleConfig() self.UpdateSubmoduleConfig()
@ -301,7 +302,8 @@ class GitWrapper(SCMWrapper):
self._CheckMinVersion("1.6.6") self._CheckMinVersion("1.6.6")
default_rev = "refs/heads/master" # If a dependency is not pinned, track the default remote branch.
default_rev = 'refs/remotes/%s/master' % self.remote
url, deps_revision = gclient_utils.SplitUrlRevision(self.url) url, deps_revision = gclient_utils.SplitUrlRevision(self.url)
rev_str = "" rev_str = ""
revision = deps_revision revision = deps_revision
@ -337,9 +339,9 @@ class GitWrapper(SCMWrapper):
if revision.startswith('refs/'): if revision.startswith('refs/'):
rev_type = "branch" rev_type = "branch"
elif revision.startswith('origin/'): elif revision.startswith(self.remote + '/'):
# For compatability with old naming, translate 'origin' to 'refs/heads' # For compatibility with old naming, translate 'origin' to 'refs/heads'
revision = revision.replace('origin/', 'refs/heads/') revision = revision.replace(self.remote + '/', 'refs/heads/')
rev_type = "branch" rev_type = "branch"
else: else:
# hash is also a tag, only make a distinction at checkout # hash is also a tag, only make a distinction at checkout
@ -375,7 +377,7 @@ class GitWrapper(SCMWrapper):
# See if the url has changed (the unittests use git://foo for the url, let # See if the url has changed (the unittests use git://foo for the url, let
# that through). # that through).
current_url = self._Capture(['config', 'remote.origin.url']) current_url = self._Capture(['config', 'remote.%s.url' % self.remote])
return_early = False return_early = False
# TODO(maruel): Delete url != 'git://foo' since it's just to make the # TODO(maruel): Delete url != 'git://foo' since it's just to make the
# unit test pass. (and update the comment above) # unit test pass. (and update the comment above)
@ -385,13 +387,13 @@ class GitWrapper(SCMWrapper):
if (current_url != url and if (current_url != url and
url != 'git://foo' and url != 'git://foo' and
subprocess2.capture( subprocess2.capture(
['git', 'config', 'remote.origin.gclient-auto-fix-url'], ['git', 'config', 'remote.%s.gclient-auto-fix-url' % self.remote],
cwd=self.checkout_path).strip() != 'False'): cwd=self.checkout_path).strip() != 'False'):
print('_____ switching %s to a new upstream' % self.relpath) print('_____ switching %s to a new upstream' % self.relpath)
# Make sure it's clean # Make sure it's clean
self._CheckClean(rev_str) self._CheckClean(rev_str)
# Switch over to the new upstream # Switch over to the new upstream
self._Run(['remote', 'set-url', 'origin', url], options) self._Run(['remote', 'set-url', self.remote, url], options)
self._FetchAndReset(revision, file_list, options) self._FetchAndReset(revision, file_list, options)
return_early = True return_early = True
@ -473,7 +475,7 @@ class GitWrapper(SCMWrapper):
# Can't find a merge-base since we don't know our upstream. That makes # Can't find a merge-base since we don't know our upstream. That makes
# this command VERY likely to produce a rebase failure. For now we # this command VERY likely to produce a rebase failure. For now we
# assume origin is our upstream since that's what the old behavior was. # assume origin is our upstream since that's what the old behavior was.
upstream_branch = 'origin' upstream_branch = self.remote
if options.revision or deps_revision: if options.revision or deps_revision:
upstream_branch = revision upstream_branch = revision
self._AttemptRebase(upstream_branch, files, options, self._AttemptRebase(upstream_branch, files, options,
@ -484,9 +486,9 @@ class GitWrapper(SCMWrapper):
self._AttemptRebase(upstream_branch, files, options, self._AttemptRebase(upstream_branch, files, options,
newbase=revision, printed_path=printed_path) newbase=revision, printed_path=printed_path)
printed_path = True printed_path = True
elif revision.replace('heads', 'remotes/origin') != upstream_branch: elif revision.replace('heads', 'remotes/' + self.remote) != upstream_branch:
# case 4 # case 4
new_base = revision.replace('heads', 'remotes/origin') new_base = revision.replace('heads', 'remotes/' + self.remote)
if not printed_path: if not printed_path:
print('\n_____ %s%s' % (self.relpath, rev_str)) print('\n_____ %s%s' % (self.relpath, rev_str))
switch_error = ("Switching upstream branch from %s to %s\n" switch_error = ("Switching upstream branch from %s to %s\n"
@ -613,7 +615,7 @@ class GitWrapper(SCMWrapper):
if not deps_revision: if not deps_revision:
deps_revision = default_rev deps_revision = default_rev
if deps_revision.startswith('refs/heads/'): if deps_revision.startswith('refs/heads/'):
deps_revision = deps_revision.replace('refs/heads/', 'origin/') deps_revision = deps_revision.replace('refs/heads/', self.remote + '/')
if file_list is not None: if file_list is not None:
files = self._Capture(['diff', deps_revision, '--name-only']).split() files = self._Capture(['diff', deps_revision, '--name-only']).split()
@ -637,7 +639,7 @@ class GitWrapper(SCMWrapper):
print(('\n________ couldn\'t run status in %s:\n' print(('\n________ couldn\'t run status in %s:\n'
'The directory does not exist.') % self.checkout_path) 'The directory does not exist.') % self.checkout_path)
else: else:
merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) merge_base = self._Capture(['merge-base', 'HEAD', self.remote])
self._Run(['diff', '--name-status', merge_base], options) self._Run(['diff', '--name-status', merge_base], options)
if file_list is not None: if file_list is not None:
files = self._Capture(['diff', '--name-only', merge_base]).split() files = self._Capture(['diff', '--name-only', merge_base]).split()
@ -695,7 +697,7 @@ class GitWrapper(SCMWrapper):
else: else:
# May exist in origin, but we don't have it yet, so fetch and look # May exist in origin, but we don't have it yet, so fetch and look
# again. # again.
scm.GIT.Capture(['fetch', 'origin'], cwd=self.checkout_path) scm.GIT.Capture(['fetch', self.remote], cwd=self.checkout_path)
if scm.GIT.IsValidRevision(cwd=self.checkout_path, rev=rev): if scm.GIT.IsValidRevision(cwd=self.checkout_path, rev=rev):
sha1 = rev sha1 = rev
@ -807,7 +809,7 @@ class GitWrapper(SCMWrapper):
# to relax this restriction in the future to allow for smarter cache # to relax this restriction in the future to allow for smarter cache
# repo update schemes (such as pulling the same repo, but from a # repo update schemes (such as pulling the same repo, but from a
# different host). # different host).
existing_url = self._Capture(['config', 'remote.origin.url'], existing_url = self._Capture(['config', 'remote.%s.url' % self.remote],
cwd=folder) cwd=folder)
assert self._NormalizeGitURL(existing_url) == self._NormalizeGitURL(url) assert self._NormalizeGitURL(existing_url) == self._NormalizeGitURL(url)
@ -874,8 +876,8 @@ class GitWrapper(SCMWrapper):
print( print(
('Checked out %s to a detached HEAD. Before making any commits\n' ('Checked out %s to a detached HEAD. Before making any commits\n'
'in this repo, you should use \'git checkout <branch>\' to switch to\n' 'in this repo, you should use \'git checkout <branch>\' to switch to\n'
'an existing branch or use \'git checkout origin -b <branch>\' to\n' 'an existing branch or use \'git checkout %s -b <branch>\' to\n'
'create a new branch for your work.') % revision) 'create a new branch for your work.') % (revision, self.remote))
def _AttemptRebase(self, upstream, files, options, newbase=None, def _AttemptRebase(self, upstream, files, options, newbase=None,
branch=None, printed_path=False): branch=None, printed_path=False):
@ -1024,12 +1026,12 @@ class GitWrapper(SCMWrapper):
def _UpdateBranchHeads(self, options, fetch=False): def _UpdateBranchHeads(self, options, fetch=False):
"""Adds, and optionally fetches, "branch-heads" refspecs if requested.""" """Adds, and optionally fetches, "branch-heads" refspecs if requested."""
if hasattr(options, 'with_branch_heads') and options.with_branch_heads: if hasattr(options, 'with_branch_heads') and options.with_branch_heads:
config_cmd = ['config', 'remote.origin.fetch', config_cmd = ['config', 'remote.%s.fetch' % self.remote,
'+refs/branch-heads/*:refs/remotes/branch-heads/*', '+refs/branch-heads/*:refs/remotes/branch-heads/*',
'^\\+refs/branch-heads/\\*:.*$'] '^\\+refs/branch-heads/\\*:.*$']
self._Run(config_cmd, options) self._Run(config_cmd, options)
if fetch: if fetch:
fetch_cmd = ['-c', 'core.deltaBaseCacheLimit=2g', 'fetch', 'origin'] fetch_cmd = ['-c', 'core.deltaBaseCacheLimit=2g', 'fetch', self.remote]
if options.verbose: if options.verbose:
fetch_cmd.append('--verbose') fetch_cmd.append('--verbose')
self._Run(fetch_cmd, options, retry=True) self._Run(fetch_cmd, options, retry=True)

@ -800,12 +800,16 @@ from :3
gclient_scm.SVNWrapper.BinaryExists = staticmethod(lambda : True) gclient_scm.SVNWrapper.BinaryExists = staticmethod(lambda : True)
def tearDown(self): def tearDown(self):
StdoutCheck.tearDown(self) try:
TestCaseUtils.tearDown(self) rmtree(self.root_dir)
unittest.TestCase.tearDown(self) StdoutCheck.tearDown(self)
rmtree(self.root_dir) TestCaseUtils.tearDown(self)
gclient_scm.GitWrapper.BinaryExists = self._original_GitBinaryExists unittest.TestCase.tearDown(self)
gclient_scm.SVNWrapper.BinaryExists = self._original_SVNBinaryExists finally:
# TODO(maruel): Use auto_stub.TestCase.
gclient_scm.GitWrapper.BinaryExists = self._original_GitBinaryExists
gclient_scm.SVNWrapper.BinaryExists = self._original_SVNBinaryExists
class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): class ManagedGitWrapperTestCase(BaseGitWrapperTestCase):
def testDir(self): def testDir(self):
@ -824,6 +828,7 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase):
'pack', 'pack',
'UpdateSubmoduleConfig', 'UpdateSubmoduleConfig',
'relpath', 'relpath',
'remote',
'revert', 'revert',
'revinfo', 'revinfo',
'runhooks', 'runhooks',
@ -1039,7 +1044,7 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase):
'Fix the conflict and run gclient again.\n' 'Fix the conflict and run gclient again.\n'
'See \'man git-rebase\' for details.\n') 'See \'man git-rebase\' for details.\n')
self.assertRaisesError(exception, scm.update, options, (), []) self.assertRaisesError(exception, scm.update, options, (), [])
exception = ('\n____ . at refs/heads/master\n' exception = ('\n____ . at refs/remotes/origin/master\n'
'\tYou have unstaged changes.\n' '\tYou have unstaged changes.\n'
'\tPlease commit, stash, or reset.\n') '\tPlease commit, stash, or reset.\n')
self.assertRaisesError(exception, scm.update, options, (), []) self.assertRaisesError(exception, scm.update, options, (), [])

Loading…
Cancel
Save