Skip to content
Closed
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
20 changes: 11 additions & 9 deletions crates/vite_global_cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ async fn managed_update(
}
current_node_version = get_current_node_version().await?;

for metadata in &all {
for metadata in all.iter().filter(|metadata| !metadata.local) {
if !is_same_node_version(&metadata.platform.node, &current_node_version) {
node_mismatches.push(NodeMismatchPackage {
name: metadata.name.clone(),
Expand All @@ -743,15 +743,17 @@ async fn managed_update(
current_node_version = get_current_node_version().await?;

for package in packages {
// Always update local packages
if global::is_local_package_spec(package) {
to_update.push(package.clone());
continue;
}

// It is not a local package, so `parse_package_spec` there won't return `Err()`
let (package_name, _) = global::parse_package_spec(package).unwrap();
let (package_name, _) = match global::parse_package_spec(package) {
Ok(parsed) => parsed,
Err(error) => {
output::error(&format!("Failed to update {package}: {error}"));
return Ok(exit_status(1));
}
};
if let Some(metadata) = PackageMetadata::load(&package_name).await? {
if metadata.local {
continue;
}
if !is_same_node_version(&metadata.platform.node, &current_node_version) {
node_mismatches.push(NodeMismatchPackage {
name: package_name,
Expand Down
5 changes: 5 additions & 0 deletions crates/vite_global_cli/src/commands/env/package_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ pub struct PackageMetadata {
/// `corepack`). Updates keep the restriction; explicit installs reset it.
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub bins_restricted: bool,
/// Whether the package was installed from local filesystem content.
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub local: bool,
/// Package manager used for installation (npm, yarn, pnpm)
pub manager: String,
/// Installation timestamp
Expand Down Expand Up @@ -81,6 +84,7 @@ impl PackageMetadata {
bins,
js_bins,
bins_restricted: false,
local: false,
manager,
installed_at: Utc::now(),
}
Expand Down Expand Up @@ -253,6 +257,7 @@ mod tests {
.unwrap();

assert!(metadata.install_id.is_empty());
assert!(!metadata.local);
}

#[test]
Expand Down
3 changes: 2 additions & 1 deletion crates/vite_global_cli/src/commands/global/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ pub async fn install(

// 4. Finalize installed packages.
let mut bin_owners = HashMap::<String, String>::new();
for (index, (package_name, Package { spec: _, install })) in packages.into_iter().enumerate() {
for (index, (package_name, Package { spec, install })) in packages.into_iter().enumerate() {
let lock_file = install_locks.remove(&package_name);
let Some(InstalledPackage {
installed_version,
Expand Down Expand Up @@ -403,6 +403,7 @@ pub async fn install(
);
metadata.install_id = install_id.clone();
metadata.bins_restricted = bins_restricted;
metadata.local = is_local_package_spec(spec);

let mut finalized = true;
for bin_name in &stale_bin_names {
Expand Down
63 changes: 62 additions & 1 deletion crates/vite_global_cli/src/commands/global/outdated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,20 @@ pub async fn get_outdated_packages(
continue;
};
if let Some(metadata) = PackageMetadata::load(&package_name).await? {
if metadata.local {
continue;
}
installed.push((metadata, Some(package.clone())));
}
}
installed
} else {
PackageMetadata::list_all().await?.into_iter().map(|package| (package, None)).collect()
PackageMetadata::list_all()
.await?
.into_iter()
.filter(|package| !package.local)
.map(|package| (package, None))
.collect()
};

if installed.is_empty() {
Expand Down Expand Up @@ -272,3 +280,56 @@ fn exit_status(code: i32) -> ExitStatus {
ExitStatus::from_raw(code as u32)
}
}

#[cfg(test)]
mod tests {
use std::collections::HashSet;

use tempfile::TempDir;

use super::*;
use crate::commands::env::package_metadata::PackageMetadata;

async fn save_local_metadata(name: &str) {
let mut metadata = PackageMetadata::new(
name.to_string(),
"1.0.0".to_string(),
"22.0.0".to_string(),
None,
vec![name.to_string()],
HashSet::from([name.to_string()]),
"npm".to_string(),
);
metadata.local = true;
metadata.save().await.unwrap();
}

#[tokio::test]
async fn skips_local_packages_when_checking_all_global_updates() {
let temp_dir = TempDir::new().unwrap();
let _guard = vite_shared::EnvConfig::test_guard(
vite_shared::EnvConfig::for_test_with_home(temp_dir.path()),
);

save_local_metadata("some-local-package").await;

let outdated = get_outdated_packages(&[], 1, true).await.unwrap();

assert!(outdated.is_empty());
}

#[tokio::test]
async fn skips_local_packages_when_checking_named_global_updates() {
let temp_dir = TempDir::new().unwrap();
let _guard = vite_shared::EnvConfig::test_guard(
vite_shared::EnvConfig::for_test_with_home(temp_dir.path()),
);

save_local_metadata("some-local-package").await;

let outdated =
get_outdated_packages(&["some-local-package".to_string()], 1, true).await.unwrap();

assert!(outdated.is_empty());
}
}
Loading