11//! Provides resolution of Yarn requirements into specific versions
22
3+ use std:: env;
4+
35use super :: super :: registry:: {
4- public_registry_index, PackageDetails , PackageIndex , RawPackageMetadata ,
5- NPM_ABBREVIATED_ACCEPT_HEADER ,
6+ fetch_public_index, public_registry_index, PackageDetails , PackageIndex ,
67} ;
78use super :: super :: registry_fetch_error;
89use super :: metadata:: { RawYarnIndex , YarnIndex } ;
@@ -12,7 +13,6 @@ use crate::session::Session;
1213use crate :: style:: progress_spinner;
1314use crate :: tool:: Yarn ;
1415use crate :: version:: { parse_version, VersionSpec , VersionTag } ;
15- use attohttpc:: header:: ACCEPT ;
1616use attohttpc:: Response ;
1717use log:: debug;
1818use semver:: { Version , VersionReq } ;
@@ -69,23 +69,30 @@ fn resolve_semver(matching: VersionReq, hooks: Option<&ToolHooks<Yarn>>) -> Fall
6969 }
7070}
7171
72- fn fetch_yarn_index ( ) -> Fallible < ( String , PackageIndex ) > {
73- let url = public_registry_index ( "yarn" ) ;
74- let spinner = progress_spinner ( format ! ( "Fetching public registry: {}" , url) ) ;
75- let metadata: RawPackageMetadata = attohttpc:: get ( & url)
76- . header ( ACCEPT , NPM_ABBREVIATED_ACCEPT_HEADER )
77- . send ( )
78- . and_then ( Response :: error_for_status)
79- . and_then ( Response :: json)
80- . with_context ( registry_fetch_error ( "Yarn" , & url) ) ?;
81-
82- spinner. finish_and_clear ( ) ;
83- Ok ( ( url, metadata. into ( ) ) )
72+ fn fetch_yarn_index ( package : & str ) -> Fallible < ( String , PackageIndex ) > {
73+ let url = public_registry_index ( package) ;
74+ fetch_public_index ( url, "Yarn" )
8475}
8576
8677fn resolve_custom_tag ( tag : String ) -> Fallible < Version > {
87- let ( url, mut index) = fetch_yarn_index ( ) ?;
78+ if env:: var_os ( "VOLTA_FEATURE_YARN_3" ) . is_some ( ) {
79+ // first try yarn2+, which uses "@yarnpkg/cli-dist" instead of "yarn"
80+ let ( url, mut index) = fetch_yarn_index ( "@yarnpkg/cli-dist" ) ?;
8881
82+ if let Some ( version) = index. tags . remove ( & tag) {
83+ debug ! ( "Found yarn@{} matching tag '{}' from {}" , version, tag, url) ;
84+ if version. major == 2 {
85+ return Err ( ErrorKind :: Yarn2NotSupported . into ( ) ) ;
86+ }
87+ return Ok ( version) ;
88+ }
89+ debug ! (
90+ "Did not find yarn matching tag '{}' from @yarnpkg/cli-dist" ,
91+ tag
92+ ) ;
93+ }
94+
95+ let ( url, mut index) = fetch_yarn_index ( "yarn" ) ?;
8996 match index. tags . remove ( & tag) {
9097 Some ( version) => {
9198 debug ! ( "Found yarn@{} matching tag '{}' from {}" , version, tag, url) ;
@@ -109,7 +116,40 @@ fn resolve_latest_legacy(url: String) -> Fallible<Version> {
109116}
110117
111118fn resolve_semver_from_registry ( matching : VersionReq ) -> Fallible < Version > {
112- let ( url, index) = fetch_yarn_index ( ) ?;
119+ if env:: var_os ( "VOLTA_FEATURE_YARN_3" ) . is_some ( ) {
120+ // first try yarn2+, which uses "@yarnpkg/cli-dist" instead of "yarn"
121+ let ( url, index) = fetch_yarn_index ( "@yarnpkg/cli-dist" ) ?;
122+ let matching_entries: Vec < PackageDetails > = index
123+ . entries
124+ . into_iter ( )
125+ . filter ( |PackageDetails { version, .. } | matching. matches ( version) )
126+ . collect ( ) ;
127+
128+ if !matching_entries. is_empty ( ) {
129+ let details_opt = matching_entries
130+ . iter ( )
131+ . find ( |PackageDetails { version, .. } | version. major >= 3 ) ;
132+
133+ match details_opt {
134+ Some ( details) => {
135+ debug ! (
136+ "Found yarn@{} matching requirement '{}' from {}" ,
137+ details. version, matching, url
138+ ) ;
139+ return Ok ( details. version . clone ( ) ) ;
140+ }
141+ None => {
142+ return Err ( ErrorKind :: Yarn2NotSupported . into ( ) ) ;
143+ }
144+ }
145+ }
146+ debug ! (
147+ "Did not find yarn matching requirement '{}' from {}" ,
148+ matching, url
149+ ) ;
150+ }
151+
152+ let ( url, index) = fetch_yarn_index ( "yarn" ) ?;
113153
114154 let details_opt = index
115155 . entries
@@ -124,6 +164,7 @@ fn resolve_semver_from_registry(matching: VersionReq) -> Fallible<Version> {
124164 ) ;
125165 Ok ( details. version )
126166 }
167+ // at this point Yarn is not found in either registry
127168 None => Err ( ErrorKind :: YarnVersionNotFound {
128169 matching : matching. to_string ( ) ,
129170 }
0 commit comments