nixpkgs/pkgs/development/interpreters/ruby/bundler-env.nix

234 lines
5.9 KiB
Nix
Raw Normal View History

{ stdenv, runCommand, writeText, writeScript, writeScriptBin, ruby, lib
, callPackage , gemFixes, fetchurl, fetchgit, buildRubyGem
#, bundler_PATCHED
, bundler_HEAD
, git
2015-01-18 23:47:28 +00:00
}@defs:
# This is a work-in-progress.
# The idea is that his will replace load-ruby-env.nix.
2015-01-18 23:47:28 +00:00
{ name, gemset, gemfile, lockfile, ruby ? defs.ruby, fixes ? gemFixes }@args:
let
const = x: y: x;
bundler = bundler_HEAD.override { inherit ruby; };
inherit (builtins) attrValues;
2015-01-18 23:47:28 +00:00
2015-01-20 06:07:55 +00:00
gemName = attrs: "${attrs.name}-${attrs.version}.gem";
2015-01-20 06:07:55 +00:00
fetchers.path = attrs: attrs.source.path;
fetchers.gem = attrs: fetchurl {
url = "${attrs.source.source or "https://rubygems.org"}/downloads/${gemName attrs}";
inherit (attrs.source) sha256;
};
2015-01-18 23:47:28 +00:00
fetchers.git = attrs: fetchgit {
2015-01-20 06:07:55 +00:00
inherit (attrs.source) url rev sha256 fetchSubmodules;
2015-01-18 23:47:28 +00:00
leaveDotGit = true;
};
2015-01-20 06:07:55 +00:00
applySrc = attrs:
attrs // {
src = (fetchers."${attrs.source.type}" attrs);
};
applyFixes = attrs:
if fixes ? "${attrs.name}"
then attrs // fixes."${attrs.name}" attrs
else attrs;
# patch a gem or source tree.
# for gems, the gem is unpacked, patched, and then repacked.
# see: https://github.com/fedora-ruby/gem-patch/blob/master/lib/rubygems/patcher.rb
applyPatches = { attrs }:
if (!(attrs ? patches))
then attrs
else attrs // { src =
stdenv.mkDerivation {
name = gemName attrs;
phases = [ "unpackPhase" "patchPhase" "installPhase" ];
buildInputs = [ ruby ];
inherit (attrs) patches;
unpackPhase = ''
runHook preUnpack
if [[ -f ${attrs.src} ]]; then
isGem=1
gem unpack ${attrs.src} --target=contents
else
cp -r ${attrs.src} contents
chmod -R +w contents
fi
cd contents
runHook postUnpack
'';
installPhase = ''
runHook preInstall
mkdir build
if [[ -n "$isGem" ]]; then
${writeScript "repack.rb" ''
#!${ruby}/bin/ruby
require 'rubygems'
require 'fileutils'
out = ENV['out']
files = Dir['**/{.[^\.]*,*}']
package = Gem::Package.new("${attrs.src}")
patched_package = Gem::Package.new(package.spec.file_name)
patched_package.spec = package.spec.clone
patched_package.spec.files = files
# Change dir and build the patched gem
Dir.chdir("../build") do
patched_package.build false
end
FileUtils.cp "../build/#{package.file_name}" out
''}
else
cp -r . out
fi
runHook postInstall
'';
};
};
2015-01-18 23:47:28 +00:00
instantiate = (attrs:
2015-01-20 06:07:55 +00:00
applyFixes (applySrc attrs)
2015-01-18 23:47:28 +00:00
);
instantiated = lib.flip lib.mapAttrs (import gemset) (name: attrs:
instantiate (attrs // { inherit name; })
);
2015-01-20 06:07:55 +00:00
# copy *.gem to ./gems
copyGems = lib.fold (next: acc:
if next.source.type == "gem"
2015-01-20 06:07:55 +00:00
then acc + "cp ${next.src} gems/${gemName next}\n"
else acc
2015-01-20 06:07:55 +00:00
) "" (attrValues instantiated);
2015-01-18 23:47:28 +00:00
runRuby = name: env: command:
runCommand name env ''
${ruby}/bin/ruby ${writeText name command}
'';
# TODO: include json_pure, so the version of ruby doesn't matter.
# not all rubies have support for JSON built-in,
# so we'll convert JSON to ruby expressions.
2015-01-20 06:07:55 +00:00
json2rb = writeScript "json2rb" ''
2015-01-18 23:47:28 +00:00
#!${ruby}/bin/ruby
begin
require 'json'
rescue LoadError => ex
require 'json_pure'
end
puts JSON.parse(STDIN.read).inspect
'';
# dump the instantiated gemset as a ruby expression.
serializedGemset = runCommand "gemset.rb" { json = builtins.toJSON instantiated; } ''
2015-01-20 06:07:55 +00:00
printf '%s' "$json" | ${json2rb} > $out
2015-01-18 23:47:28 +00:00
'';
# this is a mapping from a source type and identifier (uri/path/etc)
# to the pure store path.
# we'll use this from the patched bundler to make fetching sources pure.
sources = runRuby "sources.rb" { gemset = serializedGemset; } ''
out = ENV['out']
gemset = eval(File.read(ENV['gemset']))
sources = {
"git" => { },
"path" => { },
"gem" => { },
"svn" => { }
}
gemset.each_value do |spec|
type = spec["source"]["type"]
val = spec["src"]
key =
case type
when "gem"
spec["name"]
when "git"
spec["source"]["url"]
when "path"
spec["source"]["originalPath"]
when "svn"
nil # TODO
end
sources[type][key] = val if key
end
File.open(out, "wb") do |f|
f.print sources.inspect
end
'';
# rewrite PATH sources to point into the nix store.
2015-01-20 06:07:55 +00:00
purifiedLockfile = runRuby "purifiedLockfile" {} ''
#!${ruby}/bin/ruby
out = ENV['out']
sources = eval(File.read("${sources}"))
paths = sources["path"]
2015-01-18 23:47:28 +00:00
2015-01-20 06:07:55 +00:00
lockfile = File.read("${lockfile}")
2015-01-18 23:47:28 +00:00
paths.each_pair do |impure, pure|
lockfile.gsub!(/^ remote: #{Regexp.escape(impure)}/, " remote: #{pure}")
end
2015-01-20 06:07:55 +00:00
File.open(out, "wb") do |f|
f.print lockfile
end
2015-01-18 23:47:28 +00:00
'';
in
stdenv.mkDerivation {
inherit name;
buildInputs = [
ruby
bundler
git
];
phases = [ "installPhase" "fixupPhase" ];
2015-01-18 23:47:28 +00:00
outputs = [
2015-01-20 06:07:55 +00:00
"out" # the installed libs/bins
"bundle" # supporting files for bundler
2015-01-18 23:47:28 +00:00
];
installPhase = ''
# Copy the Gemfile and Gemfile.lock
2015-01-20 06:07:55 +00:00
mkdir -p $bundle
export BUNDLE_GEMFILE=$bundle/Gemfile
2015-01-18 23:47:28 +00:00
cp ${gemfile} $BUNDLE_GEMFILE
2015-01-20 06:07:55 +00:00
cp ${purifiedLockfile} $BUNDLE_GEMFILE.lock
2015-01-18 23:47:28 +00:00
export NIX_GEM_SOURCES=${sources}
export NIX_BUNDLER_GEMPATH=${bundler}/${ruby.gemPath}
2015-01-18 23:47:28 +00:00
export GEM_HOME=$out/${ruby.gemPath}
export GEM_PATH=$GEM_HOME
mkdir -p $GEM_HOME
mkdir gems
2015-01-20 06:07:55 +00:00
${copyGems}
2015-01-20 06:07:55 +00:00
mkdir $out/bin
cp ${./monkey_patches.rb} monkey_patches.rb
export RUBYOPT="-rmonkey_patches.rb -I $(pwd -P)"
2015-01-20 06:07:55 +00:00
bundler install --frozen --binstubs
2015-01-18 23:47:28 +00:00
'';
passthru = {
inherit ruby;
2015-01-20 06:07:55 +00:00
inherit bundler;
2015-01-18 23:47:28 +00:00
};
}