Support flake attr nixosModule
(#401)
* flake_info.nix: remove helper fn `default` Nix has builtin syntax for fetching attrs with a default value. * flake_info.nix: minor refactor - Remove commented out code - Simplify pkg filtering - Break overlong line * flake_info.nix: support flake attr `nixosModule` * Support default modules in rust backend and elm Co-authored-by: Yannik Sander <me@ysndr.de>
This commit is contained in:
parent
32700e3eee
commit
096ea9e49c
|
@ -5,43 +5,32 @@ let
|
||||||
nixpkgs = (import <nixpkgs> {});
|
nixpkgs = (import <nixpkgs> {});
|
||||||
lib = nixpkgs.lib;
|
lib = nixpkgs.lib;
|
||||||
|
|
||||||
|
|
||||||
default = drv: attr: default: if drv ? ${attr} then drv.${attr} else default;
|
|
||||||
|
|
||||||
# filter = lib.filterAttrs (key: _ : key == "apps" || key == "packages");
|
# filter = lib.filterAttrs (key: _ : key == "apps" || key == "packages");
|
||||||
|
|
||||||
withSystem = fn: lib.mapAttrs (system: drvs: (fn system drvs));
|
withSystem = fn: lib.mapAttrs (system: drvs: (fn system drvs));
|
||||||
isValid = d:
|
isValid = d:
|
||||||
let
|
let
|
||||||
r = builtins.tryEval (lib.isDerivation d && ! (lib.attrByPath [ "meta" "broken" ] false d) && builtins.seq d.name true && d ? outputs);
|
r = builtins.tryEval (lib.isDerivation d && ! (lib.attrByPath [ "meta" "broken" ] false d) &&
|
||||||
|
builtins.seq d.name true && d ? outputs);
|
||||||
in
|
in
|
||||||
r.success && r.value;
|
r.success && r.value;
|
||||||
all = pkgs:
|
validPkgs = lib.filterAttrs (k: v: isValid v);
|
||||||
let
|
|
||||||
validPkgs = lib.filterAttrs (k: v: isValid v) pkgs;
|
|
||||||
in
|
|
||||||
validPkgs;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
readPackages = system: drvs: lib.mapAttrsToList (
|
readPackages = system: drvs: lib.mapAttrsToList (
|
||||||
attribute_name: drv: (
|
attribute_name: drv: (
|
||||||
# if isValid drv then
|
|
||||||
{
|
{
|
||||||
attribute_name = attribute_name;
|
attribute_name = attribute_name;
|
||||||
system = system;
|
system = system;
|
||||||
name = drv.name;
|
name = drv.name;
|
||||||
# TODO consider using `builtins.parseDrvName`
|
# TODO consider using `builtins.parseDrvName`
|
||||||
version = default drv "version" "";
|
version = drv.version or "";
|
||||||
outputs = drv.outputs;
|
outputs = drv.outputs;
|
||||||
# paths = builtins.listToAttrs ( map (output: {name = output; value = drv.${output};}) drv.outputs );
|
# paths = builtins.listToAttrs ( map (output: {name = output; value = drv.${output};}) drv.outputs );
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs (drv ? meta && drv.meta ? description) { inherit (drv.meta) description; }
|
// lib.optionalAttrs (drv ? meta && drv.meta ? description) { inherit (drv.meta) description; }
|
||||||
// lib.optionalAttrs (drv ? meta && drv.meta ? license) { inherit (drv.meta) license; }
|
// lib.optionalAttrs (drv ? meta && drv.meta ? license) { inherit (drv.meta) license; }
|
||||||
|
|
||||||
# else {}
|
|
||||||
)
|
)
|
||||||
) (all drvs);
|
) (validPkgs drvs);
|
||||||
readApps = system: apps: lib.mapAttrsToList (
|
readApps = system: apps: lib.mapAttrsToList (
|
||||||
attribute_name: app: (
|
attribute_name: app: (
|
||||||
{
|
{
|
||||||
|
@ -54,8 +43,7 @@ let
|
||||||
)
|
)
|
||||||
) apps;
|
) apps;
|
||||||
|
|
||||||
readOptions = modules: isNixOS: let
|
readOptions = let
|
||||||
|
|
||||||
declarations = module: (
|
declarations = module: (
|
||||||
lib.evalModules {
|
lib.evalModules {
|
||||||
modules = (if lib.isList module then module else [ module ]) ++ [
|
modules = (if lib.isList module then module else [ module ]) ++ [
|
||||||
|
@ -70,7 +58,7 @@ let
|
||||||
}
|
}
|
||||||
).options;
|
).options;
|
||||||
|
|
||||||
cleanUpOption = module: opt:
|
cleanUpOption = extraAttrs: opt:
|
||||||
let
|
let
|
||||||
applyOnAttr = n: f: lib.optionalAttrs (builtins.hasAttr n opt) { ${n} = f opt.${n}; };
|
applyOnAttr = n: f: lib.optionalAttrs (builtins.hasAttr n opt) { ${n} = f opt.${n}; };
|
||||||
mkDeclaration = decl:
|
mkDeclaration = decl:
|
||||||
|
@ -96,31 +84,47 @@ let
|
||||||
// applyOnAttr "example" substFunction # (_: { __type = "function"; })
|
// applyOnAttr "example" substFunction # (_: { __type = "function"; })
|
||||||
// applyOnAttr "type" substFunction
|
// applyOnAttr "type" substFunction
|
||||||
// applyOnAttr "declarations" (map mkDeclaration)
|
// applyOnAttr "declarations" (map mkDeclaration)
|
||||||
// lib.optionalAttrs (!isNixOS) { flake = [ flake module ]; };
|
// extraAttrs;
|
||||||
|
|
||||||
|
|
||||||
options = lib.mapAttrs (
|
|
||||||
attr: module: let
|
|
||||||
list = lib.optionAttrSetToDocList (declarations module);
|
|
||||||
in
|
|
||||||
map (cleanUpOption attr) (lib.filter (x: !x.internal) list)
|
|
||||||
) modules;
|
|
||||||
in
|
in
|
||||||
lib.flatten (builtins.attrValues options);
|
{ module, modulePath ? null }: let
|
||||||
|
opts = lib.optionAttrSetToDocList (declarations module);
|
||||||
|
extraAttrs = lib.optionalAttrs (modulePath != null) {
|
||||||
|
flake = modulePath;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
map (cleanUpOption extraAttrs) (lib.filter (x: !x.internal) opts);
|
||||||
|
|
||||||
|
readFlakeOptions = let
|
||||||
|
nixosModulesOpts = builtins.concatLists (lib.mapAttrsToList (moduleName: module:
|
||||||
|
readOptions {
|
||||||
|
inherit module;
|
||||||
|
modulePath = [ flake moduleName ];
|
||||||
|
}
|
||||||
|
) (resolved.nixosModules or {}));
|
||||||
|
|
||||||
|
nixosModuleOpts = lib.optionals (resolved ? nixosModule) (
|
||||||
|
readOptions {
|
||||||
|
module = resolved.nixosModule;
|
||||||
|
modulePath = [ flake ];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
in
|
||||||
|
# We assume that `nixosModules` includes `nixosModule` when there
|
||||||
|
# are multiple modules
|
||||||
|
if nixosModulesOpts != [] then nixosModulesOpts else nixosModuleOpts;
|
||||||
|
|
||||||
read = reader: set: lib.flatten (lib.attrValues (withSystem reader set));
|
read = reader: set: lib.flatten (lib.attrValues (withSystem reader set));
|
||||||
|
|
||||||
legacyPackages' = read readPackages (default resolved "legacyPackages" {});
|
legacyPackages' = read readPackages (resolved.legacyPackages or {});
|
||||||
packages' = read readPackages (default resolved "packages" {});
|
packages' = read readPackages (resolved.packages or {});
|
||||||
|
|
||||||
apps' = read readApps (default resolved "apps" {});
|
apps' = read readApps (resolved.apps or {});
|
||||||
|
|
||||||
|
|
||||||
collectSystems = lib.lists.foldr (
|
collectSystems = lib.lists.foldr (
|
||||||
drv@{ attribute_name, system, ... }: set:
|
drv@{ attribute_name, system, ... }: set:
|
||||||
let
|
let
|
||||||
present = default set "${attribute_name}" ({ platforms = []; } // drv);
|
present = set."${attribute_name}" or ({ platforms = []; } // drv);
|
||||||
|
|
||||||
drv' = present // {
|
drv' = present // {
|
||||||
platforms = present.platforms ++ [ system ];
|
platforms = present.platforms ++ [ system ];
|
||||||
|
@ -138,11 +142,9 @@ rec {
|
||||||
legacyPackages = lib.attrValues (collectSystems legacyPackages');
|
legacyPackages = lib.attrValues (collectSystems legacyPackages');
|
||||||
packages = lib.attrValues (collectSystems packages');
|
packages = lib.attrValues (collectSystems packages');
|
||||||
apps = lib.attrValues (collectSystems apps');
|
apps = lib.attrValues (collectSystems apps');
|
||||||
options = readOptions (default resolved "nixosModules" {}) false;
|
options = readFlakeOptions;
|
||||||
nixos-options = readOptions (
|
nixos-options = readOptions {
|
||||||
{
|
module = import "${builtins.fetchTarball { url = flake; }}/nixos/modules/module-list.nix";
|
||||||
"nixos" = import "${builtins.fetchTarball { url = flake; }}/nixos/modules/module-list.nix";
|
};
|
||||||
}
|
|
||||||
) true;
|
|
||||||
all = packages ++ apps ++ options;
|
all = packages ++ apps ++ options;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/// Flakes, or Nixpkgs.
|
/// Flakes, or Nixpkgs.
|
||||||
use std::{convert::TryInto, path::PathBuf};
|
use std::{convert::TryInto, path::PathBuf};
|
||||||
|
|
||||||
use super::{import::DocValue, pandoc::PandocExt};
|
use super::{import::{DocValue, ModulePath}, pandoc::PandocExt};
|
||||||
use crate::data::import::NixOption;
|
use crate::data::import::NixOption;
|
||||||
use log::error;
|
use log::error;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -110,7 +110,7 @@ pub enum Derivation {
|
||||||
|
|
||||||
option_example: Option<DocValue>,
|
option_example: Option<DocValue>,
|
||||||
|
|
||||||
option_flake: Option<(String, String)>,
|
option_flake: Option<ModulePath>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,18 @@ pub struct NixOption {
|
||||||
pub default: Option<DocValue>,
|
pub default: Option<DocValue>,
|
||||||
pub example: Option<DocValue>,
|
pub example: Option<DocValue>,
|
||||||
|
|
||||||
/// If defined in a flake, contains defining flake and module
|
/// If defined in a flake, contains defining flake and optionally a module
|
||||||
pub flake: Option<(String, String)>,
|
pub flake: Option<ModulePath>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum ModulePath {
|
||||||
|
/// A module taken from <flake>.nixosModule
|
||||||
|
/// JSON representation is a list, therefore use a 1-Tuple as representation
|
||||||
|
DefaultModule((String,)),
|
||||||
|
/// A module taken from <flake>.nixosModules.<name>
|
||||||
|
NamedModule((String, String)),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||||
|
@ -345,6 +355,32 @@ mod tests {
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_flake_option() {
|
||||||
|
let json = r#"
|
||||||
|
{
|
||||||
|
"declarations": [],
|
||||||
|
"name": "test-option",
|
||||||
|
"flake": ["flake", "module"]
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
serde_json::from_str::<NixOption>(json).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_flake_option_default_module() {
|
||||||
|
let json = r#"
|
||||||
|
{
|
||||||
|
"declarations": [],
|
||||||
|
"name": "test-option",
|
||||||
|
"flake": ["flake"]
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
serde_json::from_str::<NixOption>(json).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_option_parsing() {}
|
fn test_option_parsing() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ type alias ResultItemSource =
|
||||||
, source : Maybe String
|
, source : Maybe String
|
||||||
|
|
||||||
-- flake
|
-- flake
|
||||||
, flake : Maybe ( String, String )
|
, flake : Maybe (List String)
|
||||||
, flakeName : Maybe String
|
, flakeName : Maybe String
|
||||||
, flakeDescription : Maybe String
|
, flakeDescription : Maybe String
|
||||||
, flakeUrl : Maybe String
|
, flakeUrl : Maybe String
|
||||||
|
@ -274,17 +274,20 @@ viewResultItem channel _ show item =
|
||||||
Maybe.map asGithubLink item.source.source
|
Maybe.map asGithubLink item.source.source
|
||||||
|
|
||||||
flakeOrNixpkgs =
|
flakeOrNixpkgs =
|
||||||
case ( item.source.flakeName, item.source.flake, item.source.flakeUrl ) of
|
let
|
||||||
|
mkLink flake url =
|
||||||
|
a [ href url ] [ text flake ]
|
||||||
|
in
|
||||||
|
case ( item.source.flake, item.source.flakeUrl ) of
|
||||||
-- its a flake
|
-- its a flake
|
||||||
( Just name, Just ( flake, attr ), Just flakeUrl_ ) ->
|
( Just (flake :: []), Just url ) ->
|
||||||
Just
|
Just
|
||||||
[ li []
|
[ li [] [ mkLink flake url ]
|
||||||
[ a [ href flakeUrl_ ] [ text flake ]
|
|
||||||
, text "#"
|
|
||||||
, text attr
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
( Just (flake :: moduleName :: []), Just url ) ->
|
||||||
|
Just [ li [] [ mkLink flake url, text "#", text moduleName ] ]
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
Nothing
|
Nothing
|
||||||
in
|
in
|
||||||
|
@ -344,12 +347,16 @@ findSource channel source =
|
||||||
flakeOrNixpkgs =
|
flakeOrNixpkgs =
|
||||||
case ( source.flake, source.flakeUrl ) of
|
case ( source.flake, source.flakeUrl ) of
|
||||||
-- its a flake
|
-- its a flake
|
||||||
( Just ( name, module_ ), Just flakeUrl_ ) ->
|
( Just (name :: attrs), Just flakeUrl_ ) ->
|
||||||
|
let
|
||||||
|
module_ =
|
||||||
|
Maybe.withDefault "(default)" <| Maybe.map (\m -> "(Module: " ++ m ++ ")") <| List.head attrs
|
||||||
|
in
|
||||||
Just <|
|
Just <|
|
||||||
List.append
|
List.append
|
||||||
(Maybe.withDefault [] <| Maybe.map (\sourceFile_ -> [ sourceFile_, span [] [ text " in " ] ]) sourceFile)
|
(Maybe.withDefault [] <| Maybe.map (\sourceFile_ -> [ sourceFile_, span [] [ text " in " ] ]) sourceFile)
|
||||||
[ span [] [ text "Flake: " ]
|
[ span [] [ text "Flake: " ]
|
||||||
, a [ href flakeUrl_ ] [ text <| name ++ "(Module: " ++ module_ ++ ")" ]
|
, a [ href flakeUrl_ ] [ text <| name ++ module_ ]
|
||||||
]
|
]
|
||||||
|
|
||||||
( Nothing, _ ) ->
|
( Nothing, _ ) ->
|
||||||
|
@ -420,7 +427,7 @@ decodeResultItemSource =
|
||||||
|> Json.Decode.Pipeline.optional "option_example" (Json.Decode.map Just Json.Decode.string) Nothing
|
|> Json.Decode.Pipeline.optional "option_example" (Json.Decode.map Just Json.Decode.string) Nothing
|
||||||
|> Json.Decode.Pipeline.optional "option_source" (Json.Decode.map Just Json.Decode.string) Nothing
|
|> Json.Decode.Pipeline.optional "option_source" (Json.Decode.map Just Json.Decode.string) Nothing
|
||||||
|> Json.Decode.Pipeline.optional "option_flake"
|
|> Json.Decode.Pipeline.optional "option_flake"
|
||||||
(Json.Decode.map Just <| Json.Decode.map2 Tuple.pair (Json.Decode.index 0 Json.Decode.string) (Json.Decode.index 1 Json.Decode.string))
|
(Json.Decode.map Just <| Json.Decode.list Json.Decode.string)
|
||||||
Nothing
|
Nothing
|
||||||
|> Json.Decode.Pipeline.optional "flake_name" (Json.Decode.map Just Json.Decode.string) Nothing
|
|> Json.Decode.Pipeline.optional "flake_name" (Json.Decode.map Just Json.Decode.string) Nothing
|
||||||
|> Json.Decode.Pipeline.optional "flake_description" (Json.Decode.map Just Json.Decode.string) Nothing
|
|> Json.Decode.Pipeline.optional "flake_description" (Json.Decode.map Just Json.Decode.string) Nothing
|
||||||
|
|
Loading…
Reference in a new issue