1
Fork 0
mirror of https://github.com/RGBCube/hjem synced 2025-10-13 13:12:16 +00:00

Merge pull request #54 from feel-co/liberate-lib

lib: liberate from the module system
This commit is contained in:
éclairevoyant 2025-08-27 00:42:08 +00:00 committed by GitHub
commit 2426d6ad20
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 159 additions and 135 deletions

View file

@ -21,7 +21,19 @@
forAllSystems = nixpkgs.lib.genAttrs ["x86_64-linux" "aarch64-linux"]; forAllSystems = nixpkgs.lib.genAttrs ["x86_64-linux" "aarch64-linux"];
in { in {
nixosModules = { nixosModules = {
hjem = ./modules/nixos; hjem = {
imports = [
self.nixosModules.hjem-lib
./modules/nixos
];
};
hjem-lib = {
lib,
pkgs,
...
}: {
_module.args.hjem-lib = import ./lib.nix {inherit lib pkgs;};
};
default = self.nixosModules.hjem; default = self.nixosModules.hjem;
}; };
@ -85,5 +97,11 @@
''; '';
} }
); );
hjem-lib = forAllSystems (system:
import ./lib.nix {
inherit (nixpkgs) lib;
pkgs = nixpkgs.legacyPackages.${system};
});
}; };
} }

246
lib.nix
View file

@ -1,147 +1,147 @@
{ {
config,
lib, lib,
osOptions,
pkgs, pkgs,
...
}: let }: let
inherit (builtins) isList; inherit (builtins) isList;
inherit (lib.modules) mkDefault mkDerivedConfig mkIf mkMerge; inherit (lib.modules) mkDefault mkDerivedConfig mkIf mkMerge;
inherit (lib.options) literalExpression mkEnableOption mkOption; inherit (lib.options) literalExpression mkEnableOption mkOption;
inherit (lib.strings) concatMapStringsSep hasPrefix; inherit (lib.strings) concatMapStringsSep hasPrefix;
inherit (lib.types) addCheck anything attrsOf bool either functionTo lines nullOr path str submodule; inherit (lib.types) addCheck anything attrsOf bool either functionTo int lines listOf nullOr oneOf path str submodule;
cfg = config;
in { in {
_module.args.hjem = { # inlined from https://github.com/NixOS/nixpkgs/tree/master/nixos/modules/config/shells-environment.nix
envVarType = osOptions.environment.variables.type; # using osOptions precludes using hjem (or this type) standalone
envVarType = attrsOf (nullOr (oneOf [(listOf (oneOf [int str path])) int str path]));
fileTypeRelativeTo = rootDir: fileTypeRelativeTo = {
submodule ({ rootDir,
name, clobberDefault,
target, clobberDefaultText,
config, }:
options, submodule ({
... name,
}: { target,
options = { config,
enable = options,
mkEnableOption "creation of this file" ...
// { }: {
default = true; options = {
example = false; enable =
}; mkEnableOption "creation of this file"
// {
target = mkOption { default = true;
type = str; example = false;
apply = p:
if hasPrefix "/" p
then throw "This option cannot handle absolute paths yet!"
else "${config.relativeTo}/${p}";
defaultText = "name";
description = ''
Path to target file relative to {option}`hjem.users.<name>.files.<file>.relativeTo`.
'';
}; };
text = mkOption { target = mkOption {
default = null; type = str;
type = nullOr lines; apply = p:
description = "Text of the file"; if hasPrefix "/" p
}; then throw "This option cannot handle absolute paths yet!"
else "${config.relativeTo}/${p}";
defaultText = "name";
description = ''
Path to target file relative to {option}`hjem.users.<name>.files.<file>.relativeTo`.
'';
};
source = mkOption { text = mkOption {
type = nullOr path; default = null;
default = null; type = nullOr lines;
description = "Path of the source file or directory"; description = "Text of the file";
}; };
generator = lib.mkOption { source = mkOption {
# functionTo doesn't actually check the return type, so do that ourselves type = nullOr path;
type = addCheck (nullOr (functionTo (either options.source.type options.text.type))) (x: let default = null;
generatedValue = x config.value; description = "Path of the source file or directory";
generatesDrv = options.source.type.check generatedValue; };
generatesStr = options.text.type.check generatedValue;
in
x != null -> (generatesDrv || generatesStr));
default = null;
description = ''
Function that when applied to `value` will create the `source` or `text` of the file.
Detection is automatic, as we check if the `generator` generates a derivation or a string after applying to `value`. generator = lib.mkOption {
''; # functionTo doesn't actually check the return type, so do that ourselves
example = literalExpression "lib.generators.toGitINI"; type = addCheck (nullOr (functionTo (either options.source.type options.text.type))) (x: let
}; generatedValue = x config.value;
generatesDrv = options.source.type.check generatedValue;
generatesStr = options.text.type.check generatedValue;
in
x != null -> (generatesDrv || generatesStr));
default = null;
description = ''
Function that when applied to `value` will create the `source` or `text` of the file.
value = lib.mkOption { Detection is automatic, as we check if the `generator` generates a derivation or a string after applying to `value`.
type = nullOr (attrsOf anything); '';
default = null; example = literalExpression "lib.generators.toGitINI";
description = "Value passed to the `generator`."; };
example = {
user.email = "me@example.com";
};
};
executable = mkOption { value = lib.mkOption {
type = bool; type = nullOr (attrsOf anything);
default = false; default = null;
example = true; description = "Value passed to the `generator`.";
description = '' example = {
Whether to set the execute bit on the target file. user.email = "me@example.com";
'';
};
clobber = mkOption {
type = bool;
default = cfg.clobberFiles;
defaultText = literalExpression "config.hjem.clobberByDefault";
description = ''
Whether to "clobber" existing target paths.
- If using the **systemd-tmpfiles** hook (Linux only), tmpfile rules
will be constructed with `L+` (*re*create) instead of `L`
(create) type while this is set to `true`.
'';
};
relativeTo = mkOption {
internal = true;
type = path;
default = rootDir;
description = "Path to which symlinks will be relative to";
apply = x:
assert (hasPrefix "/" x || abort "Relative path ${x} cannot be used for files.<file>.relativeTo"); x;
}; };
}; };
config = let executable = mkOption {
generatedValue = config.generator config.value; type = bool;
hasGenerator = config.generator != null; default = false;
generatesDrv = options.source.type.check generatedValue; example = true;
generatesStr = options.text.type.check generatedValue; description = ''
in Whether to set the execute bit on the target file.
mkMerge [ '';
{ };
target = mkDefault name;
source = mkIf (config.text != null) (mkDerivedConfig options.text (text:
pkgs.writeTextFile {
inherit name text;
inherit (config) executable;
}));
}
(lib.mkIf (hasGenerator && generatesDrv) { clobber = mkOption {
source = mkDefault generatedValue; type = bool;
}) default = clobberDefault;
defaultText = clobberDefaultText;
description = ''
Whether to "clobber" existing target paths.
(lib.mkIf (hasGenerator && generatesStr) { - If using the **systemd-tmpfiles** hook (Linux only), tmpfile rules
text = mkDefault generatedValue; will be constructed with `L+` (*re*create) instead of `L`
}) (create) type while this is set to `true`.
]; '';
}); };
toEnv = env: relativeTo = mkOption {
if isList env internal = true;
then concatMapStringsSep ":" toString env type = path;
else toString env; default = rootDir;
}; description = "Path to which symlinks will be relative to";
apply = x:
assert (hasPrefix "/" x || abort "Relative path ${x} cannot be used for files.<file>.relativeTo"); x;
};
};
config = let
generatedValue = config.generator config.value;
hasGenerator = config.generator != null;
generatesDrv = options.source.type.check generatedValue;
generatesStr = options.text.type.check generatedValue;
in
mkMerge [
{
target = mkDefault name;
source = mkIf (config.text != null) (mkDerivedConfig options.text (text:
pkgs.writeTextFile {
inherit name text;
inherit (config) executable;
}));
}
(lib.mkIf (hasGenerator && generatesDrv) {
source = mkDefault generatedValue;
})
(lib.mkIf (hasGenerator && generatesStr) {
text = mkDefault generatedValue;
})
];
});
toEnv = env:
if isList env
then concatMapStringsSep ":" toString env
else toString env;
} }

View file

@ -4,13 +4,14 @@
# be avoided here. # be avoided here.
{ {
config, config,
hjem, hjem-lib,
lib, lib,
name,
options, options,
pkgs, pkgs,
... ...
}: let }: let
inherit (hjem) envVarType fileTypeRelativeTo toEnv; inherit (hjem-lib) envVarType toEnv;
inherit (lib.attrsets) mapAttrsToList; inherit (lib.attrsets) mapAttrsToList;
inherit (lib.strings) concatLines; inherit (lib.strings) concatLines;
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
@ -18,13 +19,17 @@
inherit (lib.types) attrsOf bool listOf package path str; inherit (lib.types) attrsOf bool listOf package path str;
cfg = config; cfg = config;
fileTypeRelativeTo' = rootDir:
hjem-lib.fileTypeRelativeTo {
inherit rootDir;
clobberDefault = cfg.clobberFiles;
clobberDefaultText = literalExpression "config.hjem.users.${name}.clobberFiles";
};
in { in {
imports = [ imports = [
# Makes "assertions" option available without having to duplicate the work # Makes "assertions" option available without having to duplicate the work
# already done in the Nixpkgs module. # already done in the Nixpkgs module.
(pkgs.path + "/nixos/modules/misc/assertions.nix") (pkgs.path + "/nixos/modules/misc/assertions.nix")
../../lib.nix
]; ];
options = { options = {
@ -63,7 +68,7 @@ in {
files = mkOption { files = mkOption {
default = {}; default = {};
type = attrsOf (fileTypeRelativeTo cfg.directory); type = attrsOf (fileTypeRelativeTo' cfg.directory);
example = {".config/foo.txt".source = "Hello World";}; example = {".config/foo.txt".source = "Hello World";};
description = "Files to be managed by Hjem"; description = "Files to be managed by Hjem";
}; };
@ -84,7 +89,7 @@ in {
}; };
files = mkOption { files = mkOption {
default = {}; default = {};
type = attrsOf (fileTypeRelativeTo cfg.xdg.cache.directory); type = attrsOf (fileTypeRelativeTo' cfg.xdg.cache.directory);
example = {"foo.txt".source = "Hello World";}; example = {"foo.txt".source = "Hello World";};
description = "Cache files to be managed by Hjem"; description = "Cache files to be managed by Hjem";
}; };
@ -105,7 +110,7 @@ in {
}; };
files = mkOption { files = mkOption {
default = {}; default = {};
type = attrsOf (fileTypeRelativeTo cfg.xdg.config.directory); type = attrsOf (fileTypeRelativeTo' cfg.xdg.config.directory);
example = {"foo.txt".source = "Hello World";}; example = {"foo.txt".source = "Hello World";};
description = "Config files to be managed by Hjem"; description = "Config files to be managed by Hjem";
}; };
@ -126,7 +131,7 @@ in {
}; };
files = mkOption { files = mkOption {
default = {}; default = {};
type = attrsOf (fileTypeRelativeTo cfg.xdg.data.directory); type = attrsOf (fileTypeRelativeTo' cfg.xdg.data.directory);
example = {"foo.txt".source = "Hello World";}; example = {"foo.txt".source = "Hello World";};
description = "data files to be managed by Hjem"; description = "data files to be managed by Hjem";
}; };
@ -147,7 +152,7 @@ in {
}; };
files = mkOption { files = mkOption {
default = {}; default = {};
type = attrsOf (fileTypeRelativeTo cfg.xdg.state.directory); type = attrsOf (fileTypeRelativeTo' cfg.xdg.state.directory);
example = {"foo.txt".source = "Hello World";}; example = {"foo.txt".source = "Hello World";};
description = "state files to be managed by Hjem"; description = "state files to be managed by Hjem";
}; };

View file

@ -1,5 +1,6 @@
{ {
config, config,
hjem-lib,
lib, lib,
options, options,
pkgs, pkgs,
@ -10,7 +11,7 @@
inherit (lib.options) literalExpression mkOption; inherit (lib.options) literalExpression mkOption;
inherit (lib.strings) optionalString; inherit (lib.strings) optionalString;
inherit (lib.trivial) pipe; inherit (lib.trivial) pipe;
inherit (lib.types) attrs attrsOf bool listOf nullOr package raw submoduleWith either singleLineStr; inherit (lib.types) attrs attrsOf bool either listOf nullOr package raw singleLineStr submoduleWith;
inherit (lib.meta) getExe; inherit (lib.meta) getExe;
inherit (builtins) filter attrNames attrValues mapAttrs getAttr concatLists concatStringsSep typeOf toJSON concatMap; inherit (builtins) filter attrNames attrValues mapAttrs getAttr concatLists concatStringsSep typeOf toJSON concatMap;
@ -78,7 +79,7 @@
specialArgs = specialArgs =
cfg.specialArgs cfg.specialArgs
// { // {
inherit pkgs; inherit hjem-lib pkgs;
osConfig = config; osConfig = config;
osOptions = options; osOptions = options;
}; };