11//! Provides fetcher for Yarn distributions
22
3+ use std:: env;
34use std:: fs:: File ;
4- use std:: path:: Path ;
5+ use std:: path:: { Path , PathBuf } ;
56
67use super :: super :: download_tool_error;
78use super :: super :: registry:: { find_unpack_dir, public_registry_package} ;
89use crate :: error:: { Context , ErrorKind , Fallible } ;
9- use crate :: fs:: { create_staging_dir, create_staging_file, rename} ;
10+ use crate :: fs:: { create_staging_dir, create_staging_file, rename, set_executable } ;
1011use crate :: hook:: ToolHooks ;
1112use crate :: layout:: volta_home;
1213use crate :: style:: { progress_bar, tool_version} ;
@@ -15,7 +16,7 @@ use crate::version::VersionSpec;
1516use archive:: { Archive , Tarball } ;
1617use fs_utils:: ensure_containing_dir_exists;
1718use log:: debug;
18- use semver:: Version ;
19+ use semver:: { Version , VersionReq } ;
1920
2021pub fn fetch ( version : & Version , hooks : Option < & ToolHooks < Yarn > > ) -> Fallible < ( ) > {
2122 let yarn_dir = volta_home ( ) ?. yarn_inventory_dir ( ) ;
@@ -79,11 +80,14 @@ fn unpack_archive(archive: Box<dyn Archive>, version: &Version) -> Fallible<()>
7980 version : version_string. clone ( ) ,
8081 } ) ?;
8182
83+ let unpack_dir = find_unpack_dir ( temp. path ( ) ) ?;
84+ // "bin/yarn" is not executable in the @yarnpkg/cli-dist package
85+ ensure_bin_is_executable ( & unpack_dir, "yarn" ) ?;
86+
8287 let dest = volta_home ( ) ?. yarn_image_dir ( & version_string) ;
8388 ensure_containing_dir_exists ( & dest)
8489 . with_context ( || ErrorKind :: ContainingDirError { path : dest. clone ( ) } ) ?;
8590
86- let unpack_dir = find_unpack_dir ( temp. path ( ) ) ?;
8791 rename ( unpack_dir, & dest) . with_context ( || ErrorKind :: SetupToolImageError {
8892 tool : "Yarn" . into ( ) ,
8993 version : version_string. clone ( ) ,
@@ -122,7 +126,19 @@ fn determine_remote_url(version: &Version, hooks: Option<&ToolHooks<Yarn>>) -> F
122126 let distro_file_name = Yarn :: archive_filename ( & version_str) ;
123127 hook. resolve ( version, & distro_file_name)
124128 }
125- _ => Ok ( public_registry_package ( "yarn" , & version_str) ) ,
129+ _ => {
130+ let matches_yarn_berry = VersionReq :: parse ( ">2" ) . unwrap ( ) ;
131+ if env:: var_os ( "VOLTA_FEATURE_YARN_3" ) . is_some ( ) && matches_yarn_berry. matches ( version)
132+ {
133+ Ok ( public_registry_package (
134+ "@yarnpkg/cli-dist" ,
135+ "cli-dist" ,
136+ & version_str,
137+ ) )
138+ } else {
139+ Ok ( public_registry_package ( "yarn" , "yarn" , & version_str) )
140+ }
141+ }
126142 }
127143}
128144
@@ -138,3 +154,8 @@ fn fetch_remote_distro(
138154 url,
139155 ) )
140156}
157+
158+ fn ensure_bin_is_executable ( unpack_dir : & PathBuf , tool : & str ) -> Fallible < ( ) > {
159+ let exec_path = unpack_dir. join ( "bin" ) . join ( tool) ;
160+ set_executable ( & exec_path) . with_context ( || ErrorKind :: SetToolExecutable { tool : tool. into ( ) } )
161+ }
0 commit comments