@@ -17,7 +17,7 @@ use crate::ops::{self, CompileFilter, CompileOptions};
1717use crate :: sources:: PathSource ;
1818use crate :: util:: errors:: CargoResult ;
1919use crate :: util:: interning:: InternedString ;
20- use crate :: util:: Config ;
20+ use crate :: util:: { Config , OptVersionReq } ;
2121use crate :: util:: { FileLock , Filesystem } ;
2222
2323/// On-disk tracking for which package installed which binary.
@@ -522,25 +522,6 @@ pub fn path_source(source_id: SourceId, config: &Config) -> CargoResult<PathSour
522522 Ok ( PathSource :: new ( & path, source_id, config) )
523523}
524524
525- fn is_package_name_a_git_url ( package_name : & InternedString ) -> bool {
526- if let Ok ( url) = Url :: parse ( package_name) {
527- if let Some ( domain) = url. domain ( ) {
528- // REVIEW
529- // Are there any other git services without "git"
530- // in the domain?
531- // bitbucket?
532- // Is it possible to ask the cargo/crates team for
533- // some stats where crates projects are currently hosted on
534- return domain. contains ( "git" ) ;
535- }
536- }
537- false
538- }
539-
540- fn was_git_url_miscategorised_as_a_registry_dep ( dep : & Dependency ) -> bool {
541- return dep. source_id ( ) . is_registry ( ) && is_package_name_a_git_url ( & dep. package_name ( ) ) ;
542- }
543-
544525/// Gets a Package based on command-line requirements.
545526pub fn select_dep_pkg < T > (
546527 source : & mut T ,
@@ -566,47 +547,115 @@ where
566547 Poll :: Pending => source. block_until_ready ( ) ?,
567548 }
568549 } ;
569- match deps. iter ( ) . map ( |p| p. package_id ( ) ) . max ( ) {
570- Some ( pkgid) => {
571- let pkg = Box :: new ( source) . download_now ( pkgid, config) ?;
572- Ok ( pkg)
550+ if let Some ( pkgid) = deps. iter ( ) . map ( |p| p. package_id ( ) ) . max ( ) {
551+ let pkg = Box :: new ( source) . download_now ( pkgid, config) ?;
552+ Ok ( pkg)
553+ } else {
554+ let spe = SelectPackageError :: new ( dep, source) ;
555+ bail ! ( anyhow:: Error :: from( spe) )
556+ }
557+ }
558+
559+ struct YankedInfo {
560+ package_name : InternedString ,
561+ source_id : SourceId ,
562+ }
563+
564+ struct PackageNotFound {
565+ package_name : InternedString ,
566+ source_id : SourceId ,
567+ // REVIEW make it a reference or is cloning ok?
568+ version_req : OptVersionReq ,
569+ }
570+
571+ enum SelectPackageError {
572+ /// Return when the Package had been yanked from the Registry
573+ Yanked ( YankedInfo ) ,
574+ // Return when someone accidentally passed a git(hub|lab|ea) URL as the package name
575+ UrlTreatedAsPackageName ( PackageNotFound ) ,
576+ // Catch-all variant for all other errors
577+ CouldntFindInRegistry ( PackageNotFound ) ,
578+ }
579+
580+ fn is_package_name_a_git_url ( package_name : & InternedString ) -> bool {
581+ if let Ok ( url) = Url :: parse ( package_name) {
582+ if let Some ( domain) = url. domain ( ) {
583+ // REVIEW
584+ // Are there any other git services without "git"
585+ // in the domain?
586+ // bitbucket?
587+ // Is it possible to ask the cargo/crates team for
588+ // some stats where crates projects are currently hosted on
589+ return domain. contains ( "git" ) ;
573590 }
574- None => {
575- let is_yanked: bool = if dep. version_req ( ) . is_exact ( ) {
576- let version: String = dep. version_req ( ) . to_string ( ) ;
577- PackageId :: new ( dep. package_name ( ) , & version[ 1 ..] , source. source_id ( ) )
578- . map_or ( false , |pkg_id| source. is_yanked ( pkg_id) . unwrap_or ( false ) )
579- } else {
580- false
581- } ;
582- if is_yanked {
583- bail ! (
584- "cannot install package `{}`, it has been yanked from {}" ,
585- dep. package_name( ) ,
586- source. source_id( )
587- )
591+ }
592+ false
593+ }
594+
595+ fn was_git_url_miscategorised_as_a_registry_dep ( dep : & Dependency ) -> bool {
596+ return dep. source_id ( ) . is_registry ( ) && is_package_name_a_git_url ( & dep. package_name ( ) ) ;
597+ }
598+
599+ impl SelectPackageError {
600+ fn new < T > ( dep : Dependency , source : & mut T ) -> Self
601+ where
602+ T : Source ,
603+ {
604+ let is_yanked: bool = if dep. version_req ( ) . is_exact ( ) {
605+ let version: String = dep. version_req ( ) . to_string ( ) ;
606+ PackageId :: new ( dep. package_name ( ) , & version[ 1 ..] , source. source_id ( ) )
607+ . map_or ( false , |pkg_id| source. is_yanked ( pkg_id) . unwrap_or ( false ) )
608+ } else {
609+ false
610+ } ;
611+ if is_yanked {
612+ SelectPackageError :: Yanked ( YankedInfo {
613+ package_name : dep. package_name ( ) ,
614+ source_id : source. source_id ( ) ,
615+ } )
616+ } else {
617+ if was_git_url_miscategorised_as_a_registry_dep ( & dep) {
618+ SelectPackageError :: UrlTreatedAsPackageName ( PackageNotFound {
619+ package_name : dep. package_name ( ) ,
620+ source_id : source. source_id ( ) ,
621+ version_req : dep. version_req ( ) . clone ( ) ,
622+ } )
588623 } else {
589- if was_git_url_miscategorised_as_a_registry_dep ( & dep) {
590- bail ! (
591- "could not find `{}` in {} with version `{}`. Try adding `--git {}`" ,
592- dep. package_name( ) ,
593- source. source_id( ) ,
594- dep. version_req( ) ,
595- dep. package_name( ) ,
596- )
597- } else {
598- bail ! (
599- "could not find `{}` in {} with version `{}`" ,
600- dep. package_name( ) ,
601- source. source_id( ) ,
602- dep. version_req( ) ,
603- )
604- }
624+ SelectPackageError :: CouldntFindInRegistry ( PackageNotFound {
625+ package_name : dep. package_name ( ) ,
626+ source_id : source. source_id ( ) ,
627+ version_req : dep. version_req ( ) . clone ( ) ,
628+ } )
605629 }
606630 }
607631 }
608632}
609633
634+ impl From < SelectPackageError > for anyhow:: Error {
635+ fn from ( err : SelectPackageError ) -> Self {
636+ match err {
637+ SelectPackageError :: Yanked ( info) => anyhow:: anyhow!(
638+ "cannot install package `{}`, it has been yanked from {}" ,
639+ info. package_name,
640+ info. source_id
641+ ) ,
642+ SelectPackageError :: UrlTreatedAsPackageName ( pkg_not_found) => anyhow:: anyhow!(
643+ "could not find `{}` in {} with version `{}`. Try adding `--git {}`" ,
644+ pkg_not_found. package_name,
645+ pkg_not_found. source_id,
646+ pkg_not_found. version_req,
647+ pkg_not_found. package_name,
648+ ) ,
649+ SelectPackageError :: CouldntFindInRegistry ( pkg_not_found) => anyhow:: anyhow!(
650+ "could not find `{}` in {} with version `{}`" ,
651+ pkg_not_found. package_name,
652+ pkg_not_found. source_id,
653+ pkg_not_found. version_req,
654+ ) ,
655+ }
656+ }
657+ }
658+
610659pub fn select_pkg < T , F > (
611660 source : & mut T ,
612661 dep : Option < Dependency > ,
0 commit comments