From f427ecf1a05493c788a94ee3b70bccd7285a64b5 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 13 Oct 2023 23:49:17 +0200 Subject: [PATCH] Repurpose moduleLocation impl for new errorLocation The difference is that moduleLocation is "guaranteed" reliable data, whereas errorLocation is the best choice for error messages in the core. moduleLocation is suitable for the module key attribute. errorLocation is best for the *ROOT* module _file attribute. Initially I applied errorLocation in too many places. It is only needed when the flake output attribute names are strict in it. To avoid confusion, I'm not exposing errorLocation to the modules, until we have a concrete use case for it. --- dev/tests/eval-tests.nix | 22 ++++++++++++++++++++++ lib.nix | 28 +++++++++++++++++----------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/dev/tests/eval-tests.nix b/dev/tests/eval-tests.nix index 437ee1a..c3c03b6 100644 --- a/dev/tests/eval-tests.nix +++ b/dev/tests/eval-tests.nix @@ -26,6 +26,22 @@ rec { systems = [ ]; }; + emptyExposeArgs = mkFlake + { inputs.self = { outPath = "the self outpath"; }; } + ({ config, moduleLocation, errorLocation, ... }: { + flake = { + inherit moduleLocation errorLocation; + }; + }); + + emptyExposeArgsNoSelf = mkFlake + { inputs.self = throw "self won't be available in case of some errors"; } + ({ config, moduleLocation, errorLocation, ... }: { + flake = { + inherit moduleLocation errorLocation; + }; + }); + example1 = mkFlake { inputs.self = { }; } { @@ -162,6 +178,12 @@ rec { assert packagesNonStrictInDevShells.packages.a.default == pkg "a" "hello"; + assert emptyExposeArgs.moduleLocation == "the self outpath/flake.nix"; + + assert emptyExposeArgs.errorLocation == __curPos.file; + + assert emptyExposeArgsNoSelf.errorLocation == __curPos.file; + ok; result = runTests "ok"; diff --git a/lib.nix b/lib.nix index f338367..eaa5679 100644 --- a/lib.nix +++ b/lib.nix @@ -83,6 +83,22 @@ let '') , moduleLocation ? "${self.outPath}/flake.nix" }: + let + module = lib.setDefaultModuleLocation errorLocation module; + inputsPos = builtins.unsafeGetAttrPos "inputs" args; + errorLocation = + # Best case: user makes it explicit + args.moduleLocation or ( + # Slightly worse: Nix does not technically commit to unsafeGetAttrPos semantics + if inputsPos != null + then inputsPos.file + # Slightly worse: self may not be valid when an error occurs + else if args?inputs.self.outPath + then args.inputs.self.outPath + "/flake.nix" + # Fallback + else "" + ); + in throwIf (!args?self && !args?inputs) '' When invoking flake-parts, you must pass in the flake output arguments. @@ -121,17 +137,7 @@ let mkFlake = args: module: let - inputsPos = builtins.unsafeGetAttrPos "inputs" args; - moduleLocation = - args.moduleLocation or ( - if inputsPos != null - then inputsPos.file - else if args?inputs.self.outPath - then args.inputs.self.outPath + "/flake.nix" - else "" - ); - mod = lib.setDefaultModuleLocation moduleLocation module; - eval = flake-parts-lib.evalFlakeModule (args // { inherit moduleLocation; }) mod; + eval = flake-parts-lib.evalFlakeModule args module; in eval.config.flake;