-
-
Notifications
You must be signed in to change notification settings - Fork 19.6k
nixos-option: rewrite as a nix script #313497
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,39 +1,73 @@ | ||
| { lib | ||
| , stdenv | ||
| , boost | ||
| , cmake | ||
| , pkg-config | ||
| , installShellFiles | ||
| , nix | ||
| { | ||
| lib, | ||
| makeWrapper, | ||
| stdenvNoCC, | ||
| installShellFiles, | ||
| shellcheck, | ||
| nix, | ||
| jq, | ||
| man-db, | ||
| coreutils, | ||
| }: | ||
|
|
||
| stdenv.mkDerivation { | ||
| stdenvNoCC.mkDerivation { | ||
| name = "nixos-option"; | ||
|
|
||
| src = ./src; | ||
| src = ./nixos-option.sh; | ||
|
|
||
| postInstall = '' | ||
| installManPage ${./nixos-option.8} | ||
| ''; | ||
|
|
||
| strictDeps = true; | ||
| nativeBuildInputs = [ | ||
| cmake | ||
| pkg-config | ||
| installShellFiles | ||
| makeWrapper | ||
| shellcheck | ||
| ]; | ||
| buildInputs = [ | ||
| boost | ||
| nix | ||
| ]; | ||
| cmakeFlags = [ | ||
| "-DNIX_DEV_INCLUDEPATH=${nix.dev}/include/nix" | ||
| ]; | ||
|
|
||
| meta = with lib; { | ||
| license = licenses.lgpl2Plus; | ||
| env = { | ||
| nixosOptionNix = toString ./nixos-option.nix; | ||
| nixosOptionManpage = "${placeholder "out"}/share/man"; | ||
| }; | ||
|
|
||
| dontUnpack = true; | ||
| dontConfigure = true; | ||
| dontPatch = true; | ||
| dontBuild = true; | ||
|
|
||
| installPhase = '' | ||
| runHook preInstall | ||
|
|
||
| install -Dm555 $src $out/bin/nixos-option | ||
| substituteAllInPlace $out/bin/nixos-option | ||
| installManPage ${./nixos-option.8} | ||
|
|
||
| runHook postInstall | ||
| ''; | ||
|
|
||
| doInstallCheck = true; | ||
| installCheckPhase = '' | ||
| runHook preInstallCheck | ||
| shellcheck $out/bin/nixos-option | ||
| runHook postInstallCheck | ||
| ''; | ||
|
|
||
| postFixup = '' | ||
| wrapProgram $out/bin/nixos-option \ | ||
| --prefix PATH : ${ | ||
| lib.makeBinPath [ | ||
| nix | ||
| jq | ||
| man-db | ||
| coreutils | ||
| ] | ||
| } | ||
| ''; | ||
|
|
||
| meta = { | ||
| description = "Evaluate NixOS configuration and return the properties of given option"; | ||
| license = lib.licenses.mit; | ||
| mainProgram = "nixos-option"; | ||
| maintainers = [ ]; | ||
| inherit (nix.meta) platforms; | ||
| maintainers = with lib.maintainers; [ | ||
| FireyFly | ||
| azuwis | ||
| aleksana | ||
| ]; | ||
| }; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
Aleksanaa marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| { | ||
| nixos ? import <nixpkgs/nixos> { }, | ||
| # list representing a nixos option path (e.g. ['console' 'enable']), or a | ||
| # prefix of such a path (e.g. ['console']), or a string representing the same | ||
| # (e.g. 'console.enable') | ||
| path, | ||
| # whether to recurse down the config attrset and show each set value instead | ||
| recursive ? false, | ||
| }: | ||
|
|
||
| let | ||
| inherit (nixos.pkgs) lib; | ||
|
|
||
| path' = if lib.isString path then (if path == "" then [ ] else readOption path) else path; | ||
|
|
||
| # helper that maps `f` on subslices starting when `predStart x` and | ||
| # ending when `predEnd x` (no support for nested occurrences) | ||
| flatMapSlices = | ||
| predStart: predEnd: f: list: | ||
| let | ||
| empty = { | ||
| result = [ ]; | ||
| active = [ ]; | ||
| }; | ||
| op = | ||
| { result, active }: | ||
| x: | ||
| if predStart x && predEnd x then | ||
| { | ||
| result = result ++ active ++ f [ x ]; | ||
| active = [ ]; | ||
| } | ||
| else if predStart x then | ||
| { | ||
| result = result ++ active; | ||
| active = [ x ]; | ||
| } | ||
| else if predEnd x then | ||
| { | ||
| result = result ++ f (active ++ [ x ]); | ||
| active = [ ]; | ||
| } | ||
| else | ||
| { | ||
| inherit result; | ||
| active = active ++ [ x ]; | ||
| }; | ||
| in | ||
| (x: x.result ++ x.active) (lib.foldl op empty list); | ||
|
|
||
| # tries to invert showOption, taking a written-out option name and splitting | ||
| # it into its parts | ||
| readOption = | ||
| str: | ||
| let | ||
| unescape = list: lib.replaceStrings (map (c: "\\${c}") list) list; | ||
| unescapeNixString = lib.flip lib.pipe [ | ||
| (lib.concatStringsSep ".") | ||
| (unescape [ "$" ]) | ||
| builtins.fromJSON | ||
| ]; | ||
| in | ||
| flatMapSlices (lib.hasPrefix "\"") (lib.hasSuffix "\"") (x: [ (unescapeNixString x) ]) ( | ||
| lib.splitString "." str | ||
| ); | ||
|
|
||
| # like 'mapAttrsRecursiveCond' but handling errors in the attrset tree as leaf | ||
| # nodes (which means `f` is expected to handle shallow errors) | ||
| safeMapAttrsRecursiveCond = | ||
| cond: f: set: | ||
| let | ||
| recurse = | ||
| path: | ||
| lib.mapAttrs ( | ||
| name: value: | ||
| let | ||
| e = builtins.tryEval value; | ||
| path' = path ++ [ name ]; | ||
| in | ||
| if e.success && lib.isAttrs value && cond value then recurse path' value else f path' value | ||
| ); | ||
| in | ||
| recurse [ ] set; | ||
|
|
||
| # traverse the option tree along `path` from `root`, returning the option or | ||
| # attrset at the given location | ||
| optionByPath = | ||
| path: root: | ||
| let | ||
| into = | ||
| opt: part: | ||
| if lib.isOption opt && opt.type.descriptionClass == "composite" then | ||
| opt.type.getSubOptions [ ] | ||
| else if lib.isOption opt then | ||
| throw "Trying to access '${part}' inside ${opt.type.name} option while traversing option path '${lib.showOption path}'" | ||
| else if lib.isAttrs opt && lib.hasAttr part opt then | ||
| opt.${part} | ||
| else | ||
| throw "Found neither an attrset nor supported option type near '${part}' while traversing option path '${lib.showOption path}'"; | ||
| in | ||
| lib.foldl into root path; | ||
|
|
||
| toPretty = lib.generators.toPretty { multiline = true; }; | ||
| safeToPretty = | ||
| x: | ||
| let | ||
| e = builtins.tryEval (toPretty x); | ||
| in | ||
| if e.success then e.value else "[1;31m«error»[m"; | ||
|
|
||
| indent = str: lib.concatStringsSep "\n" (map (x: " " + x) (lib.splitString "\n" str)); | ||
|
|
||
| optionAttrNames = attrs: lib.filter (x: x != "_module") (lib.attrNames attrs); | ||
|
|
||
| ## full, non-recursive mode: print an option from `options` | ||
| renderAttrs = | ||
| attrs: "This attribute set contains:\n${lib.concatStringsSep "\n" (optionAttrNames attrs)}"; | ||
|
|
||
| renderOption = | ||
| option: value: | ||
| let | ||
| entry = | ||
| cond: heading: value: | ||
| lib.optional cond "${heading}:\n${indent value}"; | ||
| in | ||
| lib.concatStringsSep "\n\n" ( | ||
| lib.concatLists [ | ||
| (entry true "Value" (toPretty value)) | ||
| (entry (option ? default) "Default" (toPretty option.default)) | ||
| (entry (option ? type) "Type" (option.type.description)) | ||
| (entry (option ? description) "Description" (lib.removeSuffix "\n" option.description)) | ||
| (entry (option ? example) "Example" (toPretty option.example)) | ||
| (entry (option ? declarations) "Declared by" (lib.concatStringsSep "\n" option.declarations)) | ||
| (entry (option ? files) "Defined by" (lib.concatStringsSep "\n" option.files)) | ||
| ] | ||
| ); | ||
|
|
||
| renderFull = | ||
| entry: configEntry: | ||
| if lib.isOption entry then | ||
| renderOption entry configEntry | ||
| else if lib.isAttrs entry then | ||
| renderAttrs entry | ||
| else | ||
| throw "Found neither an attrset nor option at option path '${lib.showOption path'}'"; | ||
|
|
||
| ## recursive mode: print paths and values from `config` | ||
| renderRecursive = | ||
| config: | ||
| let | ||
| renderShort = n: v: "${lib.showOption (path' ++ n)} = ${safeToPretty v};"; | ||
| mapAttrsRecursive' = safeMapAttrsRecursiveCond (x: !lib.isDerivation x); | ||
| in | ||
| if lib.isAttrs config then | ||
| lib.concatStringsSep "\n" (lib.collect lib.isString (mapAttrsRecursive' renderShort config)) | ||
| else | ||
| renderShort [ ] config; | ||
|
|
||
| in | ||
| if !lib.hasAttrByPath path' nixos.config then | ||
| throw "Couldn't resolve config path '${lib.showOption path'}'" | ||
| else | ||
| let | ||
| optionEntry = optionByPath path' nixos.options; | ||
| configEntry = lib.attrByPath path' null nixos.config; | ||
| in | ||
| if recursive then renderRecursive configEntry else renderFull optionEntry configEntry |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably don't want this so late in the 24.11 cycle, so I would move this to the 25.05 release notes instead.