let lib = import ; in rec { inherit lib; input = [ { x = [ "pool" "zfs" ]; y = [ "mdadm" "raid1" ]; } { x = [ "pool" "zfs" ]; y = [ "disk" "sda" ]; } { x = [ "mdadm" "raid1" ]; y = [ "disk" "sdb" ]; } { x = [ "mdadm" "raid1" ]; y = [ "disk" "sdc" ]; } ]; outNodes = node: graph: lib.unique (builtins.map (e: e.y) (builtins.filter (v: v.x == node) graph)); vertices = graph: lib.unique (builtins.map (x: x.y) graph ++ builtins.map (x: x.x) graph); deleteVertex = node: graph: (builtins.filter (v: v.x != node && v.y != node) graph); findSink = graph: lib.findFirst (v: outNodes v graph == [ ]) (lib.trace graph (builtins.abort "No sink found")) ( vertices graph ); topSort = graph: if graph == [ ] then [ ] else if builtins.length graph == 1 then let only = builtins.head graph; in [ only.y only.x ] else let sink = findSink graph; in [ sink ] ++ topSort (deleteVertex sink graph); output = topSort input; }