From fcd90301f756c83a28096c77dab3d0ebba8bc668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Mon, 7 Jul 2025 23:12:04 +0200 Subject: [PATCH 1/2] Adds a way to disable Volta for Yarn in subprocesses --- crates/volta-core/src/run/yarn.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/crates/volta-core/src/run/yarn.rs b/crates/volta-core/src/run/yarn.rs index 86d36b13d..a2dcaf208 100644 --- a/crates/volta-core/src/run/yarn.rs +++ b/crates/volta-core/src/run/yarn.rs @@ -19,18 +19,20 @@ use crate::session::{ActivityKind, Session}; pub(super) fn command(args: &[OsString], session: &mut Session) -> Fallible { session.add_event_start(ActivityKind::Yarn); // Don't re-evaluate the context or global install interception if this is a recursive call - let platform = match env::var_os(RECURSION_ENV_VAR) { - Some(_) => None, - None => { - if let CommandArg::Global(cmd) = CommandArg::for_yarn(args) { - // For globals, only intercept if the default platform exists - if let Some(default_platform) = session.default_platform()? { - return cmd.executor(default_platform); - } - } - Platform::current(session)? + let platform = if env::var_os(RECURSION_ENV_VAR).is_some() { + None + } else if env::var_os("VOLTA_SKIP_YARN") { + None + } else { + if let CommandArg::Global(cmd) = CommandArg::for_yarn(args) { + // For globals, only intercept if the default platform exists + if let Some(default_platform) = session.default_platform()? { + return cmd.executor(default_platform); + } } + + Platform::current(session)? }; Ok(ToolCommand::new("yarn", args, platform, ToolKind::Yarn).into()) From 11400fe7686f83c855989eebf2a6270e933bc5b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Mon, 7 Jul 2025 23:39:59 +0200 Subject: [PATCH 2/2] Implements VOLTA_FEATURE_YARN=0 --- Cargo.lock | 14 ++++++++++++-- crates/volta-core/src/lib.rs | 7 +++++++ crates/volta-core/src/platform/image.rs | 9 ++++++--- crates/volta-core/src/platform/mod.rs | 8 +++++--- crates/volta-core/src/run/mod.rs | 15 +++++++++++++-- crates/volta-core/src/run/yarn.rs | 22 ++++++++++------------ crates/volta-core/src/tool/mod.rs | 11 ++++++++--- 7 files changed, 61 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e1402e365..2a602b450 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1657,7 +1657,7 @@ dependencies = [ "volta-core", "volta-migrate", "which", - "winreg", + "winreg 0.53.0", ] [[package]] @@ -1701,7 +1701,7 @@ dependencies = [ "volta-layout", "walkdir", "which", - "winreg", + "winreg 0.55.0", ] [[package]] @@ -2015,6 +2015,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winreg" +version = "0.55.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" +dependencies = [ + "cfg-if", + "windows-sys 0.59.0", +] + [[package]] name = "winsafe" version = "0.0.19" diff --git a/crates/volta-core/src/lib.rs b/crates/volta-core/src/lib.rs index 54ff743f7..c60e1afa0 100644 --- a/crates/volta-core/src/lib.rs +++ b/crates/volta-core/src/lib.rs @@ -1,5 +1,7 @@ //! The main implementation crate for the core of Volta. +use std::{env, ffi::OsString}; + mod command; pub mod error; pub mod event; @@ -22,3 +24,8 @@ pub mod toolchain; pub mod version; const VOLTA_FEATURE_PNPM: &str = "VOLTA_FEATURE_PNPM"; +const VOLTA_FEATURE_YARN: &str = "VOLTA_FEATURE_YARN"; + +pub fn is_yarn_enabled() -> bool { + env::var_os(VOLTA_FEATURE_YARN) != Some(OsString::from("0")) +} diff --git a/crates/volta-core/src/platform/image.rs b/crates/volta-core/src/platform/image.rs index 7882fa862..0d4e839ec 100644 --- a/crates/volta-core/src/platform/image.rs +++ b/crates/volta-core/src/platform/image.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use super::{build_path_error, Sourced}; use crate::error::{Context, Fallible}; +use crate::is_yarn_enabled; use crate::layout::volta_home; use crate::tool::load_default_npm_version; use node_semver::Version; @@ -34,9 +35,11 @@ impl Image { bins.push(home.pnpm_image_bin_dir(&pnpm_str)); } - if let Some(yarn) = &self.yarn { - let yarn_str = yarn.value.to_string(); - bins.push(home.yarn_image_bin_dir(&yarn_str)); + if is_yarn_enabled() { + if let Some(yarn) = &self.yarn { + let yarn_str = yarn.value.to_string(); + bins.push(home.yarn_image_bin_dir(&yarn_str)); + } } // Add Node path to the bins last, so that any custom version of npm will be earlier in the PATH diff --git a/crates/volta-core/src/platform/mod.rs b/crates/volta-core/src/platform/mod.rs index 18558f4aa..1e48b6aae 100644 --- a/crates/volta-core/src/platform/mod.rs +++ b/crates/volta-core/src/platform/mod.rs @@ -4,7 +4,7 @@ use std::fmt; use crate::error::{ErrorKind, Fallible}; use crate::session::Session; use crate::tool::{Node, Npm, Pnpm, Yarn}; -use crate::VOLTA_FEATURE_PNPM; +use crate::{is_yarn_enabled, VOLTA_FEATURE_PNPM}; use node_semver::Version; mod image; @@ -290,8 +290,10 @@ impl Platform { } } - if let Some(Sourced { value: version, .. }) = &self.yarn { - Yarn::new(version.clone()).ensure_fetched(session)?; + if is_yarn_enabled() { + if let Some(Sourced { value: version, .. }) = &self.yarn { + Yarn::new(version.clone()).ensure_fetched(session)?; + } } Ok(Image { diff --git a/crates/volta-core/src/run/mod.rs b/crates/volta-core/src/run/mod.rs index 89278eba7..7190e786b 100644 --- a/crates/volta-core/src/run/mod.rs +++ b/crates/volta-core/src/run/mod.rs @@ -7,7 +7,7 @@ use std::process::ExitStatus; use crate::error::{ErrorKind, Fallible}; use crate::platform::{CliPlatform, Image, Sourced}; use crate::session::Session; -use crate::VOLTA_FEATURE_PNPM; +use crate::{is_yarn_enabled, VOLTA_FEATURE_PNPM}; use log::debug; use node_semver::Version; @@ -86,6 +86,7 @@ fn get_executor( Some("node") => node::command(args, session), Some("npm") => npm::command(args, session), Some("npx") => npx::command(args, session), + Some("pnpm") => { // If the pnpm feature flag variable is set, delegate to the pnpm handler // If not, use the binary handler as a fallback (prior to pnpm support, installing @@ -96,7 +97,17 @@ fn get_executor( binary::command(exe, args, session) } } - Some("yarn") | Some("yarnpkg") => yarn::command(args, session), + + Some("yarn") | Some("yarnpkg") => { + println!("is_yarn_enabled: {:?}", is_yarn_enabled()); + if is_yarn_enabled() { + yarn::command(args, session) + } else { + println!("using binary"); + binary::command(exe, args, session) + } + } + _ => binary::command(exe, args, session), } } diff --git a/crates/volta-core/src/run/yarn.rs b/crates/volta-core/src/run/yarn.rs index a2dcaf208..86d36b13d 100644 --- a/crates/volta-core/src/run/yarn.rs +++ b/crates/volta-core/src/run/yarn.rs @@ -19,20 +19,18 @@ use crate::session::{ActivityKind, Session}; pub(super) fn command(args: &[OsString], session: &mut Session) -> Fallible { session.add_event_start(ActivityKind::Yarn); // Don't re-evaluate the context or global install interception if this is a recursive call - - let platform = if env::var_os(RECURSION_ENV_VAR).is_some() { - None - } else if env::var_os("VOLTA_SKIP_YARN") { - None - } else { - if let CommandArg::Global(cmd) = CommandArg::for_yarn(args) { - // For globals, only intercept if the default platform exists - if let Some(default_platform) = session.default_platform()? { - return cmd.executor(default_platform); + let platform = match env::var_os(RECURSION_ENV_VAR) { + Some(_) => None, + None => { + if let CommandArg::Global(cmd) = CommandArg::for_yarn(args) { + // For globals, only intercept if the default platform exists + if let Some(default_platform) = session.default_platform()? { + return cmd.executor(default_platform); + } } - } - Platform::current(session)? + Platform::current(session)? + } }; Ok(ToolCommand::new("yarn", args, platform, ToolKind::Yarn).into()) diff --git a/crates/volta-core/src/tool/mod.rs b/crates/volta-core/src/tool/mod.rs index a464107df..8643220fa 100644 --- a/crates/volta-core/src/tool/mod.rs +++ b/crates/volta-core/src/tool/mod.rs @@ -8,7 +8,7 @@ use crate::session::Session; use crate::style::{note_prefix, success_prefix, tool_version}; use crate::sync::VoltaLock; use crate::version::VersionSpec; -use crate::VOLTA_FEATURE_PNPM; +use crate::{is_yarn_enabled, VOLTA_FEATURE_PNPM}; use cfg_if::cfg_if; use log::{debug, info}; @@ -104,8 +104,13 @@ impl Spec { } } Spec::Yarn(version) => { - let version = yarn::resolve(version, session)?; - Ok(Box::new(Yarn::new(version))) + if is_yarn_enabled() { + let version = yarn::resolve(version, session)?; + Ok(Box::new(Yarn::new(version))) + } else { + let package = Package::new("yarn".to_owned(), version)?; + Ok(Box::new(package)) + } } // When using global package install, we allow the package manager to perform the version resolution Spec::Package(name, version) => {