Skip to content

Commit c2b76d3

Browse files
authored
feat(lib.types.linkable): type for "ln -s ${v} $out/mylink" (#545)
1 parent d155000 commit c2b76d3

2 files changed

Lines changed: 32 additions & 12 deletions

File tree

lib/types.nix

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,31 @@ in
366366
if builtins.isPath res then builtins.path { path = res; } else res;
367367
};
368368

369+
/**
370+
Allows values that are, or resolve to under interpolation, an absolute-path-like value.
371+
372+
A value is considered linkable if it matches any of the following:
373+
- It is a Nix store path (e.g. `./.`, `"${./.}"` or a derivation)
374+
- It is a plain string that starts with `"/"` and does not contain any newlines
375+
376+
This is useful when wrapping commands that accept file or directory paths,
377+
where you need to distinguish path-like values from other strings.
378+
379+
For example, when you feel like you want `lib.types.either wlib.types.stringable lib.types.lines`
380+
381+
You should instead use `lib.types.either wlib.types.linkable lib.types.lines`
382+
*/
383+
linkable = lib.mkOptionType {
384+
name = "linkable";
385+
descriptionClass = "noun";
386+
description = "absolute path";
387+
inherit (wlib.types.stringable) merge;
388+
check =
389+
x:
390+
lib.isStringLike x
391+
&& (if builtins.isString x then builtins.substring 0 1 x == "/" && !lib.hasInfix "\n" x else true);
392+
};
393+
369394
/**
370395
A single-line, non-empty string
371396
*/

wrapperModules/t/television/module.nix

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,7 @@ let
1111
nullable = false;
1212
typeName = "TOML";
1313
};
14-
isPathLike =
15-
x:
16-
builtins.isPath x
17-
|| (lib.isStringLike x && !builtins.isString x)
18-
|| (builtins.isString x && lib.hasPrefix "/" x)
19-
|| lib.isStorePath x;
14+
isLinkable = wlib.types.linkable.check;
2015
in
2116
{
2217
imports = [ wlib.modules.default ];
@@ -27,7 +22,7 @@ in
2722
description = "Television configuration options.";
2823
};
2924
channels = lib.mkOption {
30-
type = types.lazyAttrsOf (types.either wlib.types.stringable tomlFmtType);
25+
type = types.lazyAttrsOf (types.either wlib.types.linkable tomlFmtType);
3126
default = { };
3227
description = "Television channels to install.";
3328
};
@@ -40,7 +35,7 @@ in
4035
'';
4136
};
4237
themes = lib.mkOption {
43-
type = types.lazyAttrsOf (types.either wlib.types.stringable tomlFmtType);
38+
type = types.lazyAttrsOf (types.either wlib.types.linkable tomlFmtType);
4439
default = { };
4540
description = "Themes of television to install.";
4641
};
@@ -84,17 +79,17 @@ in
8479
key = "channel_${n}";
8580
relPath = lib.mkOverride 0 "${config.binName}-channels/${n}.toml";
8681
output = lib.mkOverride 0 config.configDrvOutput;
87-
${if isPathLike v then null else "content"} = builtins.toJSON v;
82+
${if isLinkable v then null else "content"} = builtins.toJSON v;
8883
"builder" =
89-
if isPathLike v then ''ln -s ${v} "$2"'' else ''${pkgs.remarshal}/bin/json2toml "$1" "$2"'';
84+
if isLinkable v then ''ln -s ${v} "$2"'' else ''${pkgs.remarshal}/bin/json2toml "$1" "$2"'';
9085
}) config.channels
9186
// builtins.mapAttrs (n: v: {
9287
key = "theme_${n}";
9388
relPath = lib.mkOverride 0 "${config.binName}-themes/${n}.toml";
9489
output = lib.mkOverride 0 config.configDrvOutput;
95-
${if isPathLike v then null else "content"} = builtins.toJSON v;
90+
${if isLinkable v then null else "content"} = builtins.toJSON v;
9691
"builder" =
97-
if isPathLike v then ''ln -s ${v} "$2"'' else ''${pkgs.remarshal}/bin/json2toml "$1" "$2"'';
92+
if isLinkable v then ''ln -s ${v} "$2"'' else ''${pkgs.remarshal}/bin/json2toml "$1" "$2"'';
9893
}) config.themes;
9994
meta.maintainers = [ wlib.maintainers.allen-liaoo ];
10095
};

0 commit comments

Comments
 (0)