diff --git a/lib/attrsets.nix b/lib/attrsets.nix index 2a1b866dbc5e..d374d229f597 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 d7a05fec8338..e4e3e7d325a4 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 7169c46fcbbc..2f818c88de5d 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 b8e666a92f9a..81e2fa353295 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") ||