summary refs log tree commit diff
path: root/pkgs/lib/properties.nix
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/lib/properties.nix')
-rw-r--r--pkgs/lib/properties.nix59
1 files changed, 59 insertions, 0 deletions
diff --git a/pkgs/lib/properties.nix b/pkgs/lib/properties.nix
index f28d652d4e69..3964c117f14f 100644
--- a/pkgs/lib/properties.nix
+++ b/pkgs/lib/properties.nix
@@ -382,4 +382,63 @@ rec {
           mkNotdef
       ) prioValList;
 
+  /* mkOrder */
+
+  # Order definitions based on there index value.  This property is useful
+  # when the result of the merge function depends on the order on the
+  # initial list.  (e.g. concatStrings) Definitions are ordered based on
+  # their rank.  The lowest ranked definition would be the first to element
+  # of the list used by the merge function.  And the highest ranked
+  # definition would be the last.  Definitions which does not have any rank
+  # value have the default rank of 100.
+  isOrder = attrs: (typeOf attrs) == "order";
+  mkOrder = rank: content: mkProperty {
+    property = {
+      _type = "order";
+      onGlobalEval = onOrderGlobalEval;
+      inherit rank;
+    };
+    inherit content;
+  };
+
+  mkHeader = mkOrder 10;
+  mkFooter = mkOrder 1000;
+
+  # Fetch the rank of each definition (add the default rank is none) and
+  # sort them based on their ranking.
+  onOrderGlobalEval = valList:
+    let
+      defaultRank = 100;
+
+      inherit (builtins) lessThan;
+
+      getRankVal =
+        foldProperty
+          (foldFilter isOrder
+            (p@{property, content, ...}:
+              if content ? rank then
+                content
+              else
+                content // {
+                  inherit (property) rank;
+                }
+            )
+            (p@{property, content, ...}:
+              content // {
+                value = p // { content = content.value; };
+              }
+            )
+          ) (value: { inherit value; });
+
+      addDefaultRank = x:
+        if x ? rank then x
+        else x // { rank = defaultRank; };
+
+      rankValList = map (x: addDefaultRank (getRankVal x)) valList;
+
+      cmp = x: y:
+        builtins.lessThan x.rank y.rank;
+    in
+      map (x: x.value) (sort cmp rankValList);
+
 }