Cache wheels built from immutable Git requirements

Cache wheels that are built from Git requirements
that contain an immutable revision (i.e. a sha).
This commit is contained in:
Stéphane Bidoul (ACSONE) 2019-08-10 12:54:16 +02:00
parent f5eba4f726
commit 9cad519521
No known key found for this signature in database
GPG Key ID: BCAB2555446B5B92
6 changed files with 54 additions and 2 deletions

View File

@ -573,6 +573,9 @@ and use any packages found there. This is disabled via the same
of that is not part of the pip API. As of 7.0, pip makes a subdirectory for
each sdist that wheels are built from and places the resulting wheels inside.
As of version 20.0, pip also caches wheels when building from an immutable Git
reference (i.e. a commit hash).
Pip attempts to choose the best wheels from those built in preference to
building a new wheel. Note that this means when a package has both optional
C extensions and builds ``py`` tagged wheels when the C extension can't be built

2
news/6640.feature Normal file
View File

@ -0,0 +1,2 @@
Cache wheels built from Git requirements that are considered immutable,
because they point to a commit hash.

View File

@ -12,7 +12,7 @@ from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._vendor.six.moves.urllib import request as urllib_request
from pip._internal.exceptions import BadCommand
from pip._internal.utils.misc import display_path
from pip._internal.utils.misc import display_path, hide_url
from pip._internal.utils.subprocess import make_command
from pip._internal.utils.temp_dir import TempDirectory
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
@ -59,6 +59,13 @@ class Git(VersionControl):
def get_base_rev_args(rev):
return [rev]
def is_immutable_rev_checkout(self, url, dest):
# type: (str, str) -> bool
_, rev_options = self.get_url_rev_options(hide_url(url))
if not rev_options.rev:
return False
return self.is_commit_id_equal(dest, rev_options.rev)
def get_git_version(self):
VERSION_PFX = 'git version '
version = self.run_command(['version'], show_stdout=False)

View File

@ -329,6 +329,20 @@ class VersionControl(object):
"""
raise NotImplementedError
def is_immutable_rev_checkout(self, url, dest):
# type: (str, str) -> bool
"""
Return true if the commit hash checked out at dest matches
the revision in url.
Always return False, if the VCS does not support immutable commit
hashes.
This method does not check if there are local uncommitted changes
in dest after checkout, as pip currently has no use case for that.
"""
return False
@classmethod
def make_rev_options(cls, rev=None, extra_args=None):
# type: (Optional[str], Optional[CommandArgs]) -> RevOptions

View File

@ -52,6 +52,7 @@ from pip._internal.utils.typing import MYPY_CHECK_RUNNING
from pip._internal.utils.ui import open_spinner
from pip._internal.utils.unpacking import unpack_file
from pip._internal.utils.urls import path_to_url
from pip._internal.vcs import vcs
if MYPY_CHECK_RUNNING:
from typing import (
@ -838,7 +839,15 @@ def should_cache(
return False
if req.link and req.link.is_vcs:
# VCS checkout. Build wheel just for this run.
# VCS checkout. Build wheel just for this run
# unless it points to an immutable commit hash in which
# case it can be cached.
assert not req.editable
assert req.source_dir
vcs_backend = vcs.get_backend_for_scheme(req.link.scheme)
assert vcs_backend
if vcs_backend.is_immutable_rev_checkout(req.link.url, req.source_dir):
return True
return False
link = req.link

View File

@ -221,3 +221,20 @@ def test_is_commit_id_equal(script):
assert not Git.is_commit_id_equal(version_pkg_path, 'abc123')
# Also check passing a None value.
assert not Git.is_commit_id_equal(version_pkg_path, None)
def test_is_immutable_rev_checkout(script):
version_pkg_path = _create_test_package(script)
commit = script.run(
'git', 'rev-parse', 'HEAD',
cwd=version_pkg_path
).stdout.strip()
assert Git().is_immutable_rev_checkout(
"git+https://g.c/o/r@" + commit, version_pkg_path
)
assert not Git().is_immutable_rev_checkout(
"git+https://g.c/o/r", version_pkg_path
)
assert not Git().is_immutable_rev_checkout(
"git+https://g.c/o/r@master", version_pkg_path
)