From 7b289bcee662929b46a9b27f966d93dd91c59efb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sun, 19 Oct 2014 13:43:29 +0200 Subject: [PATCH] Avoid running `rbenv rehash` multiple times during `bundle install` This is an attempt to work around the fact that Rubygems post_install hooks may happen multiple times per single `bundle install` and ideally we want `rbenv rehash` to run only once if new gems have been installed. However, due to Bundler parallelism using `fork` on platforms that support it, it's impossible for the child processes to communicate with the master process to signal it to run `rbenv rehash` in the end. This hooks into Bundler `install` command and runs `rbenv rehash` after all gems have finished installing, but only if the install location was system gems location and not a custom path (such as per-project `vendor/bundle`). This is limited because we can't tell whether any gems have been installed at all, let alone do those gems have executables. However it's better than having multiple `rbenv rehash` being run in parallel and outputting confusing error messages as a result. --- rbenv.d/exec/gem-rehash/rubygems_plugin.rb | 31 +++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/rbenv.d/exec/gem-rehash/rubygems_plugin.rb b/rbenv.d/exec/gem-rehash/rubygems_plugin.rb index 21d5ad9a..8d1df091 100644 --- a/rbenv.d/exec/gem-rehash/rubygems_plugin.rb +++ b/rbenv.d/exec/gem-rehash/rubygems_plugin.rb @@ -6,13 +6,32 @@ hook = lambda do |installer| `rbenv rehash` end rescue - warn "rbenv: error in gem-rehash (#{$!})" + warn "rbenv: error in gem-rehash (#{$!.class.name}: #{$!.message})" end end -begin - Gem.post_install(&hook) - Gem.post_uninstall(&hook) -rescue - warn "rbenv: error installing gem-rehash hooks (#{$!})" +if defined?(Bundler::Installer) && Bundler::Installer.respond_to?(:install) + Bundler::Installer.class_eval do + class << self + alias install_without_rbenv_rehash install + def install(root, definition, options = {}) + result = install_without_rbenv_rehash(root, definition, options) + begin + if result && Gem.default_path.include?(Bundler.bundle_path.to_s) + `rbenv rehash` + end + rescue + warn "rbenv: error in Bundler post-install hook (#{$!.class.name}: #{$!.message})" + end + result + end + end + end +else + begin + Gem.post_install(&hook) + Gem.post_uninstall(&hook) + rescue + warn "rbenv: error installing gem-rehash hooks (#{$!.class.name}: #{$!.message})" + end end