feat(readTree): Support scoped import arguments

This makes it possible to override Nix builtins within a readTree
structure. Why would you want to do that, you might ask? Well ...

Change-Id: Icc9cb32e5db4a2eba370cf81769c642d237d4937
Reviewed-on: https://cl.tvl.fyi/c/depot/+/3499
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
Vincent Ambo 2021-09-08 18:27:37 +03:00 committed by tazjin
parent aedde913d1
commit b1f4b530ec
2 changed files with 15 additions and 9 deletions

View file

@ -77,6 +77,9 @@ the tree as empty nodes (`{}`).
* `filter`: (optional) A function to filter the argument set on each
import based on the location in the tree. This can be used to, for
example, implement a "visibility" system inside of a tree.
* `scopedArgs`: (optional) An argument set that is passed to all
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

View file

@ -59,9 +59,11 @@ let
# The marker is added to every set that was imported directly by
# readTree.
importWithMark = args: path: parts: filter:
let
importedFile = import path;
importWithMark = args: scopedArgs: path: parts: filter:
let
importedFile = if scopedArgs != {}
then builtins.scopedImport scopedArgs path
else import path;
pathType = builtins.typeOf importedFile;
imported =
assert assertMsg
@ -76,14 +78,14 @@ let
let res = match "(.*)\\.nix" file;
in if res == null then null else head res;
readTree = { args, initPath, rootDir, parts, argsFilter }:
readTree = { args, initPath, rootDir, parts, argsFilter, scopedArgs }:
let
dir = readDirVisible initPath;
joinChild = c: initPath + ("/" + c);
self = if rootDir
then { __readTree = []; }
else importWithMark args initPath parts argsFilter;
else importWithMark args scopedArgs initPath parts argsFilter;
# Import subdirectories of the current one, unless the special
# `.skip-subtree` file exists which makes readTree ignore the
@ -96,7 +98,7 @@ let
children = if hasAttr ".skip-subtree" dir then [] else map (c: {
name = c;
value = readTree {
inherit argsFilter;
inherit argsFilter scopedArgs;
args = args;
initPath = (joinChild c);
rootDir = false;
@ -108,7 +110,7 @@ let
nixFiles = filter (f: f != null) (map nixFileName (attrNames dir));
nixChildren = map (c: let p = joinChild (c + ".nix"); in {
name = c;
value = importWithMark args p (parts ++ [ c ]) argsFilter;
value = importWithMark args scopedArgs p (parts ++ [ c ]) argsFilter;
}) nixFiles;
in if dir ? "default.nix"
then (if isAttrs self then self // (listToAttrs children) else self)
@ -118,9 +120,10 @@ in {
__functor = _:
{ path
, args
, filter ? (x: _parts: x) }:
, filter ? (x: _parts: x)
, scopedArgs ? {} }:
readTree {
inherit args;
inherit args scopedArgs;
argsFilter = filter;
initPath = path;
rootDir = true;