diff --git a/README.md b/README.md index ac728e5..249afaa 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ The second argument to `with-inputs` is an attribute set that can be used to drive input resolution, for example to use local checkout or to specify flake-like follows. +See [tests.nix](./tests.nix) for usage examples. + ```nix { # Local checkout — loaded as a flake if a flake.nix is present @@ -92,6 +94,9 @@ checkout or to specify flake-like follows. inputs.nixpkgs.follows = "nixpkgs"; inputs.utils.follows = "flake-utils"; }; + + # Takes the original sources.otherFlake and avoids flake call + otherFlake = source: source // { flake = false; }; } ``` diff --git a/default.nix b/default.nix index e627819..120036a 100644 --- a/default.nix +++ b/default.nix @@ -21,14 +21,18 @@ let isFollows = v: builtins.isAttrs v && v ? follows; + specKeys = [ + "follows" + "inputs" + ]; + # A spec is an attrset whose only keys are "follows" and/or "inputs", # where every inputs.* value is itself a follows spec. # Anything with outPath, lib, packages, … is a direct value, not a spec. isSpec = v: builtins.isAttrs v - && (v ? follows || v ? inputs) - && builtins.all (k: k == "follows" || k == "inputs") (builtins.attrNames v) + && builtins.all (x: builtins.elem x specKeys) (builtins.attrNames v) && (!(v ? inputs) || builtins.all (k: isFollows v.inputs.${k}) (builtins.attrNames v.inputs)); # Returns the resolved input, or null if any segment in the path is missing. @@ -58,7 +62,9 @@ let # Values with outPath but no _type go through mkInput so their flake.nix is loaded. resolveInput = name: v: - if isFollows v then + if builtins.isFunction v then + resolveInput name (v sources.${name}) + else if isFollows v then if v.follows == "" then { } else walkPath v.follows else if isSpec v then resolvedSources.${name} or { } @@ -90,12 +96,14 @@ let mkInput = name: sourceInfo: let + isFlake = sourceInfo.flake or true; flakePath = sourceInfo.outPath + "/flake.nix"; + flakeExists = sourceInfo ? outPath && builtins.pathExists flakePath; in - if sourceInfo ? outPath && builtins.pathExists flakePath then + if isFlake && flakeExists then mkFlakeInput name sourceInfo (import flakePath) else - sourceInfo; + sourceInfo // { inherit sourceInfo; }; mkFlakeInput = name: sourceInfo: flake: diff --git a/tests.nix b/tests.nix index ccecc8a..1b87ab7 100644 --- a/tests.nix +++ b/tests.nix @@ -362,4 +362,30 @@ in expected = npins.nixpkgs.outPath; }; + "test non flakes are not evaluated" = { + expr = + (with-inputs + { + yesFlake.outPath = ./fixtures/fake-flake; + nonFlake.outPath = ./fixtures/fake-flake; + } + { + nonFlake = source: source // { flake = false; }; + } + (inputs: { + result.yes.hasOutputs = inputs.yesFlake ? outputs; + result.non.hasOutputs = inputs.nonFlake ? outputs; + + result.non.sourceInfo = inputs.nonFlake.sourceInfo; + }) + ).result; + expected = { + yes.hasOutputs = true; + non.hasOutputs = false; + + non.sourceInfo.flake = false; + non.sourceInfo.outPath = ./fixtures/fake-flake; + }; + }; + }