Replace nixpkgs nullOr type with custom type

`nullOr`'s merge function requires definitions to all be null or all be
non-null. It was being used where the intent was that null be used as a
value representing unset, and as such the merge should return null if
all definitions are null and ignore nulls otherwise. This adds a type
with that merge semantics.
This commit is contained in:
Archit Gupta 2024-02-07 00:54:03 -08:00
parent 9fe4cb1994
commit 543e3aaa4d
15 changed files with 74 additions and 50 deletions

View File

@ -5,8 +5,8 @@
{ config, lib, flakelight, genSystems, ... }:
let
inherit (lib) isFunction mapAttrs mkIf mkMerge mkOption;
inherit (lib.types) lazyAttrsOf nullOr raw;
inherit (flakelight.types) optFunctionTo;
inherit (lib.types) lazyAttrsOf raw;
inherit (flakelight.types) nullable optFunctionTo;
isApp = x: (x ? type) && (x.type == "app") && (x ? program);
@ -17,12 +17,12 @@ in
{
options = {
app = mkOption {
type = nullOr raw;
type = nullable raw;
default = null;
};
apps = mkOption {
type = nullOr (optFunctionTo (lazyAttrsOf raw));
type = nullable (optFunctionTo (lazyAttrsOf raw));
default = null;
};
};

View File

@ -5,14 +5,15 @@
{ config, src, lib, inputs, outputs, flakelight, moduleArgs, ... }:
let
inherit (lib) isList mkOption mkOrder mapAttrs optionalAttrs;
inherit (lib.types) listOf nullOr oneOf str;
inherit (lib.types) listOf oneOf str;
inherit (builtins) pathExists;
inherit (flakelight) selectAttr;
inherit (flakelight.types) nullable;
in
{
options = {
description = mkOption {
type = nullOr str;
type = nullable str;
default =
if pathExists (src + /flake.nix)
then (import (src + /flake.nix)).description or null
@ -20,7 +21,7 @@ in
};
license = mkOption {
type = nullOr (oneOf [ str (listOf str) ]);
type = nullable (oneOf [ str (listOf str) ]);
default = null;
};
};

View File

@ -5,8 +5,8 @@
{ config, lib, flakelight, genSystems, ... }:
let
inherit (lib) isFunction mapAttrs mkMerge mkOption mkIf;
inherit (lib.types) lazyAttrsOf nullOr;
inherit (flakelight.types) function optFunctionTo;
inherit (lib.types) lazyAttrsOf;
inherit (flakelight.types) function nullable optFunctionTo;
wrapBundler = pkgs: bundler: drv:
if isFunction (bundler (pkgs // drv))
@ -16,12 +16,12 @@ in
{
options = {
bundler = mkOption {
type = nullOr function;
type = nullable function;
default = null;
};
bundlers = mkOption {
type = nullOr (optFunctionTo (lazyAttrsOf function));
type = nullable (optFunctionTo (lazyAttrsOf function));
default = null;
};
};

View File

@ -5,8 +5,8 @@
{ config, src, lib, flakelight, genSystems, ... }:
let
inherit (lib) isDerivation isFunction mkOption mkIf mapAttrs;
inherit (lib.types) lazyAttrsOf nullOr raw;
inherit (flakelight.types) optFunctionTo;
inherit (lib.types) lazyAttrsOf raw;
inherit (flakelight.types) nullable optFunctionTo;
mkCheck = pkgs: name: cmd:
let cmd' = if isFunction cmd then cmd pkgs else cmd; in
@ -20,7 +20,7 @@ let
in
{
options.checks = mkOption {
type = nullOr (optFunctionTo (lazyAttrsOf raw));
type = nullable (optFunctionTo (lazyAttrsOf raw));
default = null;
};

View File

@ -6,10 +6,11 @@
let
inherit (lib) filterAttrs functionArgs mapAttrs mkDefault mkIf mkMerge
mkOption;
inherit (lib.types) attrs coercedTo functionTo lazyAttrsOf lines listOf nullOr
inherit (lib.types) attrs coercedTo functionTo lazyAttrsOf lines listOf
package str submodule;
inherit (flakelight) supportedSystem;
inherit (flakelight.types) function optCallWith optFunctionTo packageDef;
inherit (flakelight.types) function nullable optCallWith optFunctionTo
packageDef;
devShellModule.options = {
inputsFrom = mkOption {
@ -38,7 +39,7 @@ let
};
overrideShell = mkOption {
type = nullOr packageDef;
type = nullable packageDef;
internal = true;
default = null;
};
@ -53,7 +54,7 @@ in
options = {
devShell = mkOption {
default = null;
type = nullOr (coercedTo function wrapFn
type = nullable (coercedTo function wrapFn
(coercedTo attrs (x: _: x)
(functionTo (submodule devShellModule))));
};

View File

@ -5,13 +5,13 @@
{ config, lib, flakelight, moduleArgs, ... }:
let
inherit (lib) mkOption mkIf mkMerge;
inherit (lib.types) lazyAttrsOf nullOr;
inherit (flakelight.types) module optCallWith;
inherit (lib.types) lazyAttrsOf;
inherit (flakelight.types) module nullable optCallWith;
in
{
options = {
flakelightModule = mkOption {
type = nullOr module;
type = nullable module;
default = null;
};

View File

@ -5,17 +5,17 @@
{ config, src, lib, flakelight, genSystems, ... }:
let
inherit (lib) mkDefault mkMerge mkOption mkIf mapAttrsToList;
inherit (lib.types) functionTo lazyAttrsOf nullOr package str;
inherit (flakelight.types) optFunctionTo;
inherit (lib.types) functionTo lazyAttrsOf package str;
inherit (flakelight.types) nullable optFunctionTo;
in
{
options = {
formatter = mkOption {
type = nullOr (functionTo package);
type = nullable (functionTo package);
default = null;
};
formatters = mkOption {
type = nullOr (optFunctionTo (lazyAttrsOf str));
type = nullable (optFunctionTo (lazyAttrsOf str));
default = null;
};
};

View File

@ -2,14 +2,15 @@
# Copyright (C) 2023 Archit Gupta <archit@accelbread.com>
# SPDX-License-Identifier: MIT
{ config, lib, ... }:
{ config, lib, flakelight, ... }:
let
inherit (lib) mkOption mkIf;
inherit (lib.types) functionTo nullOr raw uniq;
inherit (lib.types) functionTo raw uniq;
inherit (flakelight.types) nullable;
in
{
options.functor = mkOption {
type = nullOr (uniq (functionTo (functionTo raw)));
type = nullable (uniq (functionTo (functionTo raw)));
default = null;
};

View File

@ -5,13 +5,13 @@
{ config, lib, flakelight, moduleArgs, ... }:
let
inherit (lib) mkOption mkIf mkMerge;
inherit (lib.types) lazyAttrsOf nullOr;
inherit (flakelight.types) module optCallWith;
inherit (lib.types) lazyAttrsOf;
inherit (flakelight.types) module nullable optCallWith;
in
{
options = {
homeModule = mkOption {
type = nullOr module;
type = nullable module;
default = null;
};

View File

@ -2,14 +2,15 @@
# Copyright (C) 2023 Archit Gupta <archit@accelbread.com>
# SPDX-License-Identifier: MIT
{ config, lib, genSystems, ... }:
{ config, lib, flakelight, genSystems, ... }:
let
inherit (lib) mkIf mkOption;
inherit (lib.types) functionTo nullOr pkgs;
inherit (lib.types) functionTo pkgs;
inherit (flakelight.types) nullable;
in
{
options.legacyPackages = mkOption {
type = nullOr (functionTo pkgs);
type = nullable (functionTo pkgs);
default = null;
};

View File

@ -5,13 +5,13 @@
{ config, lib, flakelight, moduleArgs, ... }:
let
inherit (lib) mkOption mkIf mkMerge;
inherit (lib.types) lazyAttrsOf nullOr;
inherit (flakelight.types) module optCallWith;
inherit (lib.types) lazyAttrsOf;
inherit (flakelight.types) module nullable optCallWith;
in
{
options = {
nixosModule = mkOption {
type = nullOr module;
type = nullable module;
default = null;
};

View File

@ -5,13 +5,13 @@
{ config, lib, flakelight, moduleArgs, ... }:
let
inherit (lib) mkMerge mkOption mkIf;
inherit (lib.types) lazyAttrsOf nullOr;
inherit (flakelight.types) optCallWith overlay;
inherit (lib.types) lazyAttrsOf;
inherit (flakelight.types) nullable optCallWith overlay;
in
{
options = {
overlay = mkOption {
type = nullOr overlay;
type = nullable overlay;
default = null;
};

View File

@ -7,9 +7,9 @@ let
inherit (builtins) hasAttr parseDrvName tryEval;
inherit (lib) filterAttrs findFirst functionArgs mapAttrs' mapAttrs mkIf
mkMerge mkOption nameValuePair optionalAttrs;
inherit (lib.types) lazyAttrsOf nullOr str uniq;
inherit (lib.types) lazyAttrsOf str uniq;
inherit (flakelight) supportedSystem;
inherit (flakelight.types) optCallWith overlay packageDef;
inherit (flakelight.types) nullable optCallWith overlay packageDef;
genPkg = final: prev: name: pkg:
let
@ -32,7 +32,7 @@ in
{
options = {
package = mkOption {
type = nullOr packageDef;
type = nullable packageDef;
default = null;
};
@ -42,7 +42,7 @@ in
};
pname = mkOption {
type = nullOr str;
type = nullable str;
default = null;
};

View File

@ -6,9 +6,9 @@
let
inherit (builtins) isPath isString;
inherit (lib) mkOption mkOptionType mkIf mkMerge;
inherit (lib.types) lazyAttrsOf nullOr;
inherit (lib.types) lazyAttrsOf;
inherit (lib.options) mergeEqualOption;
inherit (flakelight.types) optCallWith;
inherit (flakelight.types) nullable optCallWith;
template = mkOptionType {
name = "template";
@ -23,7 +23,7 @@ in
{
options = {
template = mkOption {
type = nullOr (optCallWith moduleArgs template);
type = nullable (optCallWith moduleArgs template);
default = null;
};

View File

@ -6,11 +6,12 @@ inputs:
let
inherit (inputs) nixpkgs;
inherit (builtins) isAttrs isPath readDir;
inherit (nixpkgs.lib) attrNames composeManyExtensions evalModules filter
inherit (nixpkgs.lib) all attrNames composeManyExtensions evalModules filter
findFirst fix genAttrs getValues hasSuffix isFunction isList mapAttrs
mapAttrsToList mkDefault mkOptionType pathExists pipe removePrefix
removeSuffix singleton warn;
inherit (nixpkgs.lib.types) coercedTo functionTo listOf;
inherit (nixpkgs.lib.types) coercedTo defaultFunctor functionTo listOf
optionDescriptionPhrase;
inherit (nixpkgs.lib.options) mergeEqualOption mergeOneOption;
builtinModules = mapAttrsToList (k: _: ./builtinModules + ("/" + k))
@ -40,7 +41,7 @@ let
supportedSystem types;
};
types = {
types = rec {
overlay = mkOptionType {
name = "overlay";
description = "nixpkgs overlay";
@ -95,6 +96,25 @@ let
optCallWith = args: elemType: coercedTo (functionTo elemType) (x: x args)
elemType;
nullable = elemType: mkOptionType {
name = "nullable";
description = "nullable ${optionDescriptionPhrase
(class: class == "noun" || class == "composite") elemType}";
descriptionClass = "noun";
check = x: x == null || elemType.check x;
merge = loc: defs:
if all (def: def.value == null) defs then null
else elemType.merge loc (filter (def: def.value != null) defs);
emptyValue.value = null;
inherit (elemType) getSubOptions getSubModules;
substSubModules = m: nullable (elemType.substSubModules m);
functor = (defaultFunctor "nullable") // {
type = nullable;
wrapped = elemType;
};
nestedTypes = { inherit elemType; };
};
};
supportedSystem = { lib, stdenv, ... }: