Loading pkgs/stdenv/generic/check-meta.nix +5 −31 Original line number Diff line number Diff line Loading @@ -317,7 +317,7 @@ let ${concatStrings (map (output: " - ${output}\n") missingOutputs)} ''; metaTypes = metaType = let types = import ./meta-types.nix { inherit lib; }; inherit (types) Loading @@ -329,13 +329,14 @@ let any listOf bool record ; platforms = listOf (union [ str (attrsOf any) ]); # see lib.meta.platformMatch in { record { # These keys are documented description = str; mainProgram = str; Loading Loading @@ -404,34 +405,7 @@ let identifiers = attrs; }; # Map attrs directly to the verify function for performance metaTypes' = mapAttrs (_: t: t.verify) metaTypes; checkMetaAttr = k: v: if metaTypes ? ${k} then if metaTypes'.${k} v then [ ] else [ "key 'meta.${k}' has invalid value; expected ${metaTypes.${k}.name}, got\n ${ toPretty { indent = " "; } v }" ] else [ "key 'meta.${k}' is unrecognized; expected one of: \n [${ concatMapStringsSep ", " (x: "'${x}'") (attrNames metaTypes) }]" ]; checkMeta = meta: concatMap (attr: checkMetaAttr attr meta.${attr}) (attrNames meta); metaInvalid = if config.checkMeta then meta: !all (attr: metaTypes ? ${attr} && metaTypes'.${attr} meta.${attr}) (attrNames meta) else meta: false; metaInvalid = if config.checkMeta then meta: !metaType.verify meta else meta: false; checkOutputsToInstall = if config.checkMeta then Loading Loading @@ -459,7 +433,7 @@ let { reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${ concatMapStrings (x: "\n - " + x) (checkMeta attrs.meta) concatMapStrings (x: "\n - " + x) (metaType.errors "${getName attrs}.meta" attrs.meta) }\n"; remediation = ""; } Loading pkgs/stdenv/generic/meta-types.nix +54 −1 Original line number Diff line number Diff line Loading @@ -12,16 +12,40 @@ let isList all any attrNames attrValues concatMap isFunction isBool concatStringsSep concatMapStringsSep isFloat elem mapAttrs ; isTypeDef = t: isAttrs t && t ? name && isString t.name && t ? verify && isFunction t.verify; in lib.fix (self: { /* `errors type "<context>" value` gives a list of string error messages, each prefixed with "<context>: ", for why `value` is not of type `type` Only use this if `type.verify value` is false Types can override this by specifying their own `type.errors = ctx: value:` attribute This is intentionally not tied into `type.verify`, in order to keep the successful path as fast as possible with minimal allocations */ errors = t: t.errors or (ctx: v: [ "${ctx}: Invalid value; expected ${t.name}, got\n ${ lib.generators.toPretty { indent = " "; } v }" ]); string = { name = "string"; verify = isString; Loading Loading @@ -95,4 +119,33 @@ lib.fix (self: { name = "union<${concatStringsSep "," (map (t: t.name) types)}>"; verify = v: any (func: func v) funcs; }; record = fields: assert isAttrs fields && all isTypeDef (attrValues fields); let # Map attrs directly to the verify function for performance fieldVerifiers = mapAttrs (_: t: t.verify) fields; in { name = "record"; verify = v: isAttrs v && all (k: fieldVerifiers ? ${k} && fieldVerifiers.${k} v.${k}) (attrNames v); errors = ctx: v: if !isAttrs v then self.errors self.attrs ctx v else concatMap ( k: if fieldVerifiers ? ${k} then lib.optionals (fieldVerifiers.${k} v.${k}) (self.errors fields.${k} (ctx + ".${k}") v.${k}) else [ "${ctx}: key '${k}' is unrecognized; expected one of: \n [${ concatMapStringsSep ", " (x: "'${x}'") (attrNames fields) }]" ] ) (attrNames v); }; }) Loading
pkgs/stdenv/generic/check-meta.nix +5 −31 Original line number Diff line number Diff line Loading @@ -317,7 +317,7 @@ let ${concatStrings (map (output: " - ${output}\n") missingOutputs)} ''; metaTypes = metaType = let types = import ./meta-types.nix { inherit lib; }; inherit (types) Loading @@ -329,13 +329,14 @@ let any listOf bool record ; platforms = listOf (union [ str (attrsOf any) ]); # see lib.meta.platformMatch in { record { # These keys are documented description = str; mainProgram = str; Loading Loading @@ -404,34 +405,7 @@ let identifiers = attrs; }; # Map attrs directly to the verify function for performance metaTypes' = mapAttrs (_: t: t.verify) metaTypes; checkMetaAttr = k: v: if metaTypes ? ${k} then if metaTypes'.${k} v then [ ] else [ "key 'meta.${k}' has invalid value; expected ${metaTypes.${k}.name}, got\n ${ toPretty { indent = " "; } v }" ] else [ "key 'meta.${k}' is unrecognized; expected one of: \n [${ concatMapStringsSep ", " (x: "'${x}'") (attrNames metaTypes) }]" ]; checkMeta = meta: concatMap (attr: checkMetaAttr attr meta.${attr}) (attrNames meta); metaInvalid = if config.checkMeta then meta: !all (attr: metaTypes ? ${attr} && metaTypes'.${attr} meta.${attr}) (attrNames meta) else meta: false; metaInvalid = if config.checkMeta then meta: !metaType.verify meta else meta: false; checkOutputsToInstall = if config.checkMeta then Loading Loading @@ -459,7 +433,7 @@ let { reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${ concatMapStrings (x: "\n - " + x) (checkMeta attrs.meta) concatMapStrings (x: "\n - " + x) (metaType.errors "${getName attrs}.meta" attrs.meta) }\n"; remediation = ""; } Loading
pkgs/stdenv/generic/meta-types.nix +54 −1 Original line number Diff line number Diff line Loading @@ -12,16 +12,40 @@ let isList all any attrNames attrValues concatMap isFunction isBool concatStringsSep concatMapStringsSep isFloat elem mapAttrs ; isTypeDef = t: isAttrs t && t ? name && isString t.name && t ? verify && isFunction t.verify; in lib.fix (self: { /* `errors type "<context>" value` gives a list of string error messages, each prefixed with "<context>: ", for why `value` is not of type `type` Only use this if `type.verify value` is false Types can override this by specifying their own `type.errors = ctx: value:` attribute This is intentionally not tied into `type.verify`, in order to keep the successful path as fast as possible with minimal allocations */ errors = t: t.errors or (ctx: v: [ "${ctx}: Invalid value; expected ${t.name}, got\n ${ lib.generators.toPretty { indent = " "; } v }" ]); string = { name = "string"; verify = isString; Loading Loading @@ -95,4 +119,33 @@ lib.fix (self: { name = "union<${concatStringsSep "," (map (t: t.name) types)}>"; verify = v: any (func: func v) funcs; }; record = fields: assert isAttrs fields && all isTypeDef (attrValues fields); let # Map attrs directly to the verify function for performance fieldVerifiers = mapAttrs (_: t: t.verify) fields; in { name = "record"; verify = v: isAttrs v && all (k: fieldVerifiers ? ${k} && fieldVerifiers.${k} v.${k}) (attrNames v); errors = ctx: v: if !isAttrs v then self.errors self.attrs ctx v else concatMap ( k: if fieldVerifiers ? ${k} then lib.optionals (fieldVerifiers.${k} v.${k}) (self.errors fields.${k} (ctx + ".${k}") v.${k}) else [ "${ctx}: key '${k}' is unrecognized; expected one of: \n [${ concatMapStringsSep ", " (x: "'${x}'") (attrNames fields) }]" ] ) (attrNames v); }; })