feat(nix/readTree): give better error message when not a function
When a file is added to the depot tree that is picked up by read-tree, but it’s not a function like ({...}: {}), `readTree` will fail on the function application, leading to a bad error message. We can do slightly better, by checking the type and throwing a nicer trace message. `assertMsg` is copied from `nixpkgs/lib/assert.nix`, since at this point we don’t have a reference to the lib. There is another evaluation failure that can happen, which is when the function we try to call does not have dots; however, nix does not provide any inflection capabilies for checking whether a function attrset is open (`builtins.functionArgs` only tells us the attrs it mentions explicitly). Maybe the locality of the error could be improved somehow. Change-Id: Ibe38ce78bb56902075f7c31f2eeeb93485b34be3 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2469 Tested-by: BuildkiteCI Reviewed-by: tazjin <mail@tazj.in>
This commit is contained in:
parent
0f1a497361
commit
83e81def23
4 changed files with 27 additions and 1 deletions
|
@ -16,6 +16,11 @@ let
|
|||
readDir
|
||||
substring;
|
||||
|
||||
assertMsg = pred: msg:
|
||||
if pred
|
||||
then true
|
||||
else builtins.trace msg false;
|
||||
|
||||
argsWithPath = args: parts:
|
||||
let meta.locatedAt = parts;
|
||||
in meta // (if isAttrs args then args else args meta);
|
||||
|
@ -38,7 +43,14 @@ let
|
|||
# The marker is added to every set that was imported directly by
|
||||
# readTree.
|
||||
importWithMark = args: path: parts:
|
||||
let imported = import path (argsWithPath args parts);
|
||||
let
|
||||
importedFile = import path;
|
||||
pathType = builtins.typeOf importedFile;
|
||||
imported =
|
||||
assert assertMsg
|
||||
(pathType == "lambda")
|
||||
"readTree: trying to import ${toString path}, but it’s a ${pathType}, you need to make it a function like { depot, pkgs, ... }";
|
||||
importedFile (argsWithPath args parts);
|
||||
in if (isAttrs imported)
|
||||
then imported // (marker parts)
|
||||
else imported;
|
||||
|
|
|
@ -79,7 +79,17 @@ let
|
|||
(import ./test-tree-traversal/default-nix/can-be-drv/default.nix {}))
|
||||
];
|
||||
|
||||
# these each call readTree themselves because the throws have to happen inside assertThrows
|
||||
wrong = it "cannot read these files and will complain" [
|
||||
(assertThrows "this file is not a function"
|
||||
(depot.nix.readTree {} ./test-wrong-not-a-function).not-a-function)
|
||||
# can’t test for that, assertThrows can’t catch this error
|
||||
# (assertThrows "this file is a function but doesn’t have dots"
|
||||
# (depot.nix.readTree {} ./test-wrong-no-dots).no-dots-in-function)
|
||||
];
|
||||
|
||||
in runTestsuite "readTree" [
|
||||
example
|
||||
traversal-logic
|
||||
wrong
|
||||
]
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{}:
|
||||
|
||||
"This is a function, but readTree wants to pass a bunch of arguments, and not having dots means we depend on exactly which arguments."
|
|
@ -0,0 +1 @@
|
|||
"This file needs to be a function, otherwise readTree doesn’t like it!"
|
Loading…
Reference in a new issue