···261261 evalOptionValue = loc: opt: defs:
262262 let
263263 # Add in the default value for this option, if any.
264264- defs' = (optional (opt ? default)
265265- { file = head opt.declarations; value = mkOptionDefault opt.default; }) ++ defs;
264264+ defs' =
265265+ (optional (opt ? default)
266266+ { file = head opt.declarations; value = mkOptionDefault opt.default; }) ++ defs;
266267267268 # Handle properties, check types, and merge everything together.
268268- res = mergeDefinitions loc opt.type defs';
269269+ res =
270270+ if opt.readOnly or false && length defs' > 1 then
271271+ throw "The option `${showOption loc}' is read-only, but it's set multiple times."
272272+ else
273273+ mergeDefinitions loc opt.type defs';
269274270275 # Check whether the option is defined, and apply the ‘apply’
271276 # function to the merged value. This allows options to yield a
+2
lib/options.nix
···1919 , apply ? null # Function that converts the option value to something else.
2020 , internal ? null # Whether the option is for NixOS developers only.
2121 , visible ? null # Whether the option shows up in the manual.
2222+ , readOnly ? null # Whether the option can be set only once
2223 , options ? null # Obsolete, used by types.optionSet.
2324 } @ attrs:
2425 attrs // { _type = "option"; };
···9091 declarations = filter (x: x != unknownModule) opt.declarations;
9192 internal = opt.internal or false;
9293 visible = opt.visible or true;
9494+ readOnly = opt.readOnly or false;
9395 type = opt.type.name or null;
9496 }
9597 // (if opt ? example then { example = scrubOptionValue opt.example; } else {})