1515from pip ._internal .distributions import make_distribution_for_install_requirement
1616from pip ._internal .distributions .installed import InstalledDistribution
1717from pip ._internal .exceptions import (
18+ CacheEntryTypeHashNotSupported ,
19+ DependencyVcsHashNotSupported ,
1820 DirectoryUrlHashUnsupported ,
1921 HashMismatch ,
2022 HashUnpinned ,
2123 InstallationError ,
2224 MetadataInconsistent ,
25+ MutableVcsRefHashNotSupported ,
2326 NetworkConnectionError ,
2427 PreviousBuildDirError ,
2528 VcsHashUnsupported ,
2629)
2730from pip ._internal .index .package_finder import PackageFinder
2831from pip ._internal .metadata import BaseDistribution , get_metadata_distribution
29- from pip ._internal .models .direct_url import ArchiveInfo
32+ from pip ._internal .models .direct_url import ArchiveInfo , VcsInfo
3033from pip ._internal .models .link import Link
3134from pip ._internal .models .wheel import Wheel
3235from pip ._internal .network .download import BatchDownloader , Downloader
4144 direct_url_for_editable ,
4245 direct_url_from_link ,
4346)
44- from pip ._internal .utils .hashes import Hashes , MissingHashes
47+ from pip ._internal .utils .hashes import Hashes , MissingHashes , VcsHashes
4548from pip ._internal .utils .logging import indent_log
4649from pip ._internal .utils .misc import (
4750 display_path ,
@@ -72,10 +75,14 @@ def _get_prepared_distribution(
7275 return abstract_dist .get_metadata_distribution ()
7376
7477
75- def unpack_vcs_link (link : Link , location : str , verbosity : int ) -> None :
78+ def unpack_vcs_link (
79+ link : Link , location : str , verbosity : int , hashes : Optional [Hashes ] = None
80+ ) -> None :
7681 vcs_backend = vcs .get_backend_for_scheme (link .scheme )
7782 assert vcs_backend is not None
7883 vcs_backend .unpack (location , url = hide_url (link .url ), verbosity = verbosity )
84+ if hashes and not vcs_backend .is_immutable_rev_checkout (link .url , location ):
85+ raise MutableVcsRefHashNotSupported ()
7986
8087
8188class File :
@@ -152,7 +159,7 @@ def unpack_url(
152159 """
153160 # non-editable vcs urls
154161 if link .is_vcs :
155- unpack_vcs_link (link , location , verbosity = verbosity )
162+ unpack_vcs_link (link , location , verbosity = verbosity , hashes = hashes )
156163 return None
157164
158165 assert not link .is_existing_dir ()
@@ -335,6 +342,14 @@ def _get_linked_req_hashes(self, req: InstallRequirement) -> Hashes:
335342 # and raise some more informative errors than otherwise.
336343 # (For example, we can raise VcsHashUnsupported for a VCS URL
337344 # rather than HashMissing.)
345+
346+ # Check that --hash is not used with VCS and local directories direct URLs.
347+ if req .original_link :
348+ if req .original_link .is_vcs and req .hashes (trust_internet = False ):
349+ raise VcsHashUnsupported ()
350+ if req .original_link .is_existing_dir () and req .hashes (trust_internet = False ):
351+ raise DirectoryUrlHashUnsupported ()
352+
338353 if not self .require_hashes :
339354 return req .hashes (trust_internet = True )
340355
@@ -343,7 +358,9 @@ def _get_linked_req_hashes(self, req: InstallRequirement) -> Hashes:
343358 # report less-useful error messages for unhashable
344359 # requirements, complaining that there's no hash provided.
345360 if req .link .is_vcs :
346- raise VcsHashUnsupported ()
361+ if not req .user_supplied :
362+ raise DependencyVcsHashNotSupported ()
363+ return VcsHashes ()
347364 if req .link .is_existing_dir ():
348365 raise DirectoryUrlHashUnsupported ()
349366
@@ -559,24 +576,33 @@ def _prepare_linked_requirement(
559576 assert link .is_file
560577 # We need to verify hashes, and we have found the requirement in the cache
561578 # of locally built wheels.
562- if (
563- isinstance (req .download_info .info , ArchiveInfo )
564- and req .download_info .info .hashes
565- and hashes .has_one_of (req .download_info .info .hashes )
566- ):
567- # At this point we know the requirement was built from a hashable source
568- # artifact, and we verified that the cache entry's hash of the original
569- # artifact matches one of the hashes we expect. We don't verify hashes
570- # against the cached wheel, because the wheel is not the original.
579+ if isinstance (req .download_info .info , ArchiveInfo ):
580+ if req .download_info .info .hashes and hashes .has_one_of (
581+ req .download_info .info .hashes
582+ ):
583+ # At this point we know the requirement was built from a hashable
584+ # source artifact, and we verified that the cache entry's hash of
585+ # the original artifact matches one of the hashes we expect. We
586+ # don't verify hashes against the cached wheel, because the wheel is
587+ # not the original.
588+ hashes = None
589+ else :
590+ logger .warning (
591+ "The hashes of the source archive found in cache entry "
592+ "don't match, ignoring cached built wheel "
593+ "and re-downloading source."
594+ )
595+ req .link = req .cached_wheel_source_link
596+ link = req .link
597+ elif isinstance (req .download_info .info , VcsInfo ):
598+ if not req .user_supplied :
599+ raise DependencyVcsHashNotSupported ()
600+ # Don't verify hashes against the cached wheel: if it is in cache,
601+ # it means it was built from a URL referencing an immutable commit
602+ # hash.
571603 hashes = None
572604 else :
573- logger .warning (
574- "The hashes of the source archive found in cache entry "
575- "don't match, ignoring cached built wheel "
576- "and re-downloading source."
577- )
578- req .link = req .cached_wheel_source_link
579- link = req .link
605+ raise CacheEntryTypeHashNotSupported ()
580606
581607 self ._ensure_link_req_src_dir (req , parallel_builds )
582608
0 commit comments