mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-02-21 11:34:13 +00:00
lib/types: add types.pathWith
(#373287)
This commit is contained in:
commit
2f6b75b26a
@ -586,6 +586,42 @@ checkConfigOutput '^38|27$' options.submoduleLine38.declarationPositions.1.line
|
||||
# nested options work
|
||||
checkConfigOutput '^34$' options.nested.nestedLine34.declarationPositions.0.line ./declaration-positions.nix
|
||||
|
||||
# types.pathWith { inStore = true; }
|
||||
checkConfigOutput '".*/store/0lz9p8xhf89kb1c1kk6jxrzskaiygnlh-bash-5.2-p15.drv"' config.pathInStore.ok1 ./pathWith.nix
|
||||
checkConfigOutput '".*/store/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15"' config.pathInStore.ok2 ./pathWith.nix
|
||||
checkConfigOutput '".*/store/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15/bin/bash"' config.pathInStore.ok3 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .* is not of type .path in the Nix store.. Definition values:\n\s*- In .*: ""' config.pathInStore.bad1 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .* is not of type .path in the Nix store.. Definition values:\n\s*- In .*: ".*/store"' config.pathInStore.bad2 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .* is not of type .path in the Nix store.. Definition values:\n\s*- In .*: ".*/store/"' config.pathInStore.bad3 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .* is not of type .path in the Nix store.. Definition values:\n\s*- In .*: ".*/store/.links"' config.pathInStore.bad4 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .* is not of type .path in the Nix store.. Definition values:\n\s*- In .*: "/foo/bar"' config.pathInStore.bad5 ./pathWith.nix
|
||||
|
||||
# types.pathWith { inStore = false; }
|
||||
checkConfigOutput '"/foo/bar"' config.pathNotInStore.ok1 ./pathWith.nix
|
||||
checkConfigOutput '".*/store"' config.pathNotInStore.ok2 ./pathWith.nix
|
||||
checkConfigOutput '".*/store/"' config.pathNotInStore.ok3 ./pathWith.nix
|
||||
checkConfigOutput '""' config.pathNotInStore.ok4 ./pathWith.nix
|
||||
checkConfigOutput '".*/store/.links"' config.pathNotInStore.ok5 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .* is not of type .path not in the Nix store.. Definition values:\n\s*- In .*: ".*/0lz9p8xhf89kb1c1kk6jxrzskaiygnlh-bash-5.2-p15.drv"' config.pathNotInStore.bad1 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .* is not of type .path not in the Nix store.. Definition values:\n\s*- In .*: ".*/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15"' config.pathNotInStore.bad2 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .* is not of type .path not in the Nix store.. Definition values:\n\s*- In .*: ".*/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15/bin/bash"' config.pathNotInStore.bad3 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .* is not of type .path not in the Nix store.. Definition values:\n\s*- In .*: .*/pathWith.nix' config.pathNotInStore.bad4 ./pathWith.nix
|
||||
|
||||
# types.pathWith { }
|
||||
checkConfigOutput '"/this/is/absolute"' config.anyPath.ok1 ./pathWith.nix
|
||||
checkConfigOutput '"./this/is/relative"' config.anyPath.ok2 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .anyPath.bad1. is not of type .path.' config.anyPath.bad1 ./pathWith.nix
|
||||
|
||||
# types.pathWith { absolute = true; }
|
||||
checkConfigOutput '"/this/is/absolute"' config.absolutePathNotInStore.ok1 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .absolutePathNotInStore.bad1. is not of type .absolute path not in the Nix store.' config.absolutePathNotInStore.bad1 ./pathWith.nix
|
||||
checkConfigError 'A definition for option .absolutePathNotInStore.bad2. is not of type .absolute path not in the Nix store.' config.absolutePathNotInStore.bad2 ./pathWith.nix
|
||||
|
||||
# types.pathWith failed type merge
|
||||
checkConfigError 'The option .conflictingPathOptionType. in .*/pathWith.nix. is already declared in .*/pathWith.nix' config.conflictingPathOptionType ./pathWith.nix
|
||||
|
||||
# types.pathWith { inStore = true; absolute = false; }
|
||||
checkConfigError 'In pathWith, inStore means the path must be absolute' config.impossiblePathOptionType ./pathWith.nix
|
||||
|
||||
cat <<EOF
|
||||
====== module tests ======
|
||||
|
88
lib/tests/modules/pathWith.nix
Normal file
88
lib/tests/modules/pathWith.nix
Normal file
@ -0,0 +1,88 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (builtins)
|
||||
storeDir
|
||||
;
|
||||
inherit (lib)
|
||||
types
|
||||
mkOption
|
||||
;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
{
|
||||
options = {
|
||||
pathInStore = mkOption { type = types.lazyAttrsOf (types.pathWith { inStore = true; }); };
|
||||
pathNotInStore = mkOption { type = types.lazyAttrsOf (types.pathWith { inStore = false; }); };
|
||||
anyPath = mkOption { type = types.lazyAttrsOf (types.pathWith { }); };
|
||||
absolutePathNotInStore = mkOption {
|
||||
type = types.lazyAttrsOf (
|
||||
types.pathWith {
|
||||
inStore = false;
|
||||
absolute = true;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
# This conflicts with `conflictingPathOptionType` below.
|
||||
conflictingPathOptionType = mkOption { type = types.pathWith { absolute = true; }; };
|
||||
|
||||
# This doesn't make sense: the only way to have something be `inStore`
|
||||
# is to have an absolute path.
|
||||
impossiblePathOptionType = mkOption {
|
||||
type = types.pathWith {
|
||||
inStore = true;
|
||||
absolute = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
options = {
|
||||
# This should merge cleanly with `pathNotInStore` above.
|
||||
pathNotInStore = mkOption {
|
||||
type = types.lazyAttrsOf (
|
||||
types.pathWith {
|
||||
inStore = false;
|
||||
absolute = null;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
# This conflicts with `conflictingPathOptionType` above.
|
||||
conflictingPathOptionType = mkOption { type = types.pathWith { absolute = false; }; };
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
pathInStore.ok1 = "${storeDir}/0lz9p8xhf89kb1c1kk6jxrzskaiygnlh-bash-5.2-p15.drv";
|
||||
pathInStore.ok2 = "${storeDir}/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15";
|
||||
pathInStore.ok3 = "${storeDir}/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15/bin/bash";
|
||||
pathInStore.bad1 = "";
|
||||
pathInStore.bad2 = "${storeDir}";
|
||||
pathInStore.bad3 = "${storeDir}/";
|
||||
pathInStore.bad4 = "${storeDir}/.links"; # technically true, but not reasonable
|
||||
pathInStore.bad5 = "/foo/bar";
|
||||
|
||||
pathNotInStore.ok1 = "/foo/bar";
|
||||
pathNotInStore.ok2 = "${storeDir}"; # strange, but consistent with `pathInStore` above
|
||||
pathNotInStore.ok3 = "${storeDir}/"; # also strange, but also consistent
|
||||
pathNotInStore.ok4 = "";
|
||||
pathNotInStore.ok5 = "${storeDir}/.links"; # strange, but consistent with `pathInStore` above
|
||||
pathNotInStore.bad1 = "${storeDir}/0lz9p8xhf89kb1c1kk6jxrzskaiygnlh-bash-5.2-p15.drv";
|
||||
pathNotInStore.bad2 = "${storeDir}/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15";
|
||||
pathNotInStore.bad3 = "${storeDir}/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15/bin/bash";
|
||||
pathNotInStore.bad4 = ./pathWith.nix;
|
||||
|
||||
anyPath.ok1 = "/this/is/absolute";
|
||||
anyPath.ok2 = "./this/is/relative";
|
||||
anyPath.bad1 = 42;
|
||||
|
||||
absolutePathNotInStore.ok1 = "/this/is/absolute";
|
||||
absolutePathNotInStore.bad1 = "./this/is/relative";
|
||||
absolutePathNotInStore.bad2 = "${storeDir}/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15";
|
||||
|
||||
conflictingPathOptionType = "/foo/bar";
|
||||
|
||||
impossiblePathOptionType = "/foo/bar";
|
||||
}
|
@ -566,21 +566,48 @@ rec {
|
||||
})
|
||||
(x: (x._type or null) == "pkgs");
|
||||
|
||||
path = mkOptionType {
|
||||
name = "path";
|
||||
descriptionClass = "noun";
|
||||
check = x: isStringLike x && builtins.substring 0 1 (toString x) == "/";
|
||||
merge = mergeEqualOption;
|
||||
path = pathWith {
|
||||
absolute = true;
|
||||
};
|
||||
|
||||
pathInStore = mkOptionType {
|
||||
name = "pathInStore";
|
||||
description = "path in the Nix store";
|
||||
descriptionClass = "noun";
|
||||
check = x: isStringLike x && builtins.match "${builtins.storeDir}/[^.].*" (toString x) != null;
|
||||
merge = mergeEqualOption;
|
||||
pathInStore = pathWith {
|
||||
inStore = true;
|
||||
};
|
||||
|
||||
pathWith = {
|
||||
inStore ? null,
|
||||
absolute ? null,
|
||||
}:
|
||||
throwIf (inStore != null && absolute != null && inStore && !absolute) "In pathWith, inStore means the path must be absolute" mkOptionType {
|
||||
name = "pathWith";
|
||||
description = (
|
||||
(if absolute == null then "" else (if absolute then "absolute " else "relative ")) +
|
||||
"path" +
|
||||
(if inStore == null then "" else (if inStore then " in the Nix store" else " not in the Nix store"))
|
||||
);
|
||||
descriptionClass = "noun";
|
||||
|
||||
merge = mergeEqualOption;
|
||||
functor = defaultFunctor "pathWith" // {
|
||||
type = pathWith;
|
||||
payload = {inherit inStore absolute; };
|
||||
binOp = lhs: rhs: if lhs == rhs then lhs else null;
|
||||
};
|
||||
|
||||
check = x:
|
||||
let
|
||||
isInStore = builtins.match "${builtins.storeDir}/[^.].*" (toString x) != null;
|
||||
isAbsolute = builtins.substring 0 1 (toString x) == "/";
|
||||
isExpectedType = (
|
||||
if inStore == null || inStore then
|
||||
isStringLike x
|
||||
else
|
||||
isString x # Do not allow a true path, which could be copied to the store later on.
|
||||
);
|
||||
in
|
||||
isExpectedType && (inStore == null || inStore == isInStore) && (absolute == null || absolute == isAbsolute);
|
||||
};
|
||||
|
||||
listOf = elemType: mkOptionType rec {
|
||||
name = "listOf";
|
||||
description = "list of ${optionDescriptionPhrase (class: class == "noun" || class == "composite") elemType}";
|
||||
|
@ -23,15 +23,36 @@ merging is handled.
|
||||
|
||||
`types.path`
|
||||
|
||||
: A filesystem path is anything that starts with a slash when
|
||||
coerced to a string. Even if derivations can be considered as
|
||||
paths, the more specific `types.package` should be preferred.
|
||||
: A filesystem path that starts with a slash. Even if derivations can be
|
||||
considered as paths, the more specific `types.package` should be preferred.
|
||||
|
||||
`types.pathInStore`
|
||||
|
||||
: A path that is contained in the Nix store. This can be a top-level store
|
||||
path like `pkgs.hello` or a descendant like `"${pkgs.hello}/bin/hello"`.
|
||||
|
||||
`types.pathWith` { *`inStore`* ? `null`, *`absolute`* ? `null` }
|
||||
|
||||
: A filesystem path. Either a string or something that can be coerced
|
||||
to a string.
|
||||
|
||||
**Parameters**
|
||||
|
||||
`inStore` (`Boolean` or `null`, default `null`)
|
||||
: Whether the path must be in the store (`true`), must not be in the store
|
||||
(`false`), or it doesn't matter (`null`)
|
||||
|
||||
`absolute` (`Boolean` or `null`, default `null`)
|
||||
: Whether the path must be absolute (`true`), must not be absolute
|
||||
(`false`), or it doesn't matter (`null`)
|
||||
|
||||
**Behavior**
|
||||
- `pathWith { inStore = true; }` is equivalent to `pathInStore`
|
||||
- `pathWith { absolute = true; }` is equivalent to `path`
|
||||
- `pathWith { inStore = false; absolute = true; }` requires an absolute
|
||||
path that is not in the store. Useful for password files that shouldn't be
|
||||
leaked into the store.
|
||||
|
||||
`types.package`
|
||||
|
||||
: A top-level store path. This can be an attribute set pointing
|
||||
|
Loading…
Reference in New Issue
Block a user