nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at 22.05 185 lines 4.7 kB view raw
1{ stdenv, runCommand, ruby, lib, rsync 2, defaultGemConfig, buildRubyGem, buildEnv 3, makeBinaryWrapper 4, bundler 5}@defs: 6 7{ 8 name ? null 9, pname ? null 10, mainGemName ? null 11, gemdir ? null 12, gemfile ? null 13, lockfile ? null 14, gemset ? null 15, ruby ? defs.ruby 16, copyGemFiles ? false # Copy gem files instead of symlinking 17, gemConfig ? defaultGemConfig 18, postBuild ? null 19, document ? [] 20, meta ? {} 21, groups ? null 22, ignoreCollisions ? false 23, buildInputs ? [] 24, ... 25}@args: 26 27assert name == null -> pname != null; 28 29with import ./functions.nix { inherit lib gemConfig; }; 30 31let 32 gemFiles = bundlerFiles args; 33 34 importedGemset = if builtins.typeOf gemFiles.gemset != "set" 35 then import gemFiles.gemset 36 else gemFiles.gemset; 37 38 filteredGemset = filterGemset { inherit ruby groups; } importedGemset; 39 40 configuredGemset = lib.flip lib.mapAttrs filteredGemset (name: attrs: 41 applyGemConfigs (attrs // { inherit ruby document; gemName = name; }) 42 ); 43 44 hasBundler = builtins.hasAttr "bundler" filteredGemset; 45 46 bundler = 47 if hasBundler then gems.bundler 48 else defs.bundler.override (attrs: { inherit ruby; }); 49 50 gems = lib.flip lib.mapAttrs configuredGemset (name: attrs: buildGem name attrs); 51 52 name' = if name != null then 53 name 54 else 55 let 56 gem = gems.${pname}; 57 version = gem.version; 58 in 59 "${pname}-${version}"; 60 61 pname' = if pname != null then 62 pname 63 else 64 name; 65 66 copyIfBundledByPath = { bundledByPath ? false, ...}: 67 (if bundledByPath then 68 assert gemFiles.gemdir != null; "cp -a ${gemFiles.gemdir}/* $out/" #*/ 69 else "" 70 ); 71 72 maybeCopyAll = pkgname: if pkgname == null then "" else 73 let 74 mainGem = gems.${pkgname} or (throw "bundlerEnv: gem ${pkgname} not found"); 75 in 76 copyIfBundledByPath mainGem; 77 78 # We have to normalize the Gemfile.lock, otherwise bundler tries to be 79 # helpful by doing so at run time, causing executables to immediately bail 80 # out. Yes, I'm serious. 81 confFiles = runCommand "gemfile-and-lockfile" {} '' 82 mkdir -p $out 83 ${maybeCopyAll mainGemName} 84 cp ${gemFiles.gemfile} $out/Gemfile || ls -l $out/Gemfile 85 cp ${gemFiles.lockfile} $out/Gemfile.lock || ls -l $out/Gemfile.lock 86 ''; 87 88 buildGem = name: attrs: ( 89 let 90 gemAttrs = composeGemAttrs ruby gems name attrs; 91 in 92 if gemAttrs.type == "path" then 93 pathDerivation (gemAttrs.source // gemAttrs) 94 else 95 buildRubyGem gemAttrs 96 ); 97 98 envPaths = lib.attrValues gems ++ lib.optional (!hasBundler) bundler; 99 100 101 basicEnvArgs = { 102 inherit buildInputs ignoreCollisions; 103 104 name = name'; 105 106 paths = envPaths; 107 pathsToLink = [ "/lib" ]; 108 109 postBuild = genStubsScript (defs // args // { 110 inherit confFiles bundler groups; 111 binPaths = envPaths; 112 }) + lib.optionalString (postBuild != null) postBuild; 113 114 meta = { platforms = ruby.meta.platforms; } // meta; 115 116 passthru = rec { 117 inherit ruby bundler gems confFiles envPaths; 118 119 wrappedRuby = stdenv.mkDerivation { 120 name = "wrapped-ruby-${pname'}"; 121 122 nativeBuildInputs = [ makeBinaryWrapper ]; 123 124 dontUnpack = true; 125 126 buildPhase = '' 127 mkdir -p $out/bin 128 for i in ${ruby}/bin/*; do 129 makeWrapper "$i" $out/bin/$(basename "$i") \ 130 --set BUNDLE_GEMFILE ${confFiles}/Gemfile \ 131 --unset BUNDLE_PATH \ 132 --set BUNDLE_FROZEN 1 \ 133 --set GEM_HOME ${basicEnv}/${ruby.gemPath} \ 134 --set GEM_PATH ${basicEnv}/${ruby.gemPath} 135 done 136 ''; 137 138 dontInstall = true; 139 140 doCheck = true; 141 checkPhase = '' 142 $out/bin/ruby --help > /dev/null 143 ''; 144 145 inherit (ruby) meta; 146 }; 147 148 env = let 149 irbrc = builtins.toFile "irbrc" '' 150 if !(ENV["OLD_IRBRC"].nil? || ENV["OLD_IRBRC"].empty?) 151 require ENV["OLD_IRBRC"] 152 end 153 require 'rubygems' 154 require 'bundler/setup' 155 ''; 156 in stdenv.mkDerivation { 157 name = "${pname'}-interactive-environment"; 158 nativeBuildInputs = [ wrappedRuby basicEnv ]; 159 shellHook = '' 160 export OLD_IRBRC=$IRBRC 161 export IRBRC=${irbrc} 162 ''; 163 buildCommand = '' 164 echo >&2 "" 165 echo >&2 "*** Ruby 'env' attributes are intended for interactive nix-shell sessions, not for building! ***" 166 echo >&2 "" 167 exit 1 168 ''; 169 }; 170 }; 171 }; 172 173 basicEnv = 174 if copyGemFiles then 175 runCommand name' basicEnvArgs '' 176 mkdir -p $out 177 for i in $paths; do 178 ${rsync}/bin/rsync -a $i/lib $out/ 179 done 180 eval "$postBuild" 181 '' 182 else 183 buildEnv basicEnvArgs; 184in 185 basicEnv