Skip to content

Commit 4092707

Browse files
authored
Merge pull request #4676 from cjerdonek/issue-4675-fix-check-version
Address issue #4675: fix Git.check_version()
2 parents c66ecc7 + cf23b06 commit 4092707

File tree

9 files changed

+48
-35
lines changed

9 files changed

+48
-35
lines changed

docs/reference/pip_install.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,10 @@ Passing branch names, a commit hash or a tag name is possible like so::
374374
[-e] git://git.example.com/[email protected]#egg=MyProject
375375
[-e] git://git.example.com/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709#egg=MyProject
376376

377+
When passing a commit hash, specifying a full hash is preferable to a partial
378+
hash because a full hash allows pip to operate more efficiently (e.g. by
379+
making fewer network calls).
380+
377381
Mercurial
378382
~~~~~~~~~
379383

news/4675.bugfix

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix an issue where ``pip install -e`` on a Git url would fail to update if
2+
a branch or tag name is specified that happens to match the prefix of the
3+
current ``HEAD`` commit hash.

src/pip/_internal/vcs/__init__.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -279,13 +279,13 @@ def update(self, dest, rev_options):
279279
"""
280280
raise NotImplementedError
281281

282-
def check_version(self, dest, rev_options):
282+
def is_commit_id_equal(self, dest, name):
283283
"""
284-
Return True if the version is identical to what exists and
285-
doesn't need to be updated.
284+
Return whether the id of the current commit equals the given name.
286285
287286
Args:
288-
rev_options: a RevOptions object.
287+
dest: the repository directory.
288+
name: a string name.
289289
"""
290290
raise NotImplementedError
291291

@@ -313,7 +313,7 @@ def check_destination(self, dest, url, rev_options):
313313
display_path(dest),
314314
url,
315315
)
316-
if not self.check_version(dest, rev_options):
316+
if not self.is_commit_id_equal(dest, rev_options.rev):
317317
logger.info(
318318
'Updating %s %s%s',
319319
display_path(dest),
@@ -405,8 +405,7 @@ def get_url(self, location):
405405

406406
def get_revision(self, location):
407407
"""
408-
Return the current revision of the files at location
409-
Used in get_info
408+
Return the current commit id of the files at the given location.
410409
"""
411410
raise NotImplementedError
412411

src/pip/_internal/vcs/bazaar.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def get_src_requirement(self, dist, location):
104104
current_rev = self.get_revision(location)
105105
return '%s@%s#egg=%s' % (repo, current_rev, egg_project_name)
106106

107-
def check_version(self, dest, rev_options):
107+
def is_commit_id_equal(self, dest, name):
108108
"""Always assume the versions don't match"""
109109
return False
110110

src/pip/_internal/vcs/git.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,19 @@ def check_rev_options(self, dest, rev_options):
119119

120120
return rev_options
121121

122-
def check_version(self, dest, rev_options):
122+
def is_commit_id_equal(self, dest, name):
123123
"""
124-
Compare the current sha to the ref. ref may be a branch or tag name,
125-
but current rev will always point to a sha. This means that a branch
126-
or tag will never compare as True. So this ultimately only matches
127-
against exact shas.
124+
Return whether the current commit hash equals the given name.
128125
129126
Args:
130-
rev_options: a RevOptions object.
127+
dest: the repository directory.
128+
name: a string name.
131129
"""
132-
return self.get_revision(dest).startswith(rev_options.arg_rev)
130+
if not name:
131+
# Then avoid an unnecessary subprocess call.
132+
return False
133+
134+
return self.get_revision(dest) == name
133135

134136
def switch(self, dest, url, rev_options):
135137
self.run_command(['config', 'remote.origin.url', url], cwd=dest)
@@ -164,10 +166,11 @@ def obtain(self, dest):
164166

165167
if rev:
166168
rev_options = self.check_rev_options(dest, rev_options)
167-
# Only do a checkout if rev_options differs from HEAD
168-
if not self.check_version(dest, rev_options):
169+
# Only do a checkout if the current commit id doesn't match
170+
# the requested revision.
171+
if not self.is_commit_id_equal(dest, rev_options.rev):
169172
cmd_args = ['fetch', '-q', url] + rev_options.to_args()
170-
self.run_command(cmd_args, cwd=dest,)
173+
self.run_command(cmd_args, cwd=dest)
171174
self.run_command(
172175
['checkout', '-q', 'FETCH_HEAD'],
173176
cwd=dest,

src/pip/_internal/vcs/mercurial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def get_src_requirement(self, dist, location):
9797
current_rev_hash = self.get_revision_hash(location)
9898
return '%s@%s#egg=%s' % (repo, current_rev_hash, egg_project_name)
9999

100-
def check_version(self, dest, rev_options):
100+
def is_commit_id_equal(self, dest, name):
101101
"""Always assume the versions don't match"""
102102
return False
103103

src/pip/_internal/vcs/subversion.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ def get_src_requirement(self, dist, location):
217217
rev = self.get_revision(location)
218218
return 'svn+%s@%s#egg=%s' % (repo, rev, egg_project_name)
219219

220-
def check_version(self, dest, rev_options):
220+
def is_commit_id_equal(self, dest, name):
221221
"""Always assume the versions don't match"""
222222
return False
223223

tests/functional/test_install_vcs_git.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,24 @@ def test_get_short_refs_should_ignore_no_branch(script):
5858
assert result['branch0.1'] == commit, result
5959

6060

61-
def call_check_version(vcs, path, rev):
62-
rev_options = vcs.make_rev_options(rev)
63-
return vcs.check_version(path, rev_options)
64-
65-
6661
@pytest.mark.network
67-
def test_check_version(script):
62+
def test_is_commit_id_equal(script):
63+
"""
64+
Test Git.is_commit_id_equal().
65+
"""
6866
version_pkg_path = _create_test_package(script)
6967
script.run('git', 'branch', 'branch0.1', cwd=version_pkg_path)
7068
commit = script.run(
7169
'git', 'rev-parse', 'HEAD',
7270
cwd=version_pkg_path
7371
).stdout.strip()
7472
git = Git()
75-
assert call_check_version(git, version_pkg_path, commit)
76-
assert call_check_version(git, version_pkg_path, commit[:7])
77-
assert not call_check_version(git, version_pkg_path, 'branch0.1')
78-
assert not call_check_version(git, version_pkg_path, 'abc123')
73+
assert git.is_commit_id_equal(version_pkg_path, commit)
74+
assert not git.is_commit_id_equal(version_pkg_path, commit[:7])
75+
assert not git.is_commit_id_equal(version_pkg_path, 'branch0.1')
76+
assert not git.is_commit_id_equal(version_pkg_path, 'abc123')
77+
# Also check passing a None value.
78+
assert not git.is_commit_id_equal(version_pkg_path, None)
7979

8080

8181
@patch('pip._internal.vcs.git.Git.get_short_refs')

tests/unit/test_vcs.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,19 @@ def test_git_get_src_requirements(git, dist):
118118
])
119119

120120

121-
@pytest.mark.parametrize('ref,result', (
121+
@pytest.mark.parametrize('rev_name,result', (
122122
('5547fa909e83df8bd743d3978d6667497983a4b7', True),
123-
('5547fa909', True),
123+
('5547fa909', False),
124+
('5678', False),
124125
('abc123', False),
125126
('foo', False),
127+
(None, False),
126128
))
127-
def test_git_check_version(git, ref, result):
128-
rev_options = git.make_rev_options(ref)
129-
assert git.check_version('foo', rev_options) is result
129+
def test_git_is_commit_id_equal(git, rev_name, result):
130+
"""
131+
Test Git.is_commit_id_equal().
132+
"""
133+
assert git.is_commit_id_equal('/path', rev_name) is result
130134

131135

132136
def test_translate_egg_surname():

0 commit comments

Comments
 (0)