Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions crates/vp_cli_snapshots/tests/cli_snapshots/redact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ static YARN_STEP_TIMING_RE: LazyLock<regex::Regex> =
static VITEST_TIMING_RE: LazyLock<regex::Regex> = LazyLock::new(|| {
regex::Regex::new(r"(?m)(Duration\s+<duration>) \((?:[a-z]+ \d+%(?:, )?)+\)").unwrap()
});
// Vitest conditionally prints this advisory based on measured transform time.
// Remove the complete known block, not arbitrary Transform lines or failures.
static VITEST_TRANSFORM_CACHE_HINT_RE: LazyLock<regex::Regex> = LazyLock::new(|| {
regex::Regex::new(concat!(
r"(?m)\n[ \t]*Transform [^\n]*transforming modules took <duration> · \d+% of tracked time, re-done on every run\n",
r"[ \t]*persist transforms across runs with fsModuleCache: true\n",
r"(?:[ \t]*on CI this only helps when the cache directory is persisted between runs\n)?",
r"[ \t]*learn more: https://vitest\.dev/guide/improving-performance#caching-between-reruns(?:\n|$)",
))
.unwrap()
});
// Only v-prefixed versions are masked: tool and runtime banners all print
// that form (`vite v7.3.2`, `vp v0.2.2`, `Node.js v24.18.0`) and churn on
// every dep bump, while bare semver literals (`app-1.0.0.tgz`,
Expand Down Expand Up @@ -529,6 +540,7 @@ pub fn redact_output(
output = YARN_ELAPSED_RE.replace_all(&output, "${1}<duration>").into_owned();
output = DURATION_RE.replace_all(&output, "<duration>").into_owned();
output = VITEST_TIMING_RE.replace_all(&output, "$1 (<timing>)").into_owned();
output = VITEST_TRANSFORM_CACHE_HINT_RE.replace_all(&output, "").into_owned();

// Redact semver-shaped versions (bundled tool versions, Node versions).
output = VERSION_RE.replace_all(&output, "<version>").into_owned();
Expand Down
44 changes: 44 additions & 0 deletions crates/vp_cli_snapshots/tests/redact_unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,50 @@ fn masks_vitest_v5_timing_but_preserves_coverage_percentages() {
);
}

#[test]
fn omits_optional_vitest_transform_cache_hint() {
let summary = " Tests 1 passed (1)\n Duration 3.4s (transform 84%, tests 16%)\n";
for project in ["", "[unit] "] {
for ci_hint in [
"",
" on CI this only helps when the cache directory is persisted between runs\n",
] {
let hint = format!(
"\n Transform {project}transforming modules took 2.8s · 84% of tracked time, re-done on every run\n\
{}persist transforms across runs with fsModuleCache: true\n\
{ci_hint}{}learn more: https://vitest.dev/guide/improving-performance#caching-between-reruns\n",
" ", " "
);
let expected = redact_output(summary.to_owned(), &[], true);
assert_eq!(redact_output(format!("{summary}{hint}"), &[], true), expected);
assert_eq!(
redact_output(format!("{summary}{}", hint.trim_end_matches('\n')), &[], true),
expected
);
assert_eq!(
redact_output(format!("{summary}{hint}").replace('\n', "\r\n"), &[], true),
expected
);
assert_eq!(
redact_output(format!("{summary}{hint}\nnext command\n"), &[], true),
format!("{expected}\nnext command\n")
);
}
}
}

#[test]
fn preserves_transform_errors_and_incomplete_cache_hints() {
for input in [
"Transform failed: cannot load module\n",
"\n Transform transforming modules took 2.8s · 84% of tracked time, re-done on every run\n",
"persist transforms across runs with fsModuleCache: true\n",
"learn more: https://example.com/improving-performance\n",
] {
assert_eq!(redact_output(input.to_owned(), &[], true), input.replace("2.8s", "<duration>"));
}
}

#[test]
fn masks_vitest_api_port_but_preserves_other_localhost_urls() {
let input = "API started at http://localhost:63316/\nBrowser runner started at http://localhost:63317/__vitest_test__/?sessionId=keep-session\nhttp://localhost:9229/\n";
Expand Down
5 changes: 3 additions & 2 deletions crates/vp_global_cli/src/commands/env/clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use std::{path::Path, process::ExitStatus};

use vp_pm_cli::{PackageManagerType, resolve_package_manager_version};
use vp_pm_cli::{PackageManagerType, resolve_package_manager_version_for_cwd};
use vp_shared::output;
use vt_path::{AbsolutePath, AbsolutePathBuf};

Expand Down Expand Up @@ -62,7 +62,8 @@ async fn protected_package_manager(
}
let config = config::load_config().await?;
if let Some((_, selector, _)) = package_manager::configured_default_for(&config, kind)? {
let version = resolve_package_manager_version(kind, &selector).await?.to_string();
let version =
resolve_package_manager_version_for_cwd(cwd, kind, &selector).await?.to_string();
push_unique_version(&mut protected, version);
}
Ok(protected)
Expand Down
7 changes: 4 additions & 3 deletions crates/vp_global_cli/src/commands/env/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use std::process::ExitStatus;

use vp_js_runtime::NodeProvider;
use vp_pm_cli::{download_package_manager, resolve_package_manager_version};
use vp_pm_cli::{download_package_manager_for_cwd, resolve_package_manager_version_for_cwd};
use vp_shared::{PrependOptions, ToolPathEnv, env_vars};
use vt_path::AbsolutePath;

Expand Down Expand Up @@ -153,7 +153,8 @@ async fn execute_with_version(
let mut system_package_manager = None;
let selected_package_manager = if let Some(package_manager) = package_manager {
let (kind, selector, hash) = parse_package_manager_spec_with_hash(package_manager)?;
let version = resolve_package_manager_version(kind, &selector).await?.to_string();
let version =
resolve_package_manager_version_for_cwd(cwd, kind, &selector).await?.to_string();
Some((kind, version, hash))
} else {
let selected = package_manager_resolution::resolve_current_spec(cwd).await?;
Expand Down Expand Up @@ -206,7 +207,7 @@ async fn execute_with_version(
Some(format!("{kind}@{system_version}"))
} else {
let (install_dir, _, _) =
download_package_manager(kind, &version, hash.as_deref()).await?;
download_package_manager_for_cwd(cwd, kind, &version, hash.as_deref()).await?;
path_prefixes
.insert(0, (install_dir.join("bin").into_path_buf(), kind.bin_names().to_vec()));
Some(format!("{kind}@{version}"))
Expand Down
6 changes: 3 additions & 3 deletions crates/vp_global_cli/src/commands/env/lifecycle.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::process::ExitStatus;

use vp_pm_cli::{download_package_manager, resolve_package_manager_version};
use vp_pm_cli::{download_package_manager_for_cwd, resolve_package_manager_version_for_cwd};
use vt_path::AbsolutePathBuf;

use super::{
Expand Down Expand Up @@ -64,7 +64,7 @@ pub(crate) async fn install(

if scope.includes_package_managers() {
let requested = if let Some((kind, selector, hash)) = specs.package_manager {
let version = resolve_package_manager_version(kind, &selector).await?;
let version = resolve_package_manager_version_for_cwd(&cwd, kind, &selector).await?;
Some((kind, version, hash))
} else if let EnvScope::PackageManager(kind) = scope {
let resolution = package_manager::resolve_current_or_fallback_for(&cwd, kind).await?;
Expand All @@ -84,7 +84,7 @@ pub(crate) async fn install(
};
if let Some((kind, version, hash)) = requested {
vp_shared::output::print_stdout_line(format_args!("Installing {kind} v{version}..."));
download_package_manager(kind, &version, hash.as_deref()).await?;
download_package_manager_for_cwd(&cwd, kind, &version, hash.as_deref()).await?;
vp_shared::output::print_stdout_line(format_args!("Installed {kind} v{version}"));
}
}
Expand Down
14 changes: 9 additions & 5 deletions crates/vp_global_cli/src/commands/env/list_remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use console::style;
use futures::future::try_join_all;
use serde::Serialize;
use vp_js_runtime::{LtsInfo, NodeProvider, NodeVersionEntry};
use vp_pm_cli::{fetch_package_manager_versions, resolve_package_manager_version};
use vp_pm_cli::{fetch_package_manager_versions_for_cwd, resolve_package_manager_version_for_cwd};
use vt_path::AbsolutePathBuf;

use super::{
Expand Down Expand Up @@ -78,11 +78,15 @@ pub async fn execute(
Ok(None)
}
};
let cwd_ref = &cwd;
let package_manager_future =
try_join_all(package_manager_types.iter().copied().map(|kind| async move {
fetch_package_manager_versions(kind).await.map(|versions| (kind, versions)).map_err(
|error| Error::Other(format!("failed to fetch {kind} versions: {error}").into()),
)
fetch_package_manager_versions_for_cwd(cwd_ref, kind)
.await
.map(|versions| (kind, versions))
.map_err(|error| {
Error::Other(format!("failed to fetch {kind} versions: {error}").into())
})
}));
let (node_versions, package_manager_versions) =
futures::join!(node_future, package_manager_future);
Expand Down Expand Up @@ -118,7 +122,7 @@ pub async fn execute(
else {
continue;
};
let version = resolve_package_manager_version(kind, &selector).await?;
let version = resolve_package_manager_version_for_cwd(&cwd, kind, &selector).await?;
default_package_manager_versions.insert(kind.to_string(), version.to_string());
}
}
Expand Down
3 changes: 2 additions & 1 deletion crates/vp_global_cli/src/commands/env/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ async fn print_env(cwd: AbsolutePathBuf, scope: Option<String>) -> Result<ExitSt
None => package_manager::resolve_current_for(&cwd, None).await?,
};
if let Some(resolution) = resolution {
let (install_dir, _, _) = vp_pm_cli::download_package_manager(
let (install_dir, _, _) = vp_pm_cli::download_package_manager_for_cwd(
&cwd,
resolution.package_manager_type,
&resolution.version,
resolution.hash.as_deref(),
Expand Down
17 changes: 10 additions & 7 deletions crates/vp_global_cli/src/commands/env/package_manager.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use vp_pm_cli::{
EnvironmentPackageManagerResolution, PackageManagerType, resolve_environment_package_manager,
resolve_environment_package_manager_spec, resolve_package_manager_version,
resolve_environment_package_manager_spec, resolve_package_manager_version_for_cwd,
};
use vt_path::AbsolutePath;

Expand Down Expand Up @@ -36,7 +36,7 @@ pub(crate) async fn resolve_shim_for(
.as_ref()
.map(|(kind, version, hash)| (*kind, version.as_str(), hash.as_deref())),
)?;
let mut resolution = resolve_selection(resolution, Some(expected)).await?;
let mut resolution = resolve_selection(cwd, resolution, Some(expected)).await?;
if override_spec.is_some()
&& let Some(resolution) = &mut resolution
{
Expand Down Expand Up @@ -74,7 +74,7 @@ pub(crate) async fn resolve_current_for(
expected: Option<PackageManagerType>,
) -> Result<Option<EnvironmentPackageManagerResolution>, Error> {
let resolution = resolve_current_spec(cwd).await?;
resolve_selection(resolution, expected).await
resolve_selection(cwd, resolution, expected).await
}

pub(crate) async fn resolve_current_or_fallback_for(
Expand All @@ -85,7 +85,7 @@ pub(crate) async fn resolve_current_or_fallback_for(
return Ok(resolution);
}

registry_fallback_for(package_manager).await
registry_fallback_for(cwd, package_manager).await
}

pub(crate) async fn resolve_current_spec(
Expand Down Expand Up @@ -115,6 +115,7 @@ pub(crate) type PackageManagerSpec = (PackageManagerType, String, Option<String>

/// Both entry points select a family before looking up its default version.
async fn resolve_selection(
cwd: &AbsolutePath,
resolution: Option<EnvironmentPackageManagerResolution>,
expected: Option<PackageManagerType>,
) -> Result<Option<EnvironmentPackageManagerResolution>, Error> {
Expand All @@ -123,6 +124,7 @@ async fn resolve_selection(
let config = config::load_config().await?;
let default = kind.map(|kind| configured_default_for(&config, kind)).transpose()?.flatten();
resolve_environment_package_manager(
cwd,
resolution,
default.as_ref().map(|(kind, version, hash)| (*kind, version.as_str(), hash.as_deref())),
expected,
Expand All @@ -148,7 +150,7 @@ pub(crate) async fn resolve_from_files_for(
expected: Option<PackageManagerType>,
) -> Result<Option<EnvironmentPackageManagerResolution>, Error> {
let resolution = resolve_environment_package_manager_spec(cwd, None)?;
resolve_selection(resolution, expected).await
resolve_selection(cwd, resolution, expected).await
}

pub(crate) async fn resolve_from_files_or_fallback_for(
Expand All @@ -159,15 +161,16 @@ pub(crate) async fn resolve_from_files_or_fallback_for(
return Ok(resolution);
}

registry_fallback_for(package_manager).await
registry_fallback_for(cwd, package_manager).await
}

async fn registry_fallback_for(
cwd: &AbsolutePath,
package_manager: PackageManagerType,
) -> Result<EnvironmentPackageManagerResolution, Error> {
Ok(EnvironmentPackageManagerResolution {
package_manager_type: package_manager,
version: resolve_package_manager_version(package_manager, "latest").await?,
version: resolve_package_manager_version_for_cwd(cwd, package_manager, "latest").await?,
hash: None,
source: "registry fallback".into(),
source_path: None,
Expand Down
10 changes: 6 additions & 4 deletions crates/vp_global_cli/src/commands/env/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use std::{io::Write, process::ExitStatus};

use vp_js_runtime::{NodeProvider, VersionSource, resolve_node_version};
use vp_pm_cli::{
PackageManagerType, download_package_manager, resolve_package_manager_from_package_json,
resolve_package_manager_version,
PackageManagerType, download_package_manager_for_cwd,
resolve_package_manager_from_package_json, resolve_package_manager_version_for_cwd,
};
use vp_shared::output;
use vt_path::AbsolutePathBuf;
Expand Down Expand Up @@ -845,7 +845,7 @@ async fn pin_package_manager(
if matches!(target, Some(PinTarget::NodeVersion | PinTarget::Nvmrc)) {
return Err(Error::Other("Node.js file targets cannot pin a package manager".into()));
}
let resolved = resolve_package_manager_version(package_manager, version).await?;
let resolved = resolve_package_manager_version_for_cwd(cwd, package_manager, version).await?;
package_manager::warn_if_target_differs(cwd, package_manager).await;
let package_json_path = cwd.join(PACKAGE_JSON_FILE);
let content = tokio::fs::read_to_string(&package_json_path).await?;
Expand Down Expand Up @@ -912,7 +912,9 @@ async fn pin_package_manager(
}
if no_install {
output::note("Package manager will be downloaded on first use.");
} else if let Err(error) = download_package_manager(package_manager, &resolved, hash).await {
} else if let Err(error) =
download_package_manager_for_cwd(cwd, package_manager, &resolved, hash).await
{
output::warn(&format!("Failed to download {package_manager} {resolved}: {error}"));
}
Ok(ExitStatus::default())
Expand Down
12 changes: 8 additions & 4 deletions crates/vp_global_cli/src/commands/env/use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

use std::process::ExitStatus;

use vp_pm_cli::{PackageManagerType, download_package_manager, resolve_package_manager_version};
use vp_pm_cli::{
PackageManagerType, download_package_manager_for_cwd, resolve_package_manager_version_for_cwd,
};
use vt_path::AbsolutePathBuf;

use super::{
Expand Down Expand Up @@ -147,7 +149,8 @@ pub async fn execute(

let package_manager = if scope.includes_package_managers() {
if let Some((kind, selector, hash)) = specs.package_manager {
let version = resolve_package_manager_version(kind, &selector).await?.to_string();
let version =
resolve_package_manager_version_for_cwd(&cwd, kind, &selector).await?.to_string();
package_manager::warn_if_target_differs(&cwd, kind).await;
Some((kind, version, selector, hash))
} else if let EnvScope::PackageManager(kind) = scope {
Expand Down Expand Up @@ -233,7 +236,7 @@ pub async fn execute(
}

if !no_install {
ensure_components_installed(&node, &package_manager).await?;
ensure_components_installed(&cwd, &node, &package_manager).await?;
}

if has_eval_wrapper() {
Expand Down Expand Up @@ -295,6 +298,7 @@ pub async fn execute(
}

async fn ensure_components_installed(
cwd: &AbsolutePathBuf,
node: &Option<(String, String)>,
package_manager: &Option<(PackageManagerType, String, String, Option<String>)>,
) -> Result<(), Error> {
Expand All @@ -318,7 +322,7 @@ async fn ensure_components_installed(
}
}
if let Some((kind, version, _, hash)) = package_manager {
download_package_manager(*kind, version, hash.as_deref()).await?;
download_package_manager_for_cwd(cwd, *kind, version, hash.as_deref()).await?;
}
Ok(())
}
Expand Down
6 changes: 4 additions & 2 deletions crates/vp_global_cli/src/commands/env/which.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use chrono::Local;
use console::style;
use vp_pm_cli::{
PackageManagerType, package_manager_bin_path, package_manager_install_dir,
resolve_package_manager_version,
resolve_package_manager_version_for_cwd,
};
use vp_shared::output;
use vt_path::{AbsolutePath, AbsolutePathBuf};
Expand Down Expand Up @@ -170,7 +170,9 @@ async fn execute_package_manager_tool(
),
None if expected_type == PackageManagerType::Npm => return Ok(None),
None => (
resolve_package_manager_version(expected_type, "latest").await?.to_string(),
resolve_package_manager_version_for_cwd(cwd, expected_type, "latest")
.await?
.to_string(),
"registry fallback".into(),
),
};
Expand Down
3 changes: 2 additions & 1 deletion crates/vp_global_cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ pub async fn prepend_js_runtime_to_path_env(project_path: &AbsolutePath) -> Resu
}
}
if let Some(package_manager) = env::package_manager::resolve_current(project_path).await? {
let (install_dir, _, _) = vp_pm_cli::download_package_manager(
let (install_dir, _, _) = vp_pm_cli::download_package_manager_for_cwd(
project_path,
package_manager.package_manager_type,
&package_manager.version,
package_manager.hash.as_deref(),
Expand Down
Loading
Loading