From 2746f3de5cef06eb221e854eca2cc1789665a2a0 Mon Sep 17 00:00:00 2001 From: Lyn Date: Mon, 16 Sep 2024 00:10:42 +0200 Subject: [PATCH] no worky :( --- flake.lock | 6 +-- flake.nix | 6 ++- hosts/forgejo-ci/default.nix | 4 +- meta/default.nix | 8 +++ meta/enable.nix | 9 ++-- meta/lib.nix | 16 ++++++ meta/mkLocalModule.nix | 4 +- modules-extracted.nix | 100 +++++++++++++++++++++++++++++++++++ modules/test/example.nix | 6 +++ test.nix | 91 +++++++++++++++++++++++++++++++ 10 files changed, 237 insertions(+), 13 deletions(-) create mode 100644 meta/default.nix create mode 100644 meta/lib.nix create mode 100644 modules-extracted.nix create mode 100644 modules/test/example.nix create mode 100644 test.nix diff --git a/flake.lock b/flake.lock index 7ca4cde..aeb4f5c 100644 --- a/flake.lock +++ b/flake.lock @@ -34,11 +34,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1725432240, - "narHash": "sha256-+yj+xgsfZaErbfYM3T+QvEE2hU7UuE+Jf0fJCJ8uPS0=", + "lastModified": 1725634671, + "narHash": "sha256-v3rIhsJBOMLR8e/RNWxr828tB+WywYIoajrZKFM+0Gg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ad416d066ca1222956472ab7d0555a6946746a80", + "rev": "574d1eac1c200690e27b8eb4e24887f8df7ac27c", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 2109647..93e6c23 100644 --- a/flake.nix +++ b/flake.nix @@ -6,7 +6,9 @@ nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; }; outputs = {self, nixpkgs, nixpkgs-unstable, sops-nix }@inputs: let - + imports = [ + ./meta + ]; passInputs = ({lib,config,...}:{ options.inputs = lib.mkOption{type = lib.types.attrs;}; config.inputs = inputs; @@ -22,6 +24,7 @@ "forgejo" = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ + ./meta ./hosts/forgenite sops-nix.nixosModules.sops passInputs @@ -31,6 +34,7 @@ system = "x86_64-linux"; modules = [ ./hosts/forgejo-ci + ./meta sops-nix.nixosModules.sops passInputs ]; diff --git a/hosts/forgejo-ci/default.nix b/hosts/forgejo-ci/default.nix index 5ccee1e..f60ba1a 100644 --- a/hosts/forgejo-ci/default.nix +++ b/hosts/forgejo-ci/default.nix @@ -1,4 +1,4 @@ -{ config, pkgs, lib, inputs, ... }: { +{ config, pkgs, lib, inputs, ... }: with config.lyn.lib; { imports = [ ./../../services/forgejo-ci.nix @@ -8,7 +8,7 @@ ./../../meta/profiles/vm.nix ]; lyn.sops.secrets."hosts/forgejo-ci/forgejo_ci_token" = {}; - lyn.kernel = enable ["latest" "hardened"]; + #lyn.kernel = enable ["latest" "hardened"]; # Use UEFI boot.loader.systemd-boot.enable = true; diff --git a/meta/default.nix b/meta/default.nix new file mode 100644 index 0000000..6511e22 --- /dev/null +++ b/meta/default.nix @@ -0,0 +1,8 @@ +{ + imports = [ + ./mkLocalModule.nix + ./enable.nix + ./lib.nix + ]; +} + diff --git a/meta/enable.nix b/meta/enable.nix index 0f129b0..a7ecc46 100644 --- a/meta/enable.nix +++ b/meta/enable.nix @@ -1,8 +1,7 @@ {lib, config, ...}: { - lib.meta.enable = list: lib.genAttrs + config.lyn.lib.enable = list: lib.genAttrs list - (name: - ${name}.enable = true; - ) - ; + ( + name: {enable = true;} + ); } diff --git a/meta/lib.nix b/meta/lib.nix new file mode 100644 index 0000000..4a68a87 --- /dev/null +++ b/meta/lib.nix @@ -0,0 +1,16 @@ +{lib, config, ...}: { + options.lyn = { + lib = lib.mkOption { + type = lib.types.attrs; + default = {}; + }; + prelude = lib.mkOption { + type = lib.types.attrs; + default = {}; + }; + }; + config = { + lyn.prelude.llib = config.lyn.lib; + }; +} + diff --git a/meta/mkLocalModule.nix b/meta/mkLocalModule.nix index 23d1610..19b5d41 100644 --- a/meta/mkLocalModule.nix +++ b/meta/mkLocalModule.nix @@ -26,7 +26,7 @@ ``` */ mkLocalModuleMarker = marker: prefix: currentPath: optDesc: moduleConfig: let - normalizedPath = removeSuffix ".nix" (builtins.toString currentPath); + normalizedPath = lib.strings.removeSuffix ".nix" (builtins.toString currentPath); attrPath = prefix ++ (splitAfterMarker "/" marker normalizedPath); mod = {config, ...}: { options = lib.setAttrsByPath attrPath (lib.mkEnableOption optDesc); @@ -46,7 +46,7 @@ findFolderWithFile = file: arg: if builtins.pathExists (arg + "/" + file) then arg else if arg == /. then throw "could not find folder containing ${file}" - else findRoot file (arg + "/.."); + else findFolderWithFile file (arg + "/.."); /** Shorthand for mkLocalModuleMarker, setting marker to your flake and prefix to l. */ diff --git a/modules-extracted.nix b/modules-extracted.nix new file mode 100644 index 0000000..ea55c2e --- /dev/null +++ b/modules-extracted.nix @@ -0,0 +1,100 @@ +# https://github.com/NixOS/nixpkgs/blob/a5cfe012401cfebb4b2c28e74857b8ffe1402b4b/lib/modules.nix +{ lib }: +with lib.modules; +let + inherit (lib) + addErrorContext + all + any + attrByPath + attrNames + catAttrs + concatLists + concatMap + concatStringsSep + elem + filter + foldl' + functionArgs + getAttrFromPath + genericClosure + head + id + imap1 + isAttrs + isBool + isFunction + isInOldestRelease + isList + isString + length + mapAttrs + mapAttrsToList + mapAttrsRecursiveCond + min + optional + optionalAttrs + optionalString + recursiveUpdate + reverseList sort + seq + setAttrByPath + substring + throwIfNot + trace + typeOf + types + unsafeGetAttrPos + warn + warnIf + zipAttrs + zipAttrsWith + ; + inherit (lib.options) + isOption + mkOption + showDefs + showFiles + showOption + unknownModule + ; + inherit (lib.strings) + isConvertibleWithToString + ; + + unifyModuleSyntax = file: key: m: + let + addMeta = config: if m ? meta + then mkMerge [ config { meta = m.meta; } ] + else config; + addFreeformType = config: if m ? freeformType + then mkMerge [ config { _module.freeformType = m.freeformType; } ] + else config; + in + if m ? config || m ? options then + let badAttrs = removeAttrs m ["_class" "_file" "key" "disabledModules" "imports" "options" "config" "meta" "freeformType"]; in + if badAttrs != {} then + throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'. This is caused by introducing a top-level `config' or `options' attribute. Add configuration attributes immediately on the top level instead, or move all of them (namely: ${toString (attrNames badAttrs)}) into the explicit `config' attribute." + else + { _file = toString m._file or file; + _class = m._class or null; + key = toString m.key or key; + disabledModules = m.disabledModules or []; + imports = m.imports or []; + options = m.options or {}; + config = addFreeformType (addMeta (m.config or {})); + } + else + # shorthand syntax + throwIfNot (isAttrs m) "module ${file} (${key}) does not look like a module." + { _file = toString m._file or file; + _class = m._class or null; + key = toString m.key or key; + disabledModules = m.disabledModules or []; + imports = m.require or [] ++ m.imports or []; + options = {}; + config = addFreeformType (removeAttrs m ["_class" "_file" "key" "disabledModules" "require" "imports" "freeformType"]); + }; + + +in {inherit unifyModuleSyntax;} diff --git a/modules/test/example.nix b/modules/test/example.nix new file mode 100644 index 0000000..448002a --- /dev/null +++ b/modules/test/example.nix @@ -0,0 +1,6 @@ +{config, cfg, lib, ...}: { + #mod.desc = "an example"; + options.networking.hostName = lib.mkOption { default = "nixos"; }; + opt.name = lib.mkOption { default = "foo"; }; + config.networking.hostName = cfg.name; +} diff --git a/test.nix b/test.nix new file mode 100644 index 0000000..8821bbf --- /dev/null +++ b/test.nix @@ -0,0 +1,91 @@ +let + flake = builtins.getFlake "/home/lyn/flake"; + pkgs = import flake.inputs.nixpkgs {}; + lib = pkgs.lib; + + mapAttrKVs = mapFn: attrs: builtins.foldl' (acc: cur: acc // {${cur.key} = cur.value;}) {} (builtins.attrValues (builtins.mapAttrs mapFn attrs)); + #kv = key: value: {inherit key value;}; + recurseNaive = curPath: fn: mapAttrKVs (k: v: let + match = builtins.match "(.*)[.]nix" k; + in if v == "regular" && match != null then {key = builtins.elemAt match 0; value = fn (curPath + ("/" + k));} + else if v == "directory" then {key = k; value = recurseNaive (curPath + ("/" + k)) fn;} + else {key = null; value = null;} + ) (builtins.readDir curPath); + + getAttrKVsRec = prefix: as: pkgs.lib.flatten (pkgs.lib.mapAttrsToList (k: v: + if pkgs.lib.isAttrs v then getAttrKVsRec (prefix ++ [k]) v + else [{path = prefix ++ [k]; value = v;}] + ) as); + + getPathKVsRec = prefix: dir: getAttrKVsRec prefix (lib.packagesFromDirectoryRecursive { callPackage = path: x: path; directory = dir; }); + + unifyMod = (import ./modules-extracted.nix {lib = lib;}).unifyModuleSyntax; + transformLocalMod = {path, value}: p: let + param = p // { + cfg = lib.getAttrFromPath path p.config; + }; + + pathStr = builtins.concatStringsSep "." path; + modFn = p: let i = import value; in if lib.isFunction i then i p else i; + modUni = unifyMod pathStr pathStr (builtins.removeAttrs modRaw ["opt" "mod"]); + + meta = modRaw.mod or {}; + fileCtx = str: "${modUni._file} (mkLocalMods ${str})"; + enablePath = path ++ ["enable"]; + + merge = cur: upd: + + runExts = exts: let + nul = x: rec { + # First pass + args = p; # Args to call the module with. This immediately changes the params of `raw`, `mod` etc. through Nix magic + deletedKeys = ["opt" "mod"]; # Keys to delete before calling unifyModuleSyntax + + # Second pass + imports = {}; # Put any modules to import as *attributes* here (for other extensions to modify them) + raw = modFn x.args; # The raw module result, called with `args` + mod = unifyMod pathStr pathStr (builtins.removeAttrs raw x.deletedKeys); # The unified module, e.g. the result of `unifyModuleSyntax .. .. raw`, and has the default module attrs + meta = raw.mod or {}; # Equivalent to raw.mod, contains metadata of the module + }; + firstPass = builtins.foldl' (acc: ext: + builtins.foldl' (acc: ext: let + acc' = acc // (let acc2 = (ext acc) // acc; in rec { + raw = modFn acc2.args; + mod = unifyMod pathStr pathStr (builtins.removeAttrs raw acc2.deletedKeys); + meta = raw.mod or {}; + }); + res = lib.recursiveUpdate acc' (ext acc'); + in res) exts + + addMod = c: ctx: newMod: { mod.imports = c.mod.imports ++ [ (newMod // {_file = fileCtx ctx;}) ]; }; + + defaultExtensions = [ + (c: { imports.opt = { + name = "`opt` processor"; + options = lib.setAttrByPath c.path raw.opt; + };}) + (c: { imports.enable = { + name "`enable` definition"; + opt.enable = lib.mkEnableOption (c.meta.desc or c.meta.description or c.meta.name or pathStr); + };}) + (c: { + + }) + ] + + imports = [ { + _file = fileCtx "`opt` processor"; + options = lib.setAttrByPath path modRaw.opt; + } { + _file = fileCtx "`enable` definition"; + options = lib.setAttrByPath enablePath (lib.mkEnableOption (mod.desc or mod.description or mod.name or pathStr)); + } ({config, ...}: { + _file = fileCtx "config wrapper"; + config = lib.mkIf (lib.getAttrFromPath enablePath config) modUni.config; + }) ]; + + newMod = modUni // { imports = modUni.imports ++ imports; config = {}; }; + in newMod; + + mkLocalMods = {prefix ? [], dir}: { _file = "mkLocalMods collector"; imports = builtins.map transformLocalMod (getPathKVsRec prefix dir); }; +in cfg: (pkgs.lib.evalModules { modules = [ (mkLocalMods {prefix = ["lyn"]; dir = ./modules;}) cfg ]; })