Skip to content

Commit 721fdc1

Browse files
committed
Add bindir support, fixes #24
1 parent c85716b commit 721fdc1

12 files changed

+151
-69
lines changed

.travis.yml

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,19 @@
11
language: ruby
22
rvm:
3-
- jruby-18mode
4-
- jruby-19mode
3+
- jruby
54
- jruby-head
6-
- ruby-head
7-
- rbx-18mode
8-
- rbx-19mode
9-
- 1.8.7
10-
- 1.9.2
11-
- 1.9.3
12-
- 2.0.0
13-
- 2.1
14-
- 2.2
15-
- 2.3
16-
- 2.4
17-
- 2.5
5+
- rbx-3
186
before_install:
7+
- 'rvm @global do gem uninstall -a -x rubygems-bundler executable-hooks || true'
8+
- 'rm -f $(rvm @global do gem env home)/bin/jruby_executable_hooks'
199
- 'rm -rf $rvm_path/gems/*/{bin,gems}/rubygems-bundler-* $rvm_path/gems/*/{bin,gems}/executable-hooks-* $rvm_path/gems/*/bin/ruby_*_{wrapper,hooks}'
2010
- hash -r
11+
- 'if [[ -n "${WITH_RUBYGEMS:-}" ]] ; then gem update --system "${WITH_RUBYGEMS}" ; fi'
2112
- gem build executable-hooks.gemspec
2213
- gem install executable-hooks-$(awk -F'"' '/VERSION/{print $2}' < lib/executable-hooks/version.rb).gem --development
2314
before_script:
2415
- unset BUNDLE_GEMFILE
25-
script: tf --text test-tf/*
16+
script: NOEXEC=0 tf --text test-tf${TEST_SUFFIX:-}/*
2617
notifications:
2718
irc:
2819
channels:
@@ -32,10 +23,21 @@ notifications:
3223
3324
on_failure: change
3425
matrix:
35-
allow_failures:
36-
- rvm: jruby-18mode
37-
- rvm: jruby-19mode
38-
- rvm: jruby-head
39-
- rvm: rbx-18mode
40-
- rvm: rbx-19mode
26+
fast_finish: true
27+
include:
28+
- rvm: 1.8.7
29+
env: WITH_RUBYGEMS=1.6.2
30+
- rvm: 2.5
31+
env: TEST_SUFFIX=-bundle
32+
- rvm: 1.8.7
33+
- rvm: 1.9.2
34+
- rvm: 1.9.3
35+
- rvm: 2.0.0
36+
- rvm: 2.1
37+
- rvm: 2.2
38+
- rvm: 2.3
39+
- rvm: 2.4
40+
- rvm: 2.5
4141
- rvm: ruby-head
42+
allow_failures:
43+
- rvm: rbx-3

bin/ruby_executable_hooks

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ begin
1010
Gem::ExecutableHooks.run($0)
1111
rescue LoadError
1212
warn "unable to load executable-hooks/hooks" if ENV.key?('ExecutableHooks_DEBUG')
13-
end
13+
end unless $0.end_with?('/executable-hooks-uninstaller')
1414

1515
eval File.read($0), binding, $0

executable-hooks.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
1515
}
1616
s.post_install_message = <<-MESSAGE
1717
# In case of problems run the following command to update binstubs:
18-
gem regenerate_binstubs
18+
gem regenerate_binstubs
1919
MESSAGE
2020

2121

ext/wrapper_installer/extconf.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
require 'executable-hooks/wrapper'
1616
require 'executable-hooks/regenerate_binstubs_command'
1717
# call the actions
18-
ExecutableHooks::Wrapper.install_from(File.expand_path("../../..", __FILE__))
18+
options = RegenerateBinstubsCommand.default_install_options
19+
ExecutableHooks::Wrapper.new(options).install_from(File.expand_path("../../..", __FILE__))
1920
RegenerateBinstubsCommand.new.execute_no_wrapper
2021
# unload the path, what was required stays ... but there is that much we can do
2122
$:.pop

lib/executable-hooks/installer.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ module ExecutableHooksInstaller
22
# Iterate through executables and generate wrapper for each one,
33
# extract of rubygems code
44
def self.bundler_generate_bin(inst)
5-
return if inst.spec.executables.nil? or inst.spec.executables.empty?
5+
return if inst.spec.executables.nil?
6+
executables = inst.spec.executables.reject{ |name| name == 'executable-hooks-uninstaller' }
7+
return if executables.empty?
68
bindir = inst.bin_dir ? inst.bin_dir : Gem.bindir(inst.gem_home)
7-
inst.spec.executables.each do |filename|
9+
executables.each do |filename|
810
filename.untaint
911
original = File.join bindir, filename
1012
if File.exists?( original )

lib/executable-hooks/regenerate_binstubs_command.rb

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,37 @@
44
require 'executable-hooks/wrapper'
55

66
class RegenerateBinstubsCommand < Gem::Command
7+
def self.default_install_options
8+
require 'rubygems/commands/install_command'
9+
Gem::Command.extra_args = Gem.configuration[:gem]
10+
config_args = Gem.configuration[:install]
11+
config_args =
12+
case config_args
13+
when String
14+
config_args.split ' '
15+
else
16+
Array(config_args)
17+
end
18+
Gem::Command.add_specific_extra_args 'install', config_args
19+
ic = Gem::Commands::InstallCommand.new
20+
ic.handle_options ["install"]
21+
ic.options
22+
end
23+
724
def initialize
825
super 'regenerate_binstubs', 'Re run generation of executable wrappers for gems.'
26+
27+
add_option(:"Install/Update", '-i', '--install-dir DIR',
28+
'Gem repository directory to get installed',
29+
'gems') do |value, options|
30+
options[:install_dir] = File.expand_path(value)
31+
end
32+
33+
add_option(:"Install/Update", '-n', '--bindir DIR',
34+
'Directory where binary files are',
35+
'located') do |value, options|
36+
options[:bin_dir] = File.expand_path(value)
37+
end
938
end
1039

1140
def arguments # :nodoc:
@@ -33,17 +62,18 @@ def execute
3362
# https://github.com/rubygems/rubygems/issues/326
3463
puts "try also: gem pristine --binstubs"
3564
end
36-
ExecutableHooks::Wrapper.install
65+
ExecutableHooks::Wrapper.new(options).install
3766
execute_no_wrapper
3867
end
3968

40-
def execute_no_wrapper
69+
def execute_no_wrapper(wrapper_name = ExecutableHooks::Wrapper.expanded_wrapper_name)
4170
require 'executable-hooks/installer'
4271
name = get_one_optional_argument || ''
4372
specs = installed_gems.select{|spec| spec.name =~ /^#{name}/i }
4473
specs.each do |spec|
45-
unless spec.executables.empty?
46-
try_to_fix_binstubs(spec) or
74+
executables = spec.executables.reject{ |name| name == 'executable-hooks-uninstaller' }
75+
unless executables.empty?
76+
try_to_fix_binstubs(spec, executables, wrapper_name) or
4777
try_to_install_binstubs(spec) or
4878
$stderr.puts "##{spec.name} #{spec.version} not found in GEM_PATH"
4979
end
@@ -52,9 +82,9 @@ def execute_no_wrapper
5282

5383
private
5484

55-
def try_to_fix_binstubs(spec)
85+
def try_to_fix_binstubs(spec, executables, wrapper_name)
5686
executable_paths =
57-
spec.executables.map do |executable|
87+
executables.map do |executable|
5888
path = expanded_bin_paths.detect{|bin_path| File.exist?(File.join(bin_path, executable)) }
5989
File.join(path, executable) if path
6090
end
@@ -67,7 +97,7 @@ def try_to_fix_binstubs(spec)
6797
puts "#{spec.name} #{spec.version}"
6898
executable_mode = 0111
6999
executable_shebangs.map do |path, lines|
70-
lines[0] = "#!#{ExecutableHooksInstaller.env_path} #{ExecutableHooks::Wrapper.expanded_wrapper_name}"
100+
lines[0] = "#!#{ExecutableHooksInstaller.env_path} #{wrapper_name}"
71101
File.open(path, "w") do |file|
72102
file.puts(lines)
73103
end
@@ -80,24 +110,27 @@ def expanded_bin_paths
80110
@expanded_bin_paths ||= begin
81111
paths = expanded_gem_paths.map{|path| File.join(path, "bin") }
82112
paths << RbConfig::CONFIG["bindir"]
113+
# TODO: bindir from options?
83114
paths
84115
end
85116
end
86117

87118
def try_to_install_binstubs(spec)
88-
org_gem_path = expanded_gem_paths.find{|path|
89-
File.exists? File.join path, 'gems', spec.full_name
90-
} || Gem.dir
119+
org_gem_path = options[:install_dir] || existing_gem_path(spec.full_name) || Gem.dir
91120
cache_gem = File.join(org_gem_path, 'cache', spec.file_name)
92121
if File.exist? cache_gem
93122
puts "#{spec.name} #{spec.version}"
94-
inst = Gem::Installer.new Dir[cache_gem].first, :wrappers => true, :force => true, :install_dir => org_gem_path
123+
inst = Gem::Installer.new Dir[cache_gem].first, :wrappers => true, :force => true, :install_dir => org_gem_path, :bin_dir => options[:bin_dir]
95124
ExecutableHooksInstaller.bundler_generate_bin(inst)
96125
else
97126
false
98127
end
99128
end
100129

130+
def existing_gem_path(full_name)
131+
expanded_gem_paths.find{|path| File.exists? File.join path, 'gems', full_name}
132+
end
133+
101134
def expanded_gem_paths
102135
@expanded_gem_paths ||=
103136
Gem.path.map do |path|

lib/executable-hooks/specification.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module Specification
33
def self.find
44
@executable_hooks_spec ||=
55
if Gem::Specification.respond_to?(:find_by_name)
6-
Gem::Specification.find_by_name("executable-hooks")
6+
Gem::Specification.find_by_name("executable-hooks", ">=0", ">=0.alpha")
77
else
88
Gem.source_index.find_name("executable-hooks").last
99
end

lib/executable-hooks/uninstaller.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
require 'executable-hooks/wrapper'
22
require 'executable-hooks/regenerate_binstubs_command'
3+
require 'rubygems/uninstaller'
34

45
module ExecutableHooks
56
def self.uninstall
67
Gem.configuration[:custom_shebang] = "$env #{Gem.default_exec_format % "ruby"}"
7-
RegenerateBinstubsCommand.new.execute_no_wrapper
8-
Wrapper.uninstall
8+
options = RegenerateBinstubsCommand.default_install_options
9+
RegenerateBinstubsCommand.new.execute_no_wrapper("ruby")
10+
ExecutableHooks::Wrapper.new(options).uninstall
11+
options.merge!(:executables => true, :all => true, :ignore => true)
12+
Gem::Uninstaller.new("executable-hooks", options).uninstall
913
end
1014
end

lib/executable-hooks/wrapper.rb

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,23 @@
44
require 'executable-hooks/specification'
55

66
module ExecutableHooks
7-
module Wrapper
7+
class Wrapper
88
def self.wrapper_name
99
'ruby_executable_hooks'
1010
end
11+
1112
def self.expanded_wrapper_name
1213
Gem.default_exec_format % self.wrapper_name
1314
end
14-
def self.bindir
15-
Gem.respond_to?(:bindir,true) ? Gem.send(:bindir) : File.join(Gem.dir, 'bin')
16-
end
17-
def self.destination
18-
File.expand_path( expanded_wrapper_name, bindir )
19-
end
20-
def self.ensure_custom_shebang
21-
expected_shebang = "$env #{expanded_wrapper_name}"
2215

23-
Gem.configuration[:custom_shebang] ||= expected_shebang
16+
attr_reader :options
2417

25-
if Gem.configuration[:custom_shebang] != expected_shebang
26-
warn("
27-
Warning:
28-
Found custom_shebang: '#{Gem.configuration[:custom_shebang]}',
29-
Expected custom_shebang: '#{expected_shebang}',
30-
this can potentially break 'executable-hooks' and gem executables overall!
31-
Check your '~/.gemrc' and '/etc/gemrc' for 'custom_shebang' and remove it.
32-
")
33-
end
18+
def initialize(options)
19+
@options = options
3420
end
35-
def self.install
21+
22+
def install
23+
@bindir = options[:bin_dir] if options[:bin_dir]
3624
ensure_custom_shebang
3725

3826
executable_hooks_spec = ExecutableHooks::Specification.find
@@ -42,8 +30,10 @@ def self.install
4230
end
4331
end
4432

45-
def self.install_from(full_gem_path)
46-
wrapper_path = File.expand_path( "bin/#{wrapper_name}", full_gem_path )
33+
def install_from(full_gem_path)
34+
wrapper_path = File.expand_path( "bin/#{self.class.wrapper_name}", full_gem_path )
35+
bindir = calculate_bindir(options)
36+
destination = calculate_destination(bindir)
4737

4838
if File.exist?(wrapper_path) && !File.exist?(destination)
4939
FileUtils.mkdir_p(bindir) unless File.exist?(bindir)
@@ -53,8 +43,37 @@ def self.install_from(full_gem_path)
5343
File.chmod(0775, destination)
5444
end
5545
end
56-
def self.uninstall
46+
47+
def uninstall
48+
destination = calculate_destination(calculate_bindir(options))
5749
FileUtils.rm_f(destination) if File.exist?(destination)
5850
end
51+
52+
def calculate_bindir(options)
53+
return options[:bin_dir] if options[:bin_dir]
54+
Gem.respond_to?(:bindir,true) ? Gem.send(:bindir) : File.join(Gem.dir, 'bin')
55+
end
56+
57+
def calculate_destination(bindir)
58+
File.expand_path(self.class.expanded_wrapper_name, bindir)
59+
end
60+
61+
62+
def ensure_custom_shebang
63+
expected_shebang = "$env #{self.class.expanded_wrapper_name}"
64+
65+
Gem.configuration[:custom_shebang] ||= expected_shebang
66+
67+
if Gem.configuration[:custom_shebang] != expected_shebang
68+
warn("
69+
Warning:
70+
Found custom_shebang: '#{Gem.configuration[:custom_shebang]}',
71+
Expected custom_shebang: '#{expected_shebang}',
72+
this can potentially break 'executable-hooks' and gem executables overall!
73+
Check your '~/.gemrc' and '/etc/gemrc' for 'custom_shebang' and remove it.
74+
")
75+
end
76+
end
77+
5978
end
6079
end

lib/rubygems_plugin.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
require 'executable-hooks/wrapper'
1313

1414
# Set the custom_shebang if user did not set one
15-
Gem.pre_install do |inst|
16-
ExecutableHooks::Wrapper.install
15+
Gem.pre_install do |gem_installer|
16+
ExecutableHooks::Wrapper.new(gem_installer.options).install
1717
end
1818

1919
if Gem::Version.new(Gem::VERSION) < Gem::Version.new('2.0') then

test-tf-bundle/bundle_comment_test.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
gem install executable-hooks-$(awk -F'"' '/VERSION/{print $2}' < lib/executable-hooks/version.rb).gem --development
2+
# match=/installed/
3+
gem install rubygems-bundler bundler
4+
# match=/installed/
5+
gem install haml -v "4.0.7" # match=/installed/
6+
# match=/installed/
7+
8+
true TMPDIR:${TMPDIR:=/tmp}:
9+
d=$TMPDIR/test-bundled
10+
mkdir $d
11+
pushd $d
12+
13+
NOEXEC=1 haml -v # match=/4.0.7/
14+
15+
echo -e 'source "https://rubygems.org"\ngem "haml", "4.0.6"' > Gemfile
16+
bundle install # match=/haml 4.0.6/
17+
NOEXEC=1 haml -v # match=/4.0.6/
18+
19+
popd
20+
rm -rf $d

test-tf/rubygems_comment_test.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
gem install executable-hooks-$(awk -F'"' '/VERSION/{print $2}' < lib/executable-hooks/version.rb).gem --development
22
# match=/installed/
3+
wrapper_name=$(ruby -I ./lib/ -r executable-hooks/wrapper -e "puts ExecutableHooks::Wrapper.expanded_wrapper_name")
34

4-
gem install haml # match=/installed/
5-
head -n 1 $(which haml) # match=/ruby_executable_hooks/
6-
which ruby_executable_hooks # status=0
5+
gem install haml -v "<5" # match=/installed/
6+
head -n 1 $(which haml ) # match=/ruby_executable_hooks/
7+
which ${wrapper_name} # status=0
78

89
gem list # match=/haml/
910
executable-hooks-uninstaller # match=/haml/
1011

1112
head -n 1 $(which haml) # match!=/ruby_executable_hooks/
12-
which ruby_executable_hooks # status=1
13+
which ${wrapper_name} # status=1
1314

1415
gem uninstall -x haml # match=/Successfully uninstalled/

0 commit comments

Comments
 (0)