summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pkgs/rust/default.nix10
-rw-r--r--pkgs/rust/lib/crate2nix-package.nix26
2 files changed, 32 insertions, 4 deletions
diff --git a/pkgs/rust/default.nix b/pkgs/rust/default.nix
index d273db6..f6c7eb7 100644
--- a/pkgs/rust/default.nix
+++ b/pkgs/rust/default.nix
@@ -30,6 +30,12 @@ let
lib.optionalAttrs (builtins.pathExists (path + "/Cargo.json")) {
resolvedJson = path + "/Cargo.json";
};
+
+ # The checkout's Cargo.lock, to check the JSON plan against.
+ localLock = path:
+ lib.optionalAttrs (builtins.pathExists (path + "/Cargo.lock")) {
+ cargoLock = path + "/Cargo.lock";
+ };
in
{
@@ -72,10 +78,10 @@ in
in
if explicitPackages ? ${pname} then
assert mylib.debug "pkgs/rust: overriding ${pname}.src with ${mylib.pretty dir}";
- hrmPlan explicitPackages.${pname} // callArgs explicitPackages.${pname} // { inherit src; }
+ hrmPlan explicitPackages.${pname} // callArgs explicitPackages.${pname} // { inherit src; } // localLock dir
else
assert mylib.debug "pkgs/rust: automatic package ${pname} from ${mylib.pretty dir}";
- { name = pname; inherit src; }
+ { name = pname; inherit src; } // localLock dir
)
automaticPackages;
diff --git a/pkgs/rust/lib/crate2nix-package.nix b/pkgs/rust/lib/crate2nix-package.nix
index d97a97e..ee75096 100644
--- a/pkgs/rust/lib/crate2nix-package.nix
+++ b/pkgs/rust/lib/crate2nix-package.nix
@@ -12,6 +12,7 @@
# nixpkgs' defaultCrateOverrides still apply inside buildRustCrate.
{ pkgs
+, lib ? pkgs.lib
, applyOverride
, name
@@ -26,6 +27,9 @@
# IFD only; Cargo.json has its features baked in
, features ? [ "default" ]
+# Cargo.lock the JSON plan must match; null: no check
+, cargoLock ? null
+
, resolvedJson ? null
}:
@@ -67,8 +71,26 @@ let
inherit buildRustCrateForPkgs;
};
- cargoNix =
- if useJson then fromJson else fromLock;
+ # Fails evaluation if the plan uses a crate version the lock doesn't have,
+ # i.e. Cargo.lock changed since Cargo.json was generated. Dependencies added
+ # to the lock aren't detected, since the plan may leave out crates for
+ # features or targets it doesn't use; those fail the build instead.
+ checkLock = result:
+ let
+ id = name: version: "${name} ${version}";
+ lockPackages = (builtins.fromTOML (builtins.readFile cargoLock)).package;
+ locked = builtins.listToAttrs (map
+ (p: { name = id p.name p.version; value = null; })
+ (builtins.filter (p: p ? source) lockPackages));
+ planned = lib.mapAttrsToList (_: c: id c.crateName c.version)
+ (lib.filterAttrs (_: c: (c.source.type or "local") != "local")
+ (builtins.fromJSON (builtins.readFile resolvedJson')).crates);
+ missing = builtins.filter (i: !(locked ? ${i})) planned;
+ in
+ if cargoLock == null || missing == [] then result
+ else throw "crate2nix-package: ${toString resolvedJson'} is stale against ${toString cargoLock}; not in the lock: ${lib.concatStringsSep ", " (lib.take 5 missing)}${lib.optionalString (builtins.length missing > 5) ", ..."}";
+
+ cargoNix = if useJson then checkLock fromJson else fromLock;
in
cargoNix // {
build =