summary refs log tree commit diff
diff options
context:
space:
mode:
authorWinter <winter@winter.cafe>2022-11-09 22:36:54 -0500
committerWinter <winter@winter.cafe>2022-11-21 15:00:08 -0500
commitcc5756b1712cc1341781b6dc019f9483332c863c (patch)
tree57ddbc1f9b4f5811c39c2a0069fb4c7e2abf1d84
parentc30da46cc5e917883e4747037e1073e33b788dbd (diff)
prefetch-npm-deps: add support for link dependencies in v2 lockfiles
-rw-r--r--pkgs/build-support/node/fetch-npm-deps/default.nix11
-rw-r--r--pkgs/build-support/node/fetch-npm-deps/src/main.rs43
2 files changed, 41 insertions, 13 deletions
diff --git a/pkgs/build-support/node/fetch-npm-deps/default.nix b/pkgs/build-support/node/fetch-npm-deps/default.nix
index d6ee0124d2851..128669b890009 100644
--- a/pkgs/build-support/node/fetch-npm-deps/default.nix
+++ b/pkgs/build-support/node/fetch-npm-deps/default.nix
@@ -81,6 +81,17 @@
 
           hash = "sha256-oIM05TGHstX1D4k2K4TJ+SHB7H/tNKzxzssqf0GJwvY=";
         };
+
+        linkDependencies = makeTest {
+          name = "link-dependencies";
+
+          src = fetchurl {
+            url = "https://raw.githubusercontent.com/evcc-io/evcc/0.106.3/package-lock.json";
+            hash = "sha256-6ZTBMyuyPP/63gpQugggHhKVup6OB4hZ2rmSvPJ0yEs=";
+          };
+
+          hash = "sha256-uQx8F5OXKm+fqx6hP6obVYTlQIYcJwtO52j6VQNo7Sk=";
+        };
       };
 
     meta = with lib; {
diff --git a/pkgs/build-support/node/fetch-npm-deps/src/main.rs b/pkgs/build-support/node/fetch-npm-deps/src/main.rs
index 097148fef82a0..d23e41a7f9fcd 100644
--- a/pkgs/build-support/node/fetch-npm-deps/src/main.rs
+++ b/pkgs/build-support/node/fetch-npm-deps/src/main.rs
@@ -6,7 +6,7 @@ use rayon::prelude::*;
 use serde::Deserialize;
 use std::{
     collections::HashMap,
-    env, fs,
+    env, fmt, fs,
     path::Path,
     process::{self, Command},
 };
@@ -25,18 +25,34 @@ struct PackageLock {
 
 #[derive(Deserialize)]
 struct OldPackage {
-    version: String,
-    resolved: Option<String>,
+    version: UrlOrString,
+    resolved: Option<UrlOrString>,
     integrity: Option<String>,
     dependencies: Option<HashMap<String, OldPackage>>,
 }
 
 #[derive(Deserialize)]
 struct Package {
-    resolved: Option<Url>,
+    resolved: Option<UrlOrString>,
     integrity: Option<String>,
 }
 
+#[derive(Debug, Deserialize, PartialEq, Eq)]
+#[serde(untagged)]
+enum UrlOrString {
+    Url(Url),
+    String(String),
+}
+
+impl fmt::Display for UrlOrString {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            UrlOrString::Url(url) => url.fmt(f),
+            UrlOrString::String(string) => string.fmt(f),
+        }
+    }
+}
+
 fn to_new_packages(
     old_packages: HashMap<String, OldPackage>,
 ) -> anyhow::Result<HashMap<String, Package>> {
@@ -46,10 +62,10 @@ fn to_new_packages(
         new.insert(
             format!("{name}-{}", package.version),
             Package {
-                resolved: if let Ok(url) = Url::parse(&package.version) {
-                    Some(url)
+                resolved: if matches!(package.version, UrlOrString::Url(_)) {
+                    Some(package.version)
                 } else {
-                    package.resolved.as_deref().map(Url::parse).transpose()?
+                    package.resolved
                 },
                 integrity: package.integrity,
             },
@@ -230,14 +246,15 @@ fn main() -> anyhow::Result<()> {
     packages
         .unwrap()
         .into_par_iter()
+        .filter(|(dep, _)| !dep.is_empty())
+        .filter(|(_, package)| matches!(package.resolved, Some(UrlOrString::Url(_))))
         .try_for_each(|(dep, package)| {
-            if dep.is_empty() || package.resolved.is_none() {
-                return Ok::<_, anyhow::Error>(());
-            }
-
             eprintln!("{dep}");
 
-            let mut resolved = package.resolved.unwrap();
+            let mut resolved = match package.resolved {
+                Some(UrlOrString::Url(url)) => url,
+                _ => unreachable!(),
+            };
 
             if let Some(hosted_git_url) = get_hosted_git_url(&resolved) {
                 resolved = hosted_git_url;
@@ -263,7 +280,7 @@ fn main() -> anyhow::Result<()> {
                 )
                 .map_err(|e| anyhow!("couldn't insert cache entry for {dep}: {e:?}"))?;
 
-            Ok(())
+            Ok::<_, anyhow::Error>(())
         })?;
 
     fs::write(out.join("package-lock.json"), lock_content)?;