From 2a194746a53480c5073a54af9ae007df974454ab Mon Sep 17 00:00:00 2001 From: zimbatm Date: Sun, 2 Oct 2016 22:59:35 +0100 Subject: [PATCH] bundlerEnv: refactor Add `pname` attribute: if passed, the derivation name defaults to the gem name + version and only expose the gem's bin. Add `gemdir` attribute: gives a default lookup path for the Gemfile, Gemfile.lock and gemset.nix. Set the `meta.platforms' to `ruby.meta.platforms' by default. --- .../ruby-modules/bundler-env/default.nix | 72 +++++++++++++++---- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/pkgs/development/ruby-modules/bundler-env/default.nix b/pkgs/development/ruby-modules/bundler-env/default.nix index 56a3b371d1dc..57ca23d41436 100644 --- a/pkgs/development/ruby-modules/bundler-env/default.nix +++ b/pkgs/development/ruby-modules/bundler-env/default.nix @@ -6,7 +6,14 @@ , tree }@defs: -{ name, gemset, gemfile, lockfile, ruby ? defs.ruby, gemConfig ? defaultGemConfig +{ name ? null +, pname ? null +, gemdir ? null +, gemfile ? null +, lockfile ? null +, gemset ? null +, ruby ? defs.ruby +, gemConfig ? defaultGemConfig , postBuild ? null , document ? [] , meta ? {} @@ -16,54 +23,95 @@ }@args: let - importedGemset = import gemset; + drvName = + if name != null then name + else if pname != null then "${toString pname}-${mainGem.version}" + else throw "bundlerEnv: either pname or name must be set"; + + mainGem = + if pname == null then null + else gems."${pname}" or (throw "bundlerEnv: gem ${pname} not found"); + + gemfile' = + if gemfile == null then gemdir + "/Gemfile" + else gemfile; + + lockfile' = + if lockfile == null then gemdir + "/Gemfile.lock" + else lockfile; + + gemset' = + if gemset == null then gemdir + "/gemset.nix" + else gemset; + + importedGemset = import gemset'; + filteredGemset = (lib.filterAttrs (name: attrs: if (builtins.hasAttr "groups" attrs) then (builtins.any (gemGroup: builtins.any (group: group == gemGroup) groups) attrs.groups) else true ) importedGemset); + applyGemConfigs = attrs: (if gemConfig ? "${attrs.gemName}" then attrs // gemConfig."${attrs.gemName}" attrs else attrs); + configuredGemset = lib.flip lib.mapAttrs filteredGemset (name: attrs: applyGemConfigs (attrs // { inherit ruby; gemName = name; }) ); + hasBundler = builtins.hasAttr "bundler" filteredGemset; - bundler = if hasBundler then gems.bundler else defs.bundler.override (attrs: { inherit ruby; }); + + bundler = + if hasBundler then gems.bundler + else defs.bundler.override (attrs: { inherit ruby; }); + gems = lib.flip lib.mapAttrs configuredGemset (name: attrs: buildRubyGem ((removeAttrs attrs ["source"]) // attrs.source // { inherit ruby; gemName = name; gemPath = map (gemName: gems."${gemName}") (attrs.dependencies or []); })); + # We have to normalize the Gemfile.lock, otherwise bundler tries to be # helpful by doing so at run time, causing executables to immediately bail # out. Yes, I'm serious. confFiles = runCommand "gemfile-and-lockfile" {} '' mkdir -p $out - cp ${gemfile} $out/Gemfile - cp ${lockfile} $out/Gemfile.lock + cp ${gemfile'} $out/Gemfile + cp ${lockfile'} $out/Gemfile.lock ''; + envPaths = lib.attrValues gems ++ lib.optional (!hasBundler) bundler; + + binPaths = if mainGem != null then [ mainGem ] else envPaths; + bundlerEnv = buildEnv { - inherit name ignoreCollisions; + inherit ignoreCollisions; + + name = drvName; + paths = envPaths; pathsToLink = [ "/lib" ]; + postBuild = '' ${ruby}/bin/ruby ${./gen-bin-stubs.rb} \ "${ruby}/bin/ruby" \ "${confFiles}/Gemfile" \ "$out/${ruby.gemPath}" \ "${bundler}/${ruby.gemPath}" \ - ${lib.escapeShellArg envPaths} \ + ${lib.escapeShellArg binPaths} \ ${lib.escapeShellArg groups} '' + lib.optionalString (postBuild != null) postBuild; + + meta = { platforms = ruby.meta.platforms; } // meta; + passthru = rec { - inherit ruby bundler meta gems; + inherit ruby bundler gems; wrappedRuby = stdenv.mkDerivation { - name = "wrapped-ruby-${name}"; + name = "wrapped-ruby-${drvName}"; nativeBuildInputs = [ makeWrapper ]; buildCommand = '' mkdir -p $out/bin @@ -87,7 +135,7 @@ let require 'bundler/setup' ''; in stdenv.mkDerivation { - name = "interactive-${name}-environment"; + name = "interactive-${drvName}-environment"; nativeBuildInputs = [ wrappedRuby bundlerEnv ]; shellHook = '' export OLD_IRBRC="$IRBRC" @@ -102,7 +150,5 @@ let }; }; }; - in - -bundlerEnv + bundlerEnv