summary refs log tree commit diff
path: root/pkgs/development/interpreters/ruby/build-ruby-gem/nix-bundle-install.rb
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/development/interpreters/ruby/build-ruby-gem/nix-bundle-install.rb')
-rw-r--r--pkgs/development/interpreters/ruby/build-ruby-gem/nix-bundle-install.rb153
1 files changed, 153 insertions, 0 deletions
diff --git a/pkgs/development/interpreters/ruby/build-ruby-gem/nix-bundle-install.rb b/pkgs/development/interpreters/ruby/build-ruby-gem/nix-bundle-install.rb
new file mode 100644
index 00000000000..647b83b52c3
--- /dev/null
+++ b/pkgs/development/interpreters/ruby/build-ruby-gem/nix-bundle-install.rb
@@ -0,0 +1,153 @@
+require 'rbconfig'
+require 'bundler/vendored_thor'
+require 'bundler'
+require 'rubygems/command'
+require 'fileutils'
+require 'pathname'
+require 'tmpdir'
+
+# Options:
+#
+#   name        - the gem name
+#   uri         - git repo uri
+#   repo        - path to local checkout
+#   ref         - the commit hash
+#   version     - gem version
+#   build-flags - build arguments
+
+ruby = File.join(ENV["ruby"], "bin", RbConfig::CONFIG['ruby_install_name'])
+out = ENV["out"]
+bin_dir = File.join(ENV["out"], "bin")
+
+name        = ARGV[0]
+uri         = ARGV[1]
+REPO        = ARGV[2]
+ref         = ARGV[3]
+version     = ARGV[4]
+build_flags = ARGV[5]
+
+# options to pass to bundler
+options = {
+  "name"    => name,
+  "uri"     => uri,
+  "ref"     => ref,
+  "version" => version,
+}
+
+# Monkey-patch Bundler to use our local checkout.
+# I wish we didn't have to do this, but bundler does not expose an API to do
+# these kinds of things.
+Bundler.module_eval do
+  def self.requires_sudo?
+    false
+  end
+
+  def self.root
+    # we don't have a Gemfile, so it doesn't make sense to try to make paths
+    # relative to the (non existent) parent directory thereof, so we give a
+    # nonsense path here.
+    Pathname.new("/no-root-path")
+  end
+
+  def self.bundle_path
+    Pathname.new(ENV["GEM_HOME"])
+  end
+
+  def self.locked_gems
+    nil
+  end
+end
+
+Bundler::Source::Git.class_eval do
+  def allow_git_ops?
+    true
+  end
+end
+
+Bundler::Source::Git::GitProxy.class_eval do
+  def checkout
+    unless path.exist?
+      FileUtils.mkdir_p(path.dirname)
+      FileUtils.cp_r(File.join(REPO, ".git"), path)
+      system("chmod -R +w #{path}")
+    end
+  end
+
+  def copy_to(destination, submodules=false)
+    unless File.exist?(destination.join(".git"))
+      FileUtils.mkdir_p(destination.dirname)
+      FileUtils.cp_r(REPO, destination)
+      system("chmod -R +w #{destination}")
+    end
+  end
+end
+
+# UI
+verbose = false
+no_color = false
+Bundler.ui = Bundler::UI::Shell.new({"no-color" => no_color})
+Bundler.ui.level = "debug" if verbose
+
+# Install
+source = Bundler::Source::Git.new(options)
+spec = source.specs.search_all(name).first
+Bundler.rubygems.with_build_args [build_flags] do
+  source.install(spec)
+end
+
+msg = spec.post_install_message
+if msg
+  Bundler.ui.confirm "Post-install message from #{name}:"
+  Bundler.ui.info msg
+end
+
+# Write out the binstubs
+if spec.executables.any?
+  FileUtils.mkdir_p(bin_dir)
+  spec.executables.each do |exe|
+    wrapper = File.join(bin_dir, exe)
+    File.open(wrapper, "w") do |f|
+      stub = generate_stub(spec.name, exe)
+      f.write(<<-EOF)
+#!#{ruby}
+#
+# This file was generated by Nix.
+#
+# The application '#{exe}' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'rubygems'
+require 'bundler/setup'
+
+load Gem.bin_path(#{spec.name.inspect}, #{exe.inspect})
+EOF
+    end
+
+    FileUtils.chmod("+x", wrapper)
+  end
+end
+
+# Write out metadata
+meta = "#{out}/nix-support/gem-meta"
+FileUtils.mkdir_p(meta)
+FileUtils.ln_s(spec.loaded_from.to_s, "#{meta}/spec")
+File.open("#{meta}/name", "w") do |f|
+  f.write spec.name
+end
+File.open("#{meta}/install-path", "w") do |f|
+  f.write source.install_path.to_s
+end
+File.open("#{meta}/require-paths", "w") do |f|
+  f.write spec.require_paths.join(" ")
+end
+File.open("#{meta}/executables", "w") do |f|
+  f.write spec.executables.join(" ")
+end
+
+# make the lib available during bundler/git installs
+File.open("#{out}/nix-support/setup-hook", "a") do |f|
+  spec.require_paths.each do |dir|
+    f.puts("addToSearchPath RUBYLIB #{source.install_path}/#{dir}")
+  end
+end