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
|
readDir
|
||||||
substring;
|
substring;
|
||||||
|
|
||||||
|
assertMsg = pred: msg:
|
||||||
|
if pred
|
||||||
|
then true
|
||||||
|
else builtins.trace msg false;
|
||||||
|
|
||||||
argsWithPath = args: parts:
|
argsWithPath = args: parts:
|
||||||
let meta.locatedAt = parts;
|
let meta.locatedAt = parts;
|
||||||
in meta // (if isAttrs args then args else args meta);
|
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
|
# The marker is added to every set that was imported directly by
|
||||||
# readTree.
|
# readTree.
|
||||||
importWithMark = args: path: parts:
|
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)
|
in if (isAttrs imported)
|
||||||
then imported // (marker parts)
|
then imported // (marker parts)
|
||||||
else imported;
|
else imported;
|
||||||
|
|
|
@ -79,7 +79,17 @@ let
|
||||||
(import ./test-tree-traversal/default-nix/can-be-drv/default.nix {}))
|
(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" [
|
in runTestsuite "readTree" [
|
||||||
example
|
example
|
||||||
traversal-logic
|
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