prefetch-npm-deps: warn about unresolved lockfile deps
Upstream projects' `package-lock.json` file might include many deps with no resolved line in them, as described here: https://github.com/npm/cli/issues/6301 This can cause dependencies to be missing after generating a hash for `.npmDeps`. If such dependencies are encountered, it's nice to print them and warn the user that an upstream patch might be needed. Co-Authored-By: Jörg Thalheim <joerg@thalheim.io>
This commit is contained in:
co-authored by
Jörg Thalheim
parent
46557a8faa
commit
17aec4cda9
@@ -11,6 +11,36 @@ use std::{
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
fn warn_unresolved_packages(
|
||||
packages_without_resolved: &[(String, Package)],
|
||||
total_count: usize,
|
||||
) {
|
||||
let missing_count = packages_without_resolved.len();
|
||||
if missing_count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let percentage = (missing_count as f64 / total_count as f64) * 100.0;
|
||||
eprintln!(
|
||||
"warning: {} out of {} packages ({:.1}%) are missing 'resolved' URLs and will not be cached.",
|
||||
missing_count, total_count, percentage
|
||||
);
|
||||
eprintln!("warning: Packages without 'resolved' URLs:");
|
||||
for (name, _) in packages_without_resolved.iter().take(10) {
|
||||
eprintln!("warning: - {}", name.trim_start_matches("node_modules/"));
|
||||
}
|
||||
if missing_count > 10 {
|
||||
eprintln!("warning: ... and {} more", missing_count - 10);
|
||||
}
|
||||
if percentage > 50.0 {
|
||||
eprintln!(
|
||||
"warning: More than 50% of packages are missing 'resolved' URLs. This may indicate an issue with the lockfile.\n\
|
||||
warning: This is a known issue with some npm versions. See: https://github.com/npm/cli/issues/6301\n\
|
||||
warning: Consider regenerating upstream's lockfile with: npm install --package-lock-only (sending an upstream PR is best)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn packages(content: &str) -> anyhow::Result<Vec<Package>> {
|
||||
let lockfile: Lockfile = serde_json::from_str(content)?;
|
||||
|
||||
@@ -20,18 +50,27 @@ pub(super) fn packages(content: &str) -> anyhow::Result<Vec<Package>> {
|
||||
|
||||
to_new_packages(lockfile.dependencies.unwrap_or_default(), &initial_url)?
|
||||
}
|
||||
2 | 3 => lockfile
|
||||
.packages
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.filter(|(n, p)| !n.is_empty() && matches!(p.resolved, Some(UrlOrString::Url(_))))
|
||||
.map(|(n, p)| Package {
|
||||
// Use the package's own name if present (for aliases like string-width-cjs -> string-width),
|
||||
// otherwise extract from the lockfile key
|
||||
name: Some(p.name.unwrap_or(n)),
|
||||
..p
|
||||
})
|
||||
.collect(),
|
||||
2 | 3 => {
|
||||
let (packages_with_resolved, packages_without_resolved): (Vec<_>, Vec<_>) = lockfile
|
||||
.packages
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.filter(|(n, _)| !n.is_empty())
|
||||
.partition(|(_, p)| matches!(p.resolved, Some(UrlOrString::Url(_))));
|
||||
|
||||
let total_count = packages_with_resolved.len() + packages_without_resolved.len();
|
||||
warn_unresolved_packages(&packages_without_resolved, total_count);
|
||||
|
||||
packages_with_resolved
|
||||
.into_iter()
|
||||
.map(|(n, p)| Package {
|
||||
// Use the package's own name if present (for aliases like string-width-cjs -> string-width),
|
||||
// otherwise extract from the lockfile key
|
||||
name: Some(p.name.unwrap_or(n)),
|
||||
..p
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
_ => bail!(
|
||||
"We don't support lockfile version {}, please file an issue.",
|
||||
lockfile.version
|
||||
|
||||
Reference in New Issue
Block a user