Fix issue #5624: installing a Git ref for installs after the first.

This commit is contained in:
Chris Jerdonek 2018-07-17 09:36:48 -07:00
parent 63684d7e4d
commit d5af777d0d
7 changed files with 42 additions and 32 deletions

1
news/5624.bugfix Normal file
View File

@ -0,0 +1 @@
Fix installing a Git ref for installs after the first.

View File

@ -295,7 +295,7 @@ class VersionControl(object):
"""
raise NotImplementedError
def update(self, dest, rev_options):
def update(self, dest, url, rev_options):
"""
Update an already-existing repo to the given ``rev_options``.
@ -345,7 +345,7 @@ class VersionControl(object):
self.repo_name,
rev_display,
)
self.update(dest, rev_options)
self.update(dest, url, rev_options)
else:
logger.info('Skipping because already up-to-date.')
return

View File

@ -62,7 +62,7 @@ class Bazaar(VersionControl):
def switch(self, dest, url, rev_options):
self.run_command(['switch', url], cwd=dest)
def update(self, dest, rev_options):
def update(self, dest, url, rev_options):
cmd_args = ['pull', '-q'] + rev_options.to_args()
self.run_command(cmd_args, cwd=dest)

View File

@ -117,11 +117,10 @@ class Git(VersionControl):
return refs.get(branch_ref) or refs.get(tag_ref)
def check_rev_options(self, dest, rev_options):
"""Check the revision options before checkout.
Returns a new RevOptions object for the SHA1 of the branch or tag
if found.
def resolve_revision(self, dest, url, rev_options):
"""
Resolve a revision to a new RevOptions object with the SHA1 of the
branch, tag, or ref if found.
Args:
rev_options: a RevOptions object.
@ -139,6 +138,19 @@ class Git(VersionControl):
"Did not find branch or tag '%s', assuming revision or ref.",
rev,
)
if not rev.startswith('refs/'):
return rev_options
# If it looks like a ref, we have to fetch it explicitly.
self.run_command(
['fetch', '-q', url] + rev_options.to_args(),
cwd=dest,
)
# Change the revision to the SHA of the ref we fetched
sha = self.get_revision(dest, rev='FETCH_HEAD')
rev_options = rev_options.make_new(sha)
return rev_options
def is_commit_id_equal(self, dest, name):
@ -164,20 +176,12 @@ class Git(VersionControl):
if rev_options.rev:
# Then a specific revision was requested.
rev_options = self.check_rev_options(dest, rev_options)
rev_options = self.resolve_revision(dest, url, rev_options)
# Only do a checkout if the current commit id doesn't match
# the requested revision.
if not self.is_commit_id_equal(dest, rev_options.rev):
rev = rev_options.rev
# Only fetch the revision if it's a ref
if rev.startswith('refs/'):
self.run_command(
['fetch', '-q', url] + rev_options.to_args(),
cwd=dest,
)
# Change the revision to the SHA of the ref we fetched
rev = 'FETCH_HEAD'
self.run_command(['checkout', '-q', rev], cwd=dest)
cmd_args = ['checkout', '-q'] + rev_options.to_args()
self.run_command(cmd_args, cwd=dest)
#: repo may contain submodules
self.update_submodules(dest)
@ -189,7 +193,7 @@ class Git(VersionControl):
self.update_submodules(dest)
def update(self, dest, rev_options):
def update(self, dest, url, rev_options):
# First fetch changes from the default remote
if self.get_git_version() >= parse_version('1.9.0'):
# fetch tags in addition to everything else
@ -197,7 +201,7 @@ class Git(VersionControl):
else:
self.run_command(['fetch', '-q'], cwd=dest)
# Then reset to wanted revision (maybe even origin/master)
rev_options = self.check_rev_options(dest, rev_options)
rev_options = self.resolve_revision(dest, url, rev_options)
cmd_args = ['reset', '--hard', '-q'] + rev_options.to_args()
self.run_command(cmd_args, cwd=dest)
#: update submodules
@ -218,9 +222,11 @@ class Git(VersionControl):
url = found_remote.split(' ')[1]
return url.strip()
def get_revision(self, location):
def get_revision(self, location, rev=None):
if rev is None:
rev = 'HEAD'
current_rev = self.run_command(
['rev-parse', 'HEAD'], show_stdout=False, cwd=location,
['rev-parse', rev], show_stdout=False, cwd=location,
)
return current_rev.strip()

View File

@ -59,7 +59,7 @@ class Mercurial(VersionControl):
cmd_args = ['update', '-q'] + rev_options.to_args()
self.run_command(cmd_args, cwd=dest)
def update(self, dest, rev_options):
def update(self, dest, url, rev_options):
self.run_command(['pull', '-q'], cwd=dest)
cmd_args = ['update', '-q'] + rev_options.to_args()
self.run_command(cmd_args, cwd=dest)

View File

@ -57,7 +57,7 @@ class Subversion(VersionControl):
cmd_args = ['switch'] + rev_options.to_args() + [url, dest]
self.run_command(cmd_args)
def update(self, dest, rev_options):
def update(self, dest, url, rev_options):
cmd_args = ['update'] + rev_options.to_args() + [dest]
self.run_command(cmd_args)

View File

@ -108,37 +108,40 @@ def test_git_get_src_requirements(git, dist):
@patch('pip._internal.vcs.git.Git.get_revision_sha')
def test_git_check_rev_options_ref_exists(get_sha_mock):
def test_git_resolve_revision_rev_exists(get_sha_mock):
get_sha_mock.return_value = '123456'
git = Git()
rev_options = git.make_rev_options('develop')
new_options = git.check_rev_options('.', rev_options)
url = 'git+https://git.example.com'
new_options = git.resolve_revision('.', url, rev_options)
assert new_options.rev == '123456'
@patch('pip._internal.vcs.git.Git.get_revision_sha')
def test_git_check_rev_options_ref_not_found(get_sha_mock):
def test_git_resolve_revision_rev_not_found(get_sha_mock):
get_sha_mock.return_value = None
git = Git()
rev_options = git.make_rev_options('develop')
new_options = git.check_rev_options('.', rev_options)
url = 'git+https://git.example.com'
new_options = git.resolve_revision('.', url, rev_options)
assert new_options.rev == 'develop'
@patch('pip._internal.vcs.git.Git.get_revision_sha')
def test_git_check_rev_options_not_found_warning(get_sha_mock, caplog):
def test_git_resolve_revision_not_found_warning(get_sha_mock, caplog):
get_sha_mock.return_value = None
git = Git()
url = 'git+https://git.example.com'
sha = 40 * 'a'
rev_options = git.make_rev_options(sha)
new_options = git.check_rev_options('.', rev_options)
new_options = git.resolve_revision('.', url, rev_options)
assert new_options.rev == sha
rev_options = git.make_rev_options(sha[:6])
new_options = git.check_rev_options('.', rev_options)
new_options = git.resolve_revision('.', url, rev_options)
assert new_options.rev == 'aaaaaa'
# Check that a warning got logged only for the abbreviated hash.