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:
commit
2426d6ad20
4 changed files with 159 additions and 135 deletions
20
flake.nix
20
flake.nix
|
@ -21,7 +21,19 @@
|
|||
forAllSystems = nixpkgs.lib.genAttrs ["x86_64-linux" "aarch64-linux"];
|
||||
in {
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -85,5 +97,11 @@
|
|||
'';
|
||||
}
|
||||
);
|
||||
|
||||
hjem-lib = forAllSystems (system:
|
||||
import ./lib.nix {
|
||||
inherit (nixpkgs) lib;
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
246
lib.nix
246
lib.nix
|
@ -1,147 +1,147 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
osOptions,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (builtins) isList;
|
||||
inherit (lib.modules) mkDefault mkDerivedConfig mkIf mkMerge;
|
||||
inherit (lib.options) literalExpression mkEnableOption mkOption;
|
||||
inherit (lib.strings) concatMapStringsSep hasPrefix;
|
||||
inherit (lib.types) addCheck anything attrsOf bool either functionTo lines nullOr path str submodule;
|
||||
cfg = config;
|
||||
inherit (lib.types) addCheck anything attrsOf bool either functionTo int lines listOf nullOr oneOf path str submodule;
|
||||
in {
|
||||
_module.args.hjem = {
|
||||
envVarType = osOptions.environment.variables.type;
|
||||
# inlined from https://github.com/NixOS/nixpkgs/tree/master/nixos/modules/config/shells-environment.nix
|
||||
# using osOptions precludes using hjem (or this type) standalone
|
||||
envVarType = attrsOf (nullOr (oneOf [(listOf (oneOf [int str path])) int str path]));
|
||||
|
||||
fileTypeRelativeTo = rootDir:
|
||||
submodule ({
|
||||
name,
|
||||
target,
|
||||
config,
|
||||
options,
|
||||
...
|
||||
}: {
|
||||
options = {
|
||||
enable =
|
||||
mkEnableOption "creation of this file"
|
||||
// {
|
||||
default = true;
|
||||
example = false;
|
||||
};
|
||||
|
||||
target = mkOption {
|
||||
type = str;
|
||||
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`.
|
||||
'';
|
||||
fileTypeRelativeTo = {
|
||||
rootDir,
|
||||
clobberDefault,
|
||||
clobberDefaultText,
|
||||
}:
|
||||
submodule ({
|
||||
name,
|
||||
target,
|
||||
config,
|
||||
options,
|
||||
...
|
||||
}: {
|
||||
options = {
|
||||
enable =
|
||||
mkEnableOption "creation of this file"
|
||||
// {
|
||||
default = true;
|
||||
example = false;
|
||||
};
|
||||
|
||||
text = mkOption {
|
||||
default = null;
|
||||
type = nullOr lines;
|
||||
description = "Text of the file";
|
||||
};
|
||||
target = mkOption {
|
||||
type = str;
|
||||
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`.
|
||||
'';
|
||||
};
|
||||
|
||||
source = mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
description = "Path of the source file or directory";
|
||||
};
|
||||
text = mkOption {
|
||||
default = null;
|
||||
type = nullOr lines;
|
||||
description = "Text of the file";
|
||||
};
|
||||
|
||||
generator = lib.mkOption {
|
||||
# functionTo doesn't actually check the return type, so do that ourselves
|
||||
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.
|
||||
source = mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
description = "Path of the source file or directory";
|
||||
};
|
||||
|
||||
Detection is automatic, as we check if the `generator` generates a derivation or a string after applying to `value`.
|
||||
'';
|
||||
example = literalExpression "lib.generators.toGitINI";
|
||||
};
|
||||
generator = lib.mkOption {
|
||||
# functionTo doesn't actually check the return type, so do that ourselves
|
||||
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 {
|
||||
type = nullOr (attrsOf anything);
|
||||
default = null;
|
||||
description = "Value passed to the `generator`.";
|
||||
example = {
|
||||
user.email = "me@example.com";
|
||||
};
|
||||
};
|
||||
Detection is automatic, as we check if the `generator` generates a derivation or a string after applying to `value`.
|
||||
'';
|
||||
example = literalExpression "lib.generators.toGitINI";
|
||||
};
|
||||
|
||||
executable = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Whether to set the execute bit on the target file.
|
||||
'';
|
||||
};
|
||||
|
||||
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;
|
||||
value = lib.mkOption {
|
||||
type = nullOr (attrsOf anything);
|
||||
default = null;
|
||||
description = "Value passed to the `generator`.";
|
||||
example = {
|
||||
user.email = "me@example.com";
|
||||
};
|
||||
};
|
||||
|
||||
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;
|
||||
}));
|
||||
}
|
||||
executable = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Whether to set the execute bit on the target file.
|
||||
'';
|
||||
};
|
||||
|
||||
(lib.mkIf (hasGenerator && generatesDrv) {
|
||||
source = mkDefault generatedValue;
|
||||
})
|
||||
clobber = mkOption {
|
||||
type = bool;
|
||||
default = clobberDefault;
|
||||
defaultText = clobberDefaultText;
|
||||
description = ''
|
||||
Whether to "clobber" existing target paths.
|
||||
|
||||
(lib.mkIf (hasGenerator && generatesStr) {
|
||||
text = mkDefault generatedValue;
|
||||
})
|
||||
];
|
||||
});
|
||||
- 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`.
|
||||
'';
|
||||
};
|
||||
|
||||
toEnv = env:
|
||||
if isList env
|
||||
then concatMapStringsSep ":" toString env
|
||||
else toString env;
|
||||
};
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -4,13 +4,14 @@
|
|||
# be avoided here.
|
||||
{
|
||||
config,
|
||||
hjem,
|
||||
hjem-lib,
|
||||
lib,
|
||||
name,
|
||||
options,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (hjem) envVarType fileTypeRelativeTo toEnv;
|
||||
inherit (hjem-lib) envVarType toEnv;
|
||||
inherit (lib.attrsets) mapAttrsToList;
|
||||
inherit (lib.strings) concatLines;
|
||||
inherit (lib.modules) mkIf;
|
||||
|
@ -18,13 +19,17 @@
|
|||
inherit (lib.types) attrsOf bool listOf package path str;
|
||||
|
||||
cfg = config;
|
||||
fileTypeRelativeTo' = rootDir:
|
||||
hjem-lib.fileTypeRelativeTo {
|
||||
inherit rootDir;
|
||||
clobberDefault = cfg.clobberFiles;
|
||||
clobberDefaultText = literalExpression "config.hjem.users.${name}.clobberFiles";
|
||||
};
|
||||
in {
|
||||
imports = [
|
||||
# Makes "assertions" option available without having to duplicate the work
|
||||
# already done in the Nixpkgs module.
|
||||
(pkgs.path + "/nixos/modules/misc/assertions.nix")
|
||||
|
||||
../../lib.nix
|
||||
];
|
||||
|
||||
options = {
|
||||
|
@ -63,7 +68,7 @@ in {
|
|||
|
||||
files = mkOption {
|
||||
default = {};
|
||||
type = attrsOf (fileTypeRelativeTo cfg.directory);
|
||||
type = attrsOf (fileTypeRelativeTo' cfg.directory);
|
||||
example = {".config/foo.txt".source = "Hello World";};
|
||||
description = "Files to be managed by Hjem";
|
||||
};
|
||||
|
@ -84,7 +89,7 @@ in {
|
|||
};
|
||||
files = mkOption {
|
||||
default = {};
|
||||
type = attrsOf (fileTypeRelativeTo cfg.xdg.cache.directory);
|
||||
type = attrsOf (fileTypeRelativeTo' cfg.xdg.cache.directory);
|
||||
example = {"foo.txt".source = "Hello World";};
|
||||
description = "Cache files to be managed by Hjem";
|
||||
};
|
||||
|
@ -105,7 +110,7 @@ in {
|
|||
};
|
||||
files = mkOption {
|
||||
default = {};
|
||||
type = attrsOf (fileTypeRelativeTo cfg.xdg.config.directory);
|
||||
type = attrsOf (fileTypeRelativeTo' cfg.xdg.config.directory);
|
||||
example = {"foo.txt".source = "Hello World";};
|
||||
description = "Config files to be managed by Hjem";
|
||||
};
|
||||
|
@ -126,7 +131,7 @@ in {
|
|||
};
|
||||
files = mkOption {
|
||||
default = {};
|
||||
type = attrsOf (fileTypeRelativeTo cfg.xdg.data.directory);
|
||||
type = attrsOf (fileTypeRelativeTo' cfg.xdg.data.directory);
|
||||
example = {"foo.txt".source = "Hello World";};
|
||||
description = "data files to be managed by Hjem";
|
||||
};
|
||||
|
@ -147,7 +152,7 @@ in {
|
|||
};
|
||||
files = mkOption {
|
||||
default = {};
|
||||
type = attrsOf (fileTypeRelativeTo cfg.xdg.state.directory);
|
||||
type = attrsOf (fileTypeRelativeTo' cfg.xdg.state.directory);
|
||||
example = {"foo.txt".source = "Hello World";};
|
||||
description = "state files to be managed by Hjem";
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
config,
|
||||
hjem-lib,
|
||||
lib,
|
||||
options,
|
||||
pkgs,
|
||||
|
@ -10,7 +11,7 @@
|
|||
inherit (lib.options) literalExpression mkOption;
|
||||
inherit (lib.strings) optionalString;
|
||||
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 (builtins) filter attrNames attrValues mapAttrs getAttr concatLists concatStringsSep typeOf toJSON concatMap;
|
||||
|
||||
|
@ -78,7 +79,7 @@
|
|||
specialArgs =
|
||||
cfg.specialArgs
|
||||
// {
|
||||
inherit pkgs;
|
||||
inherit hjem-lib pkgs;
|
||||
osConfig = config;
|
||||
osOptions = options;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue