aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-10-24 14:59:29 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-10-24 14:59:29 +0200
commit0cc353f49f9c5d0e0bd203a6854b488a58daaa96 (patch)
tree48d4a821a842f94e3614f7c310423d9d2c98cc21 /lib
parentrefactor(modules/unison): Migrate to `by-name` and parameterize (diff)
downloadnixos-config-0cc353f49f9c5d0e0bd203a6854b488a58daaa96.zip
refactor({modules,pkgs}/by-name-overlay): De-duplicate in a `nixLib`
Diffstat (limited to '')
-rw-r--r--lib/by-name-overlay.nix65
-rw-r--r--lib/default.nix37
2 files changed, 102 insertions, 0 deletions
diff --git a/lib/by-name-overlay.nix b/lib/by-name-overlay.nix
new file mode 100644
index 00000000..cc8bcb67
--- /dev/null
+++ b/lib/by-name-overlay.nix
@@ -0,0 +1,65 @@
+{warn}:
+# Adapted from this: https://github.com/NixOS/nixpkgs/blob/1814b56453c91192f6d5a6276079948f9fe96c18/pkgs/top-level/by-name-overlay.nix
+# This file should not depend on `pkgs` and thus not use `lib`.
+{
+ baseDirectory,
+ fileName,
+ finalizeFunction,
+}: let
+ # Takes a list of attrs as input and returns one merged attr set.
+ flattenAttrs = list:
+ if builtins.isList list
+ then
+ builtins.foldl' (acc: elem:
+ if builtins.isList elem
+ # Merging them with `//` is okay here, as we can be sure that the attr names are
+ # unique (they were separate dictionary after all)
+ then acc // (flattenAttrs elem)
+ else acc // elem) {}
+ list
+ else list;
+
+ # From nixpkgs/lib {{{
+ # These functions are taken straight out of the `nixpkgs/lib`.
+ # We can't depended on `pkgs` (and thus on `lib`), because the `pkgs` module argument
+ # is only defined in the `nixpkgs` module (which is imported through this function).
+ mapAttrsToList = f: attrs:
+ builtins.map (name: f name attrs.${name}) (builtins.attrNames attrs);
+
+ nameValuePair = name: value: {inherit name value;};
+ filterAttrs = pred: set:
+ builtins.listToAttrs (builtins.concatMap (name: let
+ v = set.${name};
+ in
+ if pred name v
+ then [(nameValuePair name v)]
+ else []) (builtins.attrNames set));
+ # }}}
+
+ # Module files for a single shard
+ # Type: String -> String -> ListOf Path
+ namesForShard = shard: type:
+ if type != "directory"
+ then warn "Ignored non-directory, whilst importing by-name directory (${fileName}): '${shard}'" {}
+ else let
+ mkPath = name: _type: let
+ path = baseDirectory + "/${shard}/${name}" + "/${fileName}";
+ in
+ if builtins.pathExists path
+ then path
+ else warn "'${builtins.toString path}' does not exist. Skipped" null;
+ in
+ filterAttrs (name: value: value != null)
+ (builtins.mapAttrs
+ mkPath
+ (builtins.readDir (baseDirectory + "/${shard}")));
+
+ # A list of all module paths.
+ # These can the be simply injected into `import`
+ files = flattenAttrs (mapAttrsToList namesForShard (builtins.readDir baseDirectory));
+ output =
+ builtins.mapAttrs
+ finalizeFunction
+ files;
+in
+ output
diff --git a/lib/default.nix b/lib/default.nix
new file mode 100644
index 00000000..7c86aba1
--- /dev/null
+++ b/lib/default.nix
@@ -0,0 +1,37 @@
+{}: let
+ # Taken from `nixpkgs/lib`.
+ # Is here to avoid a dependency on `lib` (making this file easy to test with `nix eval`)
+ warn =
+ # Since Nix 2.23, https://github.com/NixOS/nix/pull/10592
+ builtins.warn
+ or (
+ # Do not eta reduce v, so that we have the same strictness as `builtins.warn`.
+ msg: v:
+ # `builtins.warn` requires a string message, so we enforce that in our implementation, so that callers aren't accidentally incompatible with newer Nix versions.
+ assert builtins.isString msg;
+ builtins.trace "evaluation warning: ${msg}" v
+ );
+in {
+ mkByName = import ./by-name-overlay.nix {inherit warn;};
+
+ # Only merge two attrsets if the RHS does not share names with the LHS.
+ # Example:
+ # ```nix
+ # let
+ # attr1 = {atuin = "first"; default = "second";};
+ # attr2 = {atuin = "hi"; other = "hi2";};
+ # in
+ # maybeMerge attr1 attr2 "Failed to merge"
+ # ```
+ maybeMerge = attr1: attr2: message: let
+ list1 = builtins.attrNames attr1;
+
+ check = name2: value:
+ if builtins.elem name2 list1
+ then warn "Overriding ${name2} while merging two attrs sets: ${message}" value
+ else value;
+
+ checkedAttr2 = builtins.mapAttrs check attr2;
+ in
+ attr1 // checkedAttr2;
+}