summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-12-19 17:44:04 +0100
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-12-19 17:44:04 +0100
commit1021c1ffe1dd8dd75380dac618b93ff2cefd81f4 (patch)
treee8149b2e3cb0350d680c661fa390520ff9ca0863
downloadnix-library-1021c1ffe1dd8dd75380dac618b93ff2cefd81f4.zip
chore: Initial Commit
-rw-r--r--by-name-overlay.nix76
-rw-r--r--default.nix42
-rw-r--r--flake.nix9
3 files changed, 127 insertions, 0 deletions
diff --git a/by-name-overlay.nix b/by-name-overlay.nix
new file mode 100644
index 0000000..4d700a8
--- /dev/null
+++ b/by-name-overlay.nix
@@ -0,0 +1,76 @@
+{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,
+  coImportsNameFunction ? null,
+  coImportsWarnMessageObject ? null,
+}: 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}";
+        coImportPath =
+          if coImportsNameFunction != null
+          then
+            coImportsNameFunction
+            {inherit shard name;}
+          else path;
+      in
+        if builtins.pathExists path
+        then
+          if builtins.pathExists coImportPath
+          then path
+          else warn "'${builtins.toString coImportPath}' does not exist. Should include ${coImportsWarnMessageObject} for '${shard}/${name}'" 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/default.nix b/default.nix
new file mode 100644
index 0000000..cb9f6ef
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,42 @@
+{}: let
+  # string -> string -> string
+  colorize = color: string: "[${color}m${string}";
+
+  # 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 "${colorize "1;35" "evaluation warning:"} ${msg}" v
+    );
+in {
+  mkByName = import ./by-name-overlay.nix {inherit warn;};
+
+  # Warn while merging two attrsets if the RHS shares names with the LHS.
+  # # Example:
+  # ```nix
+  # let
+  # attr1 = {atuin = "first"; default = "second";};
+  # attr2 = {atuin = "hi"; other = "hi2";};
+  # in
+  # warnMerge attr1 attr2 "attr1 core value set"
+  # ```
+  # # Type:
+  # {} -> {} -> string -> {}
+  warnMerge = lhs: rhs: sourceSet: let
+    overridden = builtins.intersectAttrs lhs rhs;
+    merged = lhs // rhs;
+    mkWarning = overriddenAttrs:
+      builtins.concatStringsSep " " (builtins.map (colorize "1;97") (builtins.attrNames overriddenAttrs));
+  in
+    if overridden != {}
+    then
+      warn "Attributes overridden while merging ${sourceSet}: ${mkWarning overridden}"
+      merged
+    else merged;
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..e6f5f4f
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,9 @@
+{
+  inputs = {};
+
+  outputs = _: let
+    lib = import ./default.nix {};
+  in {
+    nixLib = lib;
+  };
+}