Use include object syntax instead of shorthand
This commit is contained in:
parent
71bc768dc1
commit
feb9987300
|
@ -142,6 +142,18 @@ lib: {
|
||||||
invalid = builtins.removeAttrs module lib.modules.VALID_KEYS;
|
invalid = builtins.removeAttrs module lib.modules.VALID_KEYS;
|
||||||
in
|
in
|
||||||
invalid == { };
|
invalid == { };
|
||||||
|
|
||||||
|
## Check that an include object has the required attributes and otherwise
|
||||||
|
## only specifies supported attributes.
|
||||||
|
##
|
||||||
|
## @type (Attrs | String | Path | Function) -> Bool
|
||||||
|
include =
|
||||||
|
include:
|
||||||
|
let
|
||||||
|
invalidKeys = builtins.removeAttrs include lib.modules.VALID_INCLUDE_KEYS;
|
||||||
|
namespaceIsString = include ? namespace -> builtins.isString include.namespace;
|
||||||
|
in
|
||||||
|
builtins.isAttrs include -> (include ? module && namespaceIsString && invalidKeys == { });
|
||||||
};
|
};
|
||||||
|
|
||||||
## Modules only support certain keys at the root level. This list determines
|
## Modules only support certain keys at the root level. This list determines
|
||||||
|
@ -159,6 +171,15 @@ lib: {
|
||||||
"meta"
|
"meta"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
## Include objects only support certain keys. This list determines the
|
||||||
|
## valid attributes that users can supply.
|
||||||
|
##
|
||||||
|
## @type List String
|
||||||
|
VALID_INCLUDE_KEYS = [
|
||||||
|
"module"
|
||||||
|
"namespace"
|
||||||
|
];
|
||||||
|
|
||||||
## Normalize a module to a standard structure. All other information will be
|
## Normalize a module to a standard structure. All other information will be
|
||||||
## lost in the conversion.
|
## lost in the conversion.
|
||||||
##
|
##
|
||||||
|
@ -168,48 +189,59 @@ lib: {
|
||||||
let
|
let
|
||||||
invalid = builtins.removeAttrs module lib.modules.VALID_KEYS;
|
invalid = builtins.removeAttrs module lib.modules.VALID_KEYS;
|
||||||
invalidKeys = builtins.concatStringsSep ", " (builtins.attrNames invalid);
|
invalidKeys = builtins.concatStringsSep ", " (builtins.attrNames invalid);
|
||||||
|
throwError = msg: builtins.throw ("Module ${key} (${file}) " + msg);
|
||||||
|
|
||||||
__key__ = builtins.toString module.__key__ or key;
|
__key__ = builtins.toString module.__key__ or key;
|
||||||
|
|
||||||
normalizeIncludes =
|
normalizeIncludes =
|
||||||
includes:
|
includes:
|
||||||
let
|
let
|
||||||
flattened = builtins.concatMap (
|
normalized = lib.lists.mapWithIndex1 (
|
||||||
include:
|
n: include:
|
||||||
if
|
let
|
||||||
builtins.isAttrs include
|
invalid = builtins.removeAttrs module lib.modules.VALID_INCLUDE_KEYS;
|
||||||
&& include != { }
|
invalidKeys = builtins.concatStringsSep ", " (builtins.attrNames invalid);
|
||||||
&& !builtins.any (n: builtins.elem n lib.modules.VALID_KEYS) (builtins.attrNames include)
|
hasInvalidKeys = invalid != { };
|
||||||
then
|
throwError' = msg: throwError ("has invalid include at position ${builtins.toString n}" + msg);
|
||||||
lib.attrs.mapToList (namespace: module: {
|
in
|
||||||
inherit namespace;
|
if lib.modules.validate.include include then
|
||||||
include = module;
|
if builtins.isAttrs include then
|
||||||
}) include
|
|
||||||
else
|
|
||||||
[
|
|
||||||
{
|
{
|
||||||
inherit include;
|
inherit (include) module;
|
||||||
|
namespace = include.namespace or null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
module = include;
|
||||||
namespace = null;
|
namespace = null;
|
||||||
}
|
}
|
||||||
]
|
else if !include ? module then
|
||||||
) (lib.lists.when (includes != { }) includes);
|
{
|
||||||
|
module = include;
|
||||||
|
namespace = null;
|
||||||
|
}
|
||||||
|
else if hasInvalidKeys then
|
||||||
|
throwError' " with unsupported attribute(s): ${invalidKeys}"
|
||||||
|
else
|
||||||
|
throwError' ": namespace is not a string"
|
||||||
|
) includes;
|
||||||
|
|
||||||
throwOnConflict =
|
throwOnConflict =
|
||||||
let
|
let
|
||||||
filter =
|
filter =
|
||||||
namespaces:
|
namespaces:
|
||||||
{ namespace, include }:
|
{ namespace, ... }:
|
||||||
if namespace != null && builtins.elem namespace namespaces then
|
if namespace != null && builtins.elem namespace namespaces then
|
||||||
builtins.throw "Module ${key} declares several includes under the same namespace '${namespace}'"
|
throwError "declares several includes under the same namespace '${namespace}'"
|
||||||
else
|
else
|
||||||
namespaces ++ [ namespace ];
|
namespaces ++ [ namespace ];
|
||||||
in
|
in
|
||||||
builtins.foldl' filter [ ] flattened;
|
builtins.foldl' filter [ ] normalized;
|
||||||
|
|
||||||
createNamespacedModule =
|
createNamespacedModule =
|
||||||
{ namespace, include }:
|
{ namespace, module, ... }:
|
||||||
if namespace == null then
|
if namespace == null then
|
||||||
include
|
module
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
__key__ = "${__key__}:include-${namespace}";
|
__key__ = "${__key__}:include-${namespace}";
|
||||||
|
@ -217,13 +249,13 @@ lib: {
|
||||||
description = "options and configuration included from ${namespace}";
|
description = "options and configuration included from ${namespace}";
|
||||||
default.value = { };
|
default.value = { };
|
||||||
type = lib.types.submodules.of {
|
type = lib.types.submodules.of {
|
||||||
modules = [ include ];
|
modules = [ module ];
|
||||||
description = "include ${namespace}";
|
description = "include ${namespace}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
namespacedModules = builtins.map createNamespacedModule flattened;
|
namespacedModules = builtins.map createNamespacedModule normalized;
|
||||||
in
|
in
|
||||||
builtins.seq throwOnConflict namespacedModules;
|
builtins.seq throwOnConflict namespacedModules;
|
||||||
in
|
in
|
||||||
|
@ -259,7 +291,7 @@ lib: {
|
||||||
withFreeform (withMeta base);
|
withFreeform (withMeta base);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
builtins.throw "Module `${key}` (${file}) has unsupported attribute(s): ${invalidKeys}";
|
throwError "has unsupported attribute(s): ${invalidKeys}";
|
||||||
|
|
||||||
## Convert a module that is either a function or an attribute set into
|
## Convert a module that is either a function or an attribute set into
|
||||||
## a resolved attribute set. If the module was a function then it will
|
## a resolved attribute set. If the module was a function then it will
|
||||||
|
|
|
@ -246,28 +246,31 @@ in
|
||||||
in
|
in
|
||||||
expected == actual;
|
expected == actual;
|
||||||
|
|
||||||
"handles an empty set" =
|
|
||||||
let
|
|
||||||
expected = [ ];
|
|
||||||
actual = (lib.modules.normalize "/aux/example.nix" "example" { includes = { }; }).includes;
|
|
||||||
in
|
|
||||||
expected == actual;
|
|
||||||
|
|
||||||
"handles a mixed list" =
|
"handles a mixed list" =
|
||||||
let
|
let
|
||||||
expected = [
|
expected = [
|
||||||
{ }
|
null
|
||||||
{ a = null; }
|
{ a = null; }
|
||||||
];
|
];
|
||||||
actual =
|
actual =
|
||||||
# Because includes leverage submodules, we can't match the actual
|
# Because includes leverage submodules, we can't match the actual
|
||||||
# included namespaced submodule under "a". So we just assert the
|
# included namespaced submodule under "a". So we just assert the
|
||||||
# namespace was gotten right and do not evaluate the included value.
|
# namespace was gotten right and do not evaluate the included value.
|
||||||
builtins.map (include: builtins.mapAttrs (_: _: null) include.options or include)
|
builtins.map
|
||||||
|
(
|
||||||
|
include:
|
||||||
|
if builtins.isAttrs include then
|
||||||
|
builtins.mapAttrs (_: _: null) include.options or include
|
||||||
|
else
|
||||||
|
include
|
||||||
|
)
|
||||||
(lib.modules.normalize "/aux/example.nix" "example" {
|
(lib.modules.normalize "/aux/example.nix" "example" {
|
||||||
includes = [
|
includes = [
|
||||||
{ }
|
null
|
||||||
{ a = null; }
|
{
|
||||||
|
module = null;
|
||||||
|
namespace = "a";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
}).includes;
|
}).includes;
|
||||||
in
|
in
|
||||||
|
@ -277,8 +280,14 @@ in
|
||||||
let
|
let
|
||||||
normalized = lib.modules.normalize "/aux/example.nix" "example" {
|
normalized = lib.modules.normalize "/aux/example.nix" "example" {
|
||||||
includes = [
|
includes = [
|
||||||
{ a = { }; }
|
{
|
||||||
{ a = { }; }
|
module = null;
|
||||||
|
namespace = "a";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
module = null;
|
||||||
|
namespace = "a";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
@ -288,8 +297,8 @@ in
|
||||||
let
|
let
|
||||||
normalized = lib.modules.normalize "/aux/example.nix" "example" {
|
normalized = lib.modules.normalize "/aux/example.nix" "example" {
|
||||||
includes = [
|
includes = [
|
||||||
{ }
|
null
|
||||||
{ }
|
null
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
@ -298,14 +307,14 @@ in
|
||||||
"handles multiple without namespace" =
|
"handles multiple without namespace" =
|
||||||
let
|
let
|
||||||
expected = [
|
expected = [
|
||||||
{ }
|
null
|
||||||
{ }
|
null
|
||||||
];
|
];
|
||||||
actual =
|
actual =
|
||||||
(lib.modules.normalize "/aux/example.nix" "example" {
|
(lib.modules.normalize "/aux/example.nix" "example" {
|
||||||
includes = [
|
includes = [
|
||||||
{ }
|
null
|
||||||
{ }
|
null
|
||||||
];
|
];
|
||||||
}).includes;
|
}).includes;
|
||||||
in
|
in
|
||||||
|
@ -786,9 +795,8 @@ in
|
||||||
{
|
{
|
||||||
includes = [
|
includes = [
|
||||||
{
|
{
|
||||||
myinclude = {
|
namespace = "myinclude";
|
||||||
options.msg = lib.options.create { default.value = "hello"; };
|
module.options.msg = lib.options.create { default.value = "hello"; };
|
||||||
};
|
|
||||||
}
|
}
|
||||||
{ options.msg = lib.options.create { default.value = "hello"; }; }
|
{ options.msg = lib.options.create { default.value = "hello"; }; }
|
||||||
];
|
];
|
||||||
|
|
Loading…
Reference in a new issue