summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--lib/attrsets.nix9
-rw-r--r--lib/default.nix4
-rw-r--r--lib/fixed-points.nix10
-rw-r--r--pkgs/development/ruby-modules/bundled-common/functions.nix20
4 files changed, 39 insertions, 4 deletions
diff --git a/lib/attrsets.nix b/lib/attrsets.nix
index 2a1b866dbc5..d374d229f59 100644
--- a/lib/attrsets.nix
+++ b/lib/attrsets.nix
@@ -94,6 +94,15 @@ rec {
   attrValues = builtins.attrValues or (attrs: attrVals (attrNames attrs) attrs);
 
 
+  /* Given a set of attribute names, return the set of the corresponding
+     attributes from the given set.
+
+     Example:
+       getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; }
+       => { a = 1; b = 2; }
+  */
+  getAttrs = names: attrs: genAttrs names (name: attrs.${name});
+
   /* Collect each attribute named `attr' from a list of attribute
      sets.  Sets that don't contain the named attribute are ignored.
 
diff --git a/lib/default.nix b/lib/default.nix
index d7a05fec833..e4e3e7d325a 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -61,10 +61,10 @@ let
       boolToString mergeAttrs flip mapNullable inNixShell min max
       importJSON warn info nixpkgsVersion version mod compare
       splitByAndCompare functionArgs setFunctionArgs isFunction;
-    inherit (fixedPoints) fix fix' extends composeExtensions
+    inherit (fixedPoints) fix fix' converge extends composeExtensions
       makeExtensible makeExtensibleWithCustomName;
     inherit (attrsets) attrByPath hasAttrByPath setAttrByPath
-      getAttrFromPath attrVals attrValues catAttrs filterAttrs
+      getAttrFromPath attrVals attrValues getAttrs catAttrs filterAttrs
       filterAttrsRecursive foldAttrs collect nameValuePair mapAttrs
       mapAttrs' mapAttrsToList mapAttrsRecursive mapAttrsRecursiveCond
       genAttrs isDerivation toDerivation optionalAttrs
diff --git a/lib/fixed-points.nix b/lib/fixed-points.nix
index 7169c46fcbb..2f818c88de5 100644
--- a/lib/fixed-points.nix
+++ b/lib/fixed-points.nix
@@ -24,6 +24,16 @@ rec {
   # for a concrete example.
   fix' = f: let x = f x // { __unfix__ = f; }; in x;
 
+  # Return the fixpoint that `f` converges to when called recursively, starting
+  # with the input `x`.
+  #
+  #     nix-repl> converge (x: x / 2) 16
+  #     0
+  converge = f: x:
+    if (f x) == x
+    then x
+    else converge f (f x);
+
   # Modify the contents of an explicitly recursive attribute set in a way that
   # honors `self`-references. This is accomplished with a function
   #
diff --git a/pkgs/development/ruby-modules/bundled-common/functions.nix b/pkgs/development/ruby-modules/bundled-common/functions.nix
index b8e666a92f9..81e2fa35329 100644
--- a/pkgs/development/ruby-modules/bundled-common/functions.nix
+++ b/pkgs/development/ruby-modules/bundled-common/functions.nix
@@ -1,5 +1,9 @@
 { lib, gemConfig, ... }:
-rec {
+
+let
+  inherit (lib) attrValues concatMap converge filterAttrs getAttrs;
+
+in rec {
   bundlerFiles = {
     gemfile ? null
   , lockfile ? null
@@ -22,7 +26,19 @@ rec {
     else gemset;
   };
 
-  filterGemset = {ruby, groups,...}: gemset: lib.filterAttrs (name: attrs: platformMatches ruby attrs && groupMatches groups attrs) gemset;
+  filterGemset = { ruby, groups, ... }: gemset:
+    let
+      platformGems = filterAttrs (_: platformMatches ruby) gemset;
+      directlyMatchingGems = filterAttrs (_: groupMatches groups) platformGems;
+
+      expandDependencies = gems:
+        let
+          depNames = concatMap (gem: gem.dependencies or []) (attrValues gems);
+          deps = getAttrs depNames platformGems;
+        in
+          gems // deps;
+    in
+      converge expandDependencies directlyMatchingGems;
 
   platformMatches = {rubyEngine, version, ...}: attrs: (
   !(attrs ? "platforms") ||