mirror of
https://github.com/nix-community/home-manager
synced 2024-11-25 22:20:29 +00:00
lib: improve DAG library
Specifically, - directly export `modules/lib/dag.nix` instead of renaming attributes, - run through utilities to reuse code where possible, - expose `lib.hm.dag.isEntry` and reuse it in `modules/lib/types-dag.nix`, - reuse utilities through `lib` set instead of passing imports to functions, and - eta reduction of `map`, `entryAnywhere`, `entryAfter` and `entryBefore`.
This commit is contained in:
parent
30dda628bc
commit
4a724cb84c
4 changed files with 50 additions and 79 deletions
|
@ -4,39 +4,38 @@
|
||||||
#
|
#
|
||||||
# - not specific to strings, i.e., any payload is OK,
|
# - not specific to strings, i.e., any payload is OK,
|
||||||
#
|
#
|
||||||
# - the addition of the function `dagEntryBefore` indicating a
|
# - the addition of the function `entryBefore` indicating a "wanted
|
||||||
# "wanted by" relationship.
|
# by" relationship.
|
||||||
|
|
||||||
{ lib }:
|
{ lib }:
|
||||||
|
|
||||||
let inherit (lib) all any filterAttrs mapAttrs mapAttrsToList toposort;
|
let inherit (lib) all filterAttrs hm mapAttrs toposort;
|
||||||
in rec {
|
in {
|
||||||
|
empty = { };
|
||||||
emptyDag = { };
|
|
||||||
|
|
||||||
|
isEntry = e: e ? data && e ? after && e ? before;
|
||||||
isDag = dag:
|
isDag = dag:
|
||||||
let isEntry = e: (e ? data) && (e ? after) && (e ? before);
|
builtins.isAttrs dag && all hm.dag.isEntry (builtins.attrValues dag);
|
||||||
in builtins.isAttrs dag && all (x: x) (mapAttrsToList (n: isEntry) dag);
|
|
||||||
|
|
||||||
# Takes an attribute set containing entries built by
|
# Takes an attribute set containing entries built by entryAnywhere,
|
||||||
# dagEntryAnywhere, dagEntryAfter, and dagEntryBefore to a
|
# entryAfter, and entryBefore to a topologically sorted list of
|
||||||
# topologically sorted list of entries.
|
# entries.
|
||||||
#
|
#
|
||||||
# Internally this function uses the `toposort` function in
|
# Internally this function uses the `toposort` function in
|
||||||
# `<nixpkgs/lib/lists.nix>` and its value is accordingly.
|
# `<nixpkgs/lib/lists.nix>` and its value is accordingly.
|
||||||
#
|
#
|
||||||
# Specifically, the result on success is
|
# Specifically, the result on success is
|
||||||
#
|
#
|
||||||
# { result = [{name = ?; data = ?;} …] }
|
# { result = [ { name = ?; data = ?; } … ] }
|
||||||
#
|
#
|
||||||
# For example
|
# For example
|
||||||
#
|
#
|
||||||
# nix-repl> dagTopoSort {
|
# nix-repl> topoSort {
|
||||||
# a = dagEntryAnywhere "1";
|
# a = entryAnywhere "1";
|
||||||
# b = dagEntryAfter ["a" "c"] "2";
|
# b = entryAfter [ "a" "c" ] "2";
|
||||||
# c = dagEntryBefore ["d"] "3";
|
# c = entryBefore [ "d" ] "3";
|
||||||
# d = dagEntryBefore ["e"] "4";
|
# d = entryBefore [ "e" ] "4";
|
||||||
# e = dagEntryAnywhere "5";
|
# e = entryAnywhere "5";
|
||||||
# } == {
|
# } == {
|
||||||
# result = [
|
# result = [
|
||||||
# { data = "1"; name = "a"; }
|
# { data = "1"; name = "a"; }
|
||||||
|
@ -51,66 +50,54 @@ in rec {
|
||||||
# And the result on error is
|
# And the result on error is
|
||||||
#
|
#
|
||||||
# {
|
# {
|
||||||
# cycle = [ {after = ?; name = ?; data = ?} … ];
|
# cycle = [ { after = ?; name = ?; data = ? } … ];
|
||||||
# loops = [ {after = ?; name = ?; data = ?} … ];
|
# loops = [ { after = ?; name = ?; data = ? } … ];
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
# For example
|
# For example
|
||||||
#
|
#
|
||||||
# nix-repl> dagTopoSort {
|
# nix-repl> topoSort {
|
||||||
# a = dagEntryAnywhere "1";
|
# a = entryAnywhere "1";
|
||||||
# b = dagEntryAfter ["a" "c"] "2";
|
# b = entryAfter [ "a" "c" ] "2";
|
||||||
# c = dagEntryAfter ["d"] "3";
|
# c = entryAfter [ "d" ] "3";
|
||||||
# d = dagEntryAfter ["b"] "4";
|
# d = entryAfter [ "b" ] "4";
|
||||||
# e = dagEntryAnywhere "5";
|
# e = entryAnywhere "5";
|
||||||
# } == {
|
# } == {
|
||||||
# cycle = [
|
# cycle = [
|
||||||
# { after = ["a" "c"]; data = "2"; name = "b"; }
|
# { after = [ "a" "c" ]; data = "2"; name = "b"; }
|
||||||
# { after = ["d"]; data = "3"; name = "c"; }
|
# { after = [ "d" ]; data = "3"; name = "c"; }
|
||||||
# { after = ["b"]; data = "4"; name = "d"; }
|
# { after = [ "b" ]; data = "4"; name = "d"; }
|
||||||
# ];
|
# ];
|
||||||
# loops = [
|
# loops = [
|
||||||
# { after = ["a" "c"]; data = "2"; name = "b"; }
|
# { after = [ "a" "c" ]; data = "2"; name = "b"; }
|
||||||
# ];
|
# ];
|
||||||
# } == {}
|
# }
|
||||||
# true
|
# true
|
||||||
dagTopoSort = dag:
|
topoSort = dag:
|
||||||
let
|
let
|
||||||
dagBefore = dag: name:
|
dagBefore = dag: name:
|
||||||
mapAttrsToList (n: v: n)
|
builtins.attrNames
|
||||||
(filterAttrs (n: v: any (a: a == name) v.before) dag);
|
(filterAttrs (n: v: builtins.elem name v.before) dag);
|
||||||
normalizedDag = mapAttrs (n: v: {
|
normalizedDag = mapAttrs (n: v: {
|
||||||
name = n;
|
name = n;
|
||||||
data = v.data;
|
data = v.data;
|
||||||
after = v.after ++ dagBefore dag n;
|
after = v.after ++ dagBefore dag n;
|
||||||
}) dag;
|
}) dag;
|
||||||
before = a: b: any (c: a.name == c) b.after;
|
before = a: b: builtins.elem a.name b.after;
|
||||||
sorted = toposort before (mapAttrsToList (n: v: v) normalizedDag);
|
sorted = toposort before (builtins.attrValues normalizedDag);
|
||||||
in if sorted ? result then {
|
in if sorted ? result then {
|
||||||
result = map (v: { inherit (v) name data; }) sorted.result;
|
result = map (v: { inherit (v) name data; }) sorted.result;
|
||||||
} else
|
} else
|
||||||
sorted;
|
sorted;
|
||||||
|
|
||||||
# Applies a function to each element of the given DAG.
|
# Applies a function to each element of the given DAG.
|
||||||
dagMap = f: dag: mapAttrs (n: v: v // { data = f n v.data; }) dag;
|
map = f: mapAttrs (n: v: v // { data = f n v.data; });
|
||||||
|
|
||||||
|
entryBetween = before: after: data: { inherit data before after; };
|
||||||
|
|
||||||
# Create a DAG entry with no particular dependency information.
|
# Create a DAG entry with no particular dependency information.
|
||||||
dagEntryAnywhere = data: {
|
entryAnywhere = hm.dag.entryBetween [ ] [ ];
|
||||||
inherit data;
|
|
||||||
before = [ ];
|
|
||||||
after = [ ];
|
|
||||||
};
|
|
||||||
|
|
||||||
dagEntryBetween = before: after: data: { inherit data before after; };
|
|
||||||
|
|
||||||
dagEntryAfter = after: data: {
|
|
||||||
inherit data after;
|
|
||||||
before = [ ];
|
|
||||||
};
|
|
||||||
|
|
||||||
dagEntryBefore = before: data: {
|
|
||||||
inherit data before;
|
|
||||||
after = [ ];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
entryAfter = hm.dag.entryBetween [ ];
|
||||||
|
entryBefore = before: hm.dag.entryBetween before [ ];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,7 @@
|
||||||
{ lib }:
|
{ lib }:
|
||||||
|
|
||||||
rec {
|
rec {
|
||||||
dag =
|
dag = import ./dag.nix { inherit lib; };
|
||||||
let
|
|
||||||
d = import ./dag.nix { inherit lib; };
|
|
||||||
in
|
|
||||||
{
|
|
||||||
empty = d.emptyDag;
|
|
||||||
isDag = d.isDag;
|
|
||||||
topoSort = d.dagTopoSort;
|
|
||||||
map = d.dagMap;
|
|
||||||
entryAnywhere = d.dagEntryAnywhere;
|
|
||||||
entryBetween = d.dagEntryBetween;
|
|
||||||
entryAfter = d.dagEntryAfter;
|
|
||||||
entryBefore = d.dagEntryBefore;
|
|
||||||
};
|
|
||||||
|
|
||||||
assertions = import ./assertions.nix { inherit lib; };
|
assertions = import ./assertions.nix { inherit lib; };
|
||||||
|
|
||||||
|
@ -22,7 +9,7 @@ rec {
|
||||||
gvariant = import ./gvariant.nix { inherit lib; };
|
gvariant = import ./gvariant.nix { inherit lib; };
|
||||||
maintainers = import ./maintainers.nix;
|
maintainers = import ./maintainers.nix;
|
||||||
strings = import ./strings.nix { inherit lib; };
|
strings = import ./strings.nix { inherit lib; };
|
||||||
types = import ./types.nix { inherit dag gvariant lib; };
|
types = import ./types.nix { inherit gvariant lib; };
|
||||||
|
|
||||||
shell = import ./shell.nix { inherit lib; };
|
shell = import ./shell.nix { inherit lib; };
|
||||||
zsh = import ./zsh.nix { inherit lib; };
|
zsh = import ./zsh.nix { inherit lib; };
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
{ dag, lib }:
|
{ lib }:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
concatStringsSep defaultFunctor fixedWidthNumber imap1 isAttrs isList length
|
concatStringsSep defaultFunctor fixedWidthNumber hm imap1 isAttrs isList
|
||||||
listToAttrs mapAttrs mkIf mkOrder mkOption mkOptionType nameValuePair
|
length listToAttrs mapAttrs mkIf mkOrder mkOption mkOptionType nameValuePair
|
||||||
stringLength types warn;
|
stringLength types warn;
|
||||||
|
|
||||||
isDagEntry = e: isAttrs e && (e ? data) && (e ? after) && (e ? before);
|
|
||||||
|
|
||||||
dagEntryOf = elemType:
|
dagEntryOf = elemType:
|
||||||
let
|
let
|
||||||
submoduleType = types.submodule ({ name, ... }: {
|
submoduleType = types.submodule ({ name, ... }: {
|
||||||
|
@ -21,10 +19,10 @@ let
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
maybeConvert = def:
|
maybeConvert = def:
|
||||||
if isDagEntry def.value then
|
if hm.dag.isEntry def.value then
|
||||||
def.value
|
def.value
|
||||||
else
|
else
|
||||||
dag.entryAnywhere (if def ? priority then
|
hm.dag.entryAnywhere (if def ? priority then
|
||||||
mkOrder def.priority def.value
|
mkOrder def.priority def.value
|
||||||
else
|
else
|
||||||
def.value);
|
def.value);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{ lib, dag ? import ./dag.nix { inherit lib; }
|
{ lib, gvariant ? import ./gvariant.nix { inherit lib; } }:
|
||||||
, gvariant ? import ./gvariant.nix { inherit lib; } }:
|
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
|
@ -7,7 +6,7 @@ let
|
||||||
mergeAttrs mergeDefaultOption mergeOneOption mergeOptions mkOption
|
mergeAttrs mergeDefaultOption mergeOneOption mergeOptions mkOption
|
||||||
mkOptionType showFiles showOption types;
|
mkOptionType showFiles showOption types;
|
||||||
|
|
||||||
typesDag = import ./types-dag.nix { inherit dag lib; };
|
typesDag = import ./types-dag.nix { inherit lib; };
|
||||||
|
|
||||||
# Needed since the type is called gvariant and its merge attribute
|
# Needed since the type is called gvariant and its merge attribute
|
||||||
# must refer back to the type.
|
# must refer back to the type.
|
||||||
|
|
Loading…
Reference in a new issue