feat(readTree): Add special here argument.

It's convenient for depending on sub-tree members of the current file as
well as gives access to siblings.

Change-Id: I74234cec6566177d88d3bc8507fa3f6ec789adb8
Reviewed-on: https://cl.snix.dev/c/snix/+/30098
Reviewed-by: adis bladis <adisbladis@gmail.com>
Tested-by: besadii
This commit is contained in:
vkryachko 2025-03-18 13:30:08 +00:00 committed by Vova Kryachko
parent 39b3e2c410
commit a04c73ca83
7 changed files with 39 additions and 15 deletions

View file

@ -84,9 +84,15 @@ the tree as empty nodes (`{}`).
imported files via `builtins.scopedImport`. This will forcefully
override the given values in the import scope, use with care!
The package headers in this repository follow the form `{ pkgs, ... }:` where
`pkgs` is a fixed-point of the entire package tree (see the `default.nix` at the
root of the depot).
The package headers in this repository follow the form
`{depot, pkgs, lib, here, ... }:` where:
* `depot` is a fixed-point of the entire package tree (see the `default.nix`
at the root of the depot).
* `pkgs` is the nixpkgs used in the repo, see `third_party/nixpkgs`
* `lib` is essentially a shortcut to `pkgs.lib` exposed for convenience
* `here` is a special argument that points to the current location in the
tree. Useful to avoid specifying dependencies from the very top of the `depot`
In theory `readTree` can pass arguments of different shapes, but I have found
this to be a good solution for the most part.

View file

@ -125,7 +125,7 @@ let
self =
if rootDir
then { __readTree = [ ]; }
else importFile args scopedArgs initPath parts argsFilter;
else importFile (args // { here = result; }) scopedArgs initPath parts argsFilter;
# Import subdirectories of the current one, unless any skip
# instructions exist.
@ -162,7 +162,7 @@ let
let
p = joinChild (c + ".nix");
childParts = parts ++ [ c ];
imported = importFile args scopedArgs p childParts argsFilter;
imported = importFile (args // { here = result; }) scopedArgs p childParts argsFilter;
in
{
name = c;
@ -181,14 +181,16 @@ let
else nixChildren ++ children
);
result =
if isAttrs nodeValue
then merge nodeValue (allChildren // (marker parts allChildren))
else nodeValue;
in
if skipTree
then { skip = true; }
else {
ok =
if isAttrs nodeValue
then merge nodeValue (allChildren // (marker parts allChildren))
else nodeValue;
ok = result;
};
# Top-level implementation of readTree itself.

View file

@ -134,6 +134,13 @@ let
(assertEq "default.nix drv is not changed by readTree"
tree-tl.default-nix.can-be-drv
(import ./test-tree-traversal/default-nix/can-be-drv/default.nix { }))
(assertEq "`here` argument represents the attrset a given file is part of"
(builtins.removeAttrs tree-tl.here-arg [ "__readTree" "__readTreeChildren" "subdir" ])
{
attr1 = "foo";
attr2 = "foo";
attr3 = "sibl1";
})
];
# these each call readTree themselves because the throws have to happen inside assertThrows

View file

@ -0,0 +1,6 @@
{ here, ... }: {
attr1 = "foo";
attr2 = here.attr1;
attr3 = here.subdir.sibl2;
}

View file

@ -0,0 +1 @@
{ ... }: "sibl1"

View file

@ -0,0 +1,2 @@
{ here, ... }:
here.sibl1