toy-executable-hooks 1.6.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.travis.yml +47 -0
- data/CHANGELOG.md +103 -0
- data/DEVELOPMENT.md +11 -0
- data/Gemfile +5 -0
- data/LICENSE +13 -0
- data/README.md +27 -0
- data/bin/executable-hooks-uninstaller +5 -0
- data/bin/ruby_executable_hooks +23 -0
- data/executable-hooks.gemspec +28 -0
- data/ext/wrapper_installer/extconf.rb +25 -0
- data/lib/executable-hooks/hooks.rb +54 -0
- data/lib/executable-hooks/installer.rb +100 -0
- data/lib/executable-hooks/regenerate_binstubs_command.rb +154 -0
- data/lib/executable-hooks/specification.rb +17 -0
- data/lib/executable-hooks/uninstaller.rb +14 -0
- data/lib/executable-hooks/version.rb +3 -0
- data/lib/executable-hooks/wrapper.rb +85 -0
- data/lib/rubygems_executable_plugin.rb +3 -0
- data/lib/rubygems_plugin.rb +29 -0
- data/test-tf/rubygems_comment_test.sh +15 -0
- data/test-tf-bundle/bundle_comment_test.sh +20 -0
- data/test-tf-truffleruby/truffleruby_comment_test.sh +16 -0
- metadata +85 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4228b8fc482489f26f465e9343a7f4cf8441c1028f8355a9b4eab920a3305bf9
|
4
|
+
data.tar.gz: f9724765c712ad7a708e2df328d684277426dc1e597e82ad5eee411f708c0a57
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bbb46a195def1f1d8fbb5498d832d00ebc1fbbfd7df426218d267c0485edbe27b70df9b64f7d52e69ae5fd7bc9534a6515c58378e625994dccc55ca6a79dfdcc
|
7
|
+
data.tar.gz: 6e089e4c1fca69a9518ab2621cd918e5f57de5d3a102f2d69aea8459c7ab7e4d1da68987ba97def73ece83ff6227d2ca95a2b06050008982064212b6dfa99256
|
data/.travis.yml
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- jruby
|
4
|
+
- jruby-head
|
5
|
+
- rbx-3
|
6
|
+
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'
|
9
|
+
- 'rm -rf $rvm_path/gems/*/{bin,gems}/rubygems-bundler-* $rvm_path/gems/*/{bin,gems}/executable-hooks-* $rvm_path/gems/*/bin/ruby_*_{wrapper,hooks}'
|
10
|
+
- hash -r
|
11
|
+
- 'if [[ -n "${WITH_RUBYGEMS:-}" ]] ; then gem update --system "${WITH_RUBYGEMS}" ; fi'
|
12
|
+
- gem build executable-hooks.gemspec
|
13
|
+
- gem install executable-hooks-$(awk -F'"' '/VERSION/{print $2}' < lib/executable-hooks/version.rb).gem --development
|
14
|
+
before_script:
|
15
|
+
- unset BUNDLE_GEMFILE
|
16
|
+
script: NOEXEC=0 tf --text test-tf${TEST_SUFFIX:-}/*
|
17
|
+
notifications:
|
18
|
+
irc:
|
19
|
+
channels:
|
20
|
+
- "irc.freenode.org#rubygems-bundler"
|
21
|
+
email:
|
22
|
+
recipients:
|
23
|
+
- mpapis@gmail.com
|
24
|
+
on_failure: change
|
25
|
+
matrix:
|
26
|
+
fast_finish: true
|
27
|
+
include:
|
28
|
+
- rvm: 1.8.7
|
29
|
+
env: WITH_RUBYGEMS=1.4.2
|
30
|
+
- rvm: 1.8.7
|
31
|
+
env: WITH_RUBYGEMS=1.6.2
|
32
|
+
- rvm: 2.5
|
33
|
+
env: TEST_SUFFIX=-bundle
|
34
|
+
- rvm: 2.5
|
35
|
+
env: TEST_SUFFIX=-truffleruby
|
36
|
+
- rvm: 1.8.7
|
37
|
+
- rvm: 1.9.2
|
38
|
+
- rvm: 1.9.3
|
39
|
+
- rvm: 2.0.0
|
40
|
+
- rvm: 2.1
|
41
|
+
- rvm: 2.2
|
42
|
+
- rvm: 2.3
|
43
|
+
- rvm: 2.4
|
44
|
+
- rvm: 2.5
|
45
|
+
- rvm: ruby-head
|
46
|
+
allow_failures:
|
47
|
+
- rvm: rbx-3
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 1.6.2
|
4
|
+
date: 2021-01-26
|
5
|
+
|
6
|
+
- Converts end_with? to match for Ruby 1.8.6 compatibility #37
|
7
|
+
|
8
|
+
## 1.6.1
|
9
|
+
date: 2021-01-26
|
10
|
+
|
11
|
+
- Avoid Ruby 2.7 warning, merge #38
|
12
|
+
|
13
|
+
## 1.6.0
|
14
|
+
date: 2018-10-25
|
15
|
+
|
16
|
+
- Restore support for ruby-1.8.6, fixes #34
|
17
|
+
- Do not force overwrite wrapper, fixes #33
|
18
|
+
|
19
|
+
## 1.5.0
|
20
|
+
date: 2018-06-25
|
21
|
+
|
22
|
+
- Support truffleruby, fixes rvm/rvm#4408
|
23
|
+
|
24
|
+
## 1.4.2
|
25
|
+
date: 2018-02-14
|
26
|
+
|
27
|
+
- Support rubygems 1.4.2, fixes #29
|
28
|
+
|
29
|
+
## 1.4.1
|
30
|
+
date: 2018-02-12
|
31
|
+
|
32
|
+
- Fix bundle install, fixes #28
|
33
|
+
|
34
|
+
## 1.4.0
|
35
|
+
date: 2018-02-08
|
36
|
+
|
37
|
+
- Add bindir support, fixes #24
|
38
|
+
|
39
|
+
## 1.3.2
|
40
|
+
date: 2014-06-06
|
41
|
+
|
42
|
+
- make sure executable mode is set on binaries when using fast fix, update wayneeseguin/rvm#2894
|
43
|
+
|
44
|
+
## 1.3.1
|
45
|
+
date: 2014-01-16
|
46
|
+
|
47
|
+
- do not hardcode env ruby_executable_hooks when using shortcut try_to_fix_binstubs, fix #12
|
48
|
+
|
49
|
+
## 1.3.0
|
50
|
+
date: 2014-01-11
|
51
|
+
|
52
|
+
- First try to fix binstubs before installing them, fix wayneeseguin/rvm#2536
|
53
|
+
|
54
|
+
## 1.2.6
|
55
|
+
date: 2013-10-21
|
56
|
+
|
57
|
+
- Remind users about regenerating binstubs "in case of problems", merge #11
|
58
|
+
|
59
|
+
## 1.2.5
|
60
|
+
date: 2013-10-12
|
61
|
+
|
62
|
+
- first try to create the bin dir then check if it is writable, update #9, update wayneeseguin/rvm#2277
|
63
|
+
|
64
|
+
## 1.2.4
|
65
|
+
date: 2013-10-10
|
66
|
+
|
67
|
+
- raise exception if can not write to bindir, fix #9
|
68
|
+
|
69
|
+
## 1.2.3
|
70
|
+
date: 2013-09-24
|
71
|
+
|
72
|
+
- fix detecting program name and system process title, fix #8, update #7, update #5
|
73
|
+
|
74
|
+
## 1.2.2
|
75
|
+
date: 2013-09-23
|
76
|
+
|
77
|
+
- change process title only when supported by Process, fix #7, update #5
|
78
|
+
|
79
|
+
## 1.2.1
|
80
|
+
date: 2013-09-22
|
81
|
+
|
82
|
+
- fix installing wrapper when first time installing the gem, fix #6
|
83
|
+
|
84
|
+
## 1.2.0
|
85
|
+
date: 2013-09-17
|
86
|
+
|
87
|
+
- fix full program name with params, fix #5
|
88
|
+
- RG 2.1 introduces find_latest_files
|
89
|
+
- add license to gemspec, fix #4
|
90
|
+
|
91
|
+
## 1.1.0
|
92
|
+
date: 2013-07-11
|
93
|
+
|
94
|
+
- fix hooks for older rubygems versions
|
95
|
+
- add regenerating wrappers on gem installation, closes #2
|
96
|
+
- fix uninstaller
|
97
|
+
- honor the program suffix, fix #3
|
98
|
+
- add a warning for custom custom_shebang, fix #1
|
99
|
+
|
100
|
+
## 1.0.0
|
101
|
+
date: 2013-07-10
|
102
|
+
|
103
|
+
- extracted hooking to rubygems executables from https://github.com/mpapis/rubygems-bundler
|
data/DEVELOPMENT.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Releasing
|
2
|
+
|
3
|
+
- update `lib/executable-hooks/version.rb` with new version (use semantic versioning)
|
4
|
+
- update `CHANGELOG.md` with changes relevant to running hooks
|
5
|
+
- git commit changes with version as comment
|
6
|
+
- git tag version
|
7
|
+
- `git push`
|
8
|
+
- `git push --tags`
|
9
|
+
- use ruby 1.8.7 for releasing `rvm use 1.8.7 --install`
|
10
|
+
- `gem build executable-hooks.gemspec`
|
11
|
+
- `gem push executable-hooks-1.6.1.gem` - update version
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2013-2014 Michal Papis
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Rubygems executable hooks
|
2
|
+
|
3
|
+
Add next rubygems plugin support for executables.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
Install the gem:
|
8
|
+
|
9
|
+
gem install executable-hooks
|
10
|
+
|
11
|
+
In gem `lib` dir create `rubygems_executable_plugin.rb`:
|
12
|
+
|
13
|
+
Gem.execute do |original_file|
|
14
|
+
warn("Executing: #{original_file}")
|
15
|
+
end
|
16
|
+
|
17
|
+
Generate and install the new gem with executable hook.
|
18
|
+
|
19
|
+
Now try it:
|
20
|
+
|
21
|
+
gem install haml
|
22
|
+
haml --version
|
23
|
+
|
24
|
+
Returns:
|
25
|
+
|
26
|
+
Executing: /home/mpapis/.rvm/gems/ruby-1.8.7-p374-new1/bin/haml
|
27
|
+
Haml 4.0.3
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
title = "ruby #{ARGV*" "}"
|
4
|
+
$0 = ARGV.shift
|
5
|
+
Process.setproctitle(title) if Process.methods.include?(:setproctitle)
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
begin
|
9
|
+
require 'executable-hooks/hooks'
|
10
|
+
Gem::ExecutableHooks.run($0)
|
11
|
+
rescue LoadError
|
12
|
+
warn "unable to load executable-hooks/hooks" if ENV.key?('ExecutableHooks_DEBUG')
|
13
|
+
end unless $0.match(/\/executable-hooks-uninstaller$/)
|
14
|
+
|
15
|
+
content = File.read($0)
|
16
|
+
|
17
|
+
if (index = content.index("\n#!ruby\n")) && index > 0
|
18
|
+
skipped_content = content.slice!(0..index)
|
19
|
+
start_line = skipped_content.count("\n") + 1
|
20
|
+
eval content, binding, $0, start_line
|
21
|
+
else
|
22
|
+
eval content, binding, $0
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
|
4
|
+
Kernel.load(File.expand_path("../lib/executable-hooks/version.rb", __FILE__))
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "toy-executable-hooks"
|
8
|
+
s.version = ExecutableHooks::VERSION
|
9
|
+
s.license = 'Apache 2.0'
|
10
|
+
s.authors = ["Michal Papis"]
|
11
|
+
s.email = ["mpapis@gmail.com"]
|
12
|
+
s.homepage = "https://github.com/rvm/executable-hooks"
|
13
|
+
s.summary = %q{
|
14
|
+
Hook into rubygems executables allowing extra actions to be taken before executable is run.
|
15
|
+
}
|
16
|
+
s.post_install_message = <<-MESSAGE
|
17
|
+
# In case of problems run the following command to update binstubs:
|
18
|
+
gem regenerate_binstubs
|
19
|
+
MESSAGE
|
20
|
+
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
s.extensions = %w( ext/wrapper_installer/extconf.rb )
|
25
|
+
s.executables = %w( executable-hooks-uninstaller )
|
26
|
+
|
27
|
+
s.add_development_dependency "tf", "~>0.4"
|
28
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Fake building extension
|
2
|
+
File.open('Makefile', 'w') { |f| f.write("all:\n\ninstall:\n\n") }
|
3
|
+
File.open('make', 'w') do |f|
|
4
|
+
f.write('#!/bin/sh')
|
5
|
+
f.chmod(f.stat.mode | 0111)
|
6
|
+
end
|
7
|
+
File.open('wrapper_installer.so', 'w') {}
|
8
|
+
File.open('wrapper_installer.dll', 'w') {}
|
9
|
+
File.open('nmake.bat', 'w') { |f| }
|
10
|
+
|
11
|
+
|
12
|
+
# add the gem to load path
|
13
|
+
$: << File.expand_path("../../../lib", __FILE__)
|
14
|
+
# load the actions
|
15
|
+
require 'executable-hooks/wrapper'
|
16
|
+
require 'executable-hooks/regenerate_binstubs_command'
|
17
|
+
# call the actions
|
18
|
+
options = RegenerateBinstubsCommand.default_install_options
|
19
|
+
ExecutableHooks::Wrapper.new(options).install_from(File.expand_path("../../..", __FILE__))
|
20
|
+
RegenerateBinstubsCommand.new.execute_no_wrapper
|
21
|
+
# unload the path, what was required stays ... but there is that much we can do
|
22
|
+
$:.pop
|
23
|
+
|
24
|
+
# just in case - it worked
|
25
|
+
true
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Gem
|
2
|
+
@executables_hooks ||= []
|
3
|
+
|
4
|
+
class << self
|
5
|
+
unless method_defined?(:execute)
|
6
|
+
def execute(&hook)
|
7
|
+
@executables_hooks << hook
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :executables_hooks
|
11
|
+
end
|
12
|
+
|
13
|
+
unless method_defined?(:load_executable_plugins)
|
14
|
+
def load_executable_plugins
|
15
|
+
if ENV['RUBYGEMS_LOAD_ALL_PLUGINS']
|
16
|
+
load_plugin_files find_files('rubygems_executable_plugin', false)
|
17
|
+
else
|
18
|
+
begin
|
19
|
+
load_plugin_files find_latest_files('rubygems_executable_plugin', false)
|
20
|
+
rescue NoMethodError
|
21
|
+
load_plugin_files find_files('rubygems_executable_plugin', false)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
rescue ArgumentError, NoMethodError
|
25
|
+
# old rubygems
|
26
|
+
plugins = find_files('rubygems_executable_plugin')
|
27
|
+
|
28
|
+
plugins.each do |plugin|
|
29
|
+
|
30
|
+
# Skip older versions of the GemCutter plugin: Its commands are in
|
31
|
+
# RubyGems proper now.
|
32
|
+
|
33
|
+
next if plugin =~ /gemcutter-0\.[0-3]/
|
34
|
+
|
35
|
+
begin
|
36
|
+
load plugin
|
37
|
+
rescue ::Exception => e
|
38
|
+
details = "#{plugin.inspect}: #{e.message} (#{e.class})"
|
39
|
+
warn "Error loading RubyGems plugin #{details}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class ExecutableHooks
|
47
|
+
def self.run(original_file)
|
48
|
+
Gem.load_executable_plugins
|
49
|
+
Gem.executables_hooks.each do |hook|
|
50
|
+
hook.call(original_file)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module ExecutableHooksInstaller
|
2
|
+
# Iterate through executables and generate wrapper for each one,
|
3
|
+
# extract of rubygems code
|
4
|
+
def self.bundler_generate_bin(inst)
|
5
|
+
return if inst.spec.executables.nil?
|
6
|
+
executables = inst.spec.executables.reject{ |name| name == 'executable-hooks-uninstaller' }
|
7
|
+
return if executables.empty?
|
8
|
+
bindir = inst.bin_dir ? inst.bin_dir : Gem.bindir(inst.gem_home)
|
9
|
+
executables.each do |filename|
|
10
|
+
filename.untaint
|
11
|
+
original = File.join bindir, filename
|
12
|
+
if File.exists?( original )
|
13
|
+
bin_script_path = File.join bindir, inst.formatted_program_filename(filename)
|
14
|
+
FileUtils.rm_f bin_script_path
|
15
|
+
File.open bin_script_path, 'wb', 0755 do |file|
|
16
|
+
file.print bundler_app_script_text(inst, filename)
|
17
|
+
end
|
18
|
+
inst.say bin_script_path if Gem.configuration.really_verbose
|
19
|
+
else
|
20
|
+
inst.say "Can not find #{inst.spec.name} in GEM_PATH"
|
21
|
+
break
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def self.shebang(inst, bin_file_name)
|
28
|
+
# options were defined first in 1.5, we want to support back to 1.3.7
|
29
|
+
ruby_name = Gem::ConfigMap[:ruby_install_name] if inst.instance_variable_get(:@env_shebang)
|
30
|
+
bindir = inst.bin_dir ? inst.bin_dir : Gem.bindir(inst.gem_home)
|
31
|
+
path = File.join bindir, inst.formatted_program_filename(bin_file_name)
|
32
|
+
first_line = File.open(path, "rb") {|file| file.gets}
|
33
|
+
|
34
|
+
if /\A#!/ =~ first_line then
|
35
|
+
# Preserve extra words on shebang line, like "-w". Thanks RPA.
|
36
|
+
shebang = first_line.sub(/\A\#!.*?ruby\S*((\s+\S+)+)/, "#!#{Gem.ruby}")
|
37
|
+
opts = $1
|
38
|
+
shebang.strip! # Avoid nasty ^M issues.
|
39
|
+
end
|
40
|
+
|
41
|
+
if which = Gem.configuration[:custom_shebang]
|
42
|
+
which = which.gsub(/\$(\w+)/) do
|
43
|
+
case $1
|
44
|
+
when "env"
|
45
|
+
env_path
|
46
|
+
when "ruby"
|
47
|
+
"#{Gem.ruby}#{opts}"
|
48
|
+
when "exec"
|
49
|
+
bin_file_name
|
50
|
+
when "name"
|
51
|
+
inst.spec.name
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
return "#!#{which}"
|
56
|
+
end
|
57
|
+
|
58
|
+
if not ruby_name then
|
59
|
+
"#!#{Gem.ruby}#{opts}"
|
60
|
+
elsif opts then
|
61
|
+
"#!/bin/sh\n'exec' #{ruby_name.dump} '-x' \"$0\" \"$@\"\n#{shebang}"
|
62
|
+
else
|
63
|
+
"#!#{env_path} #{ruby_name}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.env_path
|
68
|
+
@env_path ||= Gem::Installer::ENV_PATHS.find {|path| File.executable?(path) }
|
69
|
+
end
|
70
|
+
|
71
|
+
# Return the text for an application file.
|
72
|
+
def self.bundler_app_script_text(inst, bin_file_name)
|
73
|
+
<<-TEXT
|
74
|
+
#{shebang(inst, bin_file_name)}
|
75
|
+
#
|
76
|
+
# This file was generated by RubyGems.
|
77
|
+
#
|
78
|
+
# The application '#{inst.spec.name}' is installed as part of a gem, and
|
79
|
+
# this file is here to facilitate running it.
|
80
|
+
#
|
81
|
+
|
82
|
+
require 'rubygems'
|
83
|
+
|
84
|
+
version = "#{Gem::Requirement.default}"
|
85
|
+
|
86
|
+
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
|
87
|
+
version = $1
|
88
|
+
ARGV.shift
|
89
|
+
end
|
90
|
+
|
91
|
+
gem '#{inst.spec.name}', version
|
92
|
+
load Gem.bin_path('#{inst.spec.name}', '#{bin_file_name}', version)
|
93
|
+
TEXT
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
Gem.post_install do |inst|
|
99
|
+
ExecutableHooksInstaller.bundler_generate_bin(inst)
|
100
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'rubygems/command_manager'
|
2
|
+
require 'rubygems/installer'
|
3
|
+
require 'rubygems/version'
|
4
|
+
require 'executable-hooks/wrapper'
|
5
|
+
|
6
|
+
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
|
+
|
24
|
+
def initialize
|
25
|
+
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
|
38
|
+
end
|
39
|
+
|
40
|
+
def arguments # :nodoc:
|
41
|
+
"STRING start of gem name to regenerate binstubs"
|
42
|
+
end
|
43
|
+
|
44
|
+
def usage # :nodoc:
|
45
|
+
"#{program_name} [STRING]"
|
46
|
+
end
|
47
|
+
|
48
|
+
def defaults_str # :nodoc:
|
49
|
+
""
|
50
|
+
end
|
51
|
+
|
52
|
+
def description # :nodoc:
|
53
|
+
'Re run generation of executable wrappers for all gems. '+
|
54
|
+
'Wrappers will be compatible with both rubygems and bundler. '+
|
55
|
+
'The switcher is BUNDLE_GEMFILE environment variable, '+
|
56
|
+
'when set it switches to bundler mode, when not set, '+
|
57
|
+
'then the command will work as it was with pure rubygems.'
|
58
|
+
end
|
59
|
+
|
60
|
+
def execute
|
61
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('2.0.0') then
|
62
|
+
# https://github.com/rubygems/rubygems/issues/326
|
63
|
+
puts "try also: gem pristine --binstubs"
|
64
|
+
end
|
65
|
+
ExecutableHooks::Wrapper.new(options).install
|
66
|
+
execute_no_wrapper
|
67
|
+
end
|
68
|
+
|
69
|
+
def execute_no_wrapper(wrapper_name = ExecutableHooks::Wrapper.expanded_wrapper_name)
|
70
|
+
require 'executable-hooks/installer'
|
71
|
+
name = get_one_optional_argument || ''
|
72
|
+
specs = installed_gems.select{|spec| spec.name =~ /^#{name}/i }
|
73
|
+
specs.each do |spec|
|
74
|
+
executables = spec.executables.reject{ |name| name == 'executable-hooks-uninstaller' }
|
75
|
+
unless executables.empty?
|
76
|
+
try_to_fix_binstubs(spec, executables, wrapper_name) or
|
77
|
+
try_to_install_binstubs(spec) or
|
78
|
+
$stderr.puts "##{spec.name} #{spec.version} not found in GEM_PATH"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def try_to_fix_binstubs(spec, executables, wrapper_name)
|
86
|
+
executable_paths =
|
87
|
+
executables.map do |executable|
|
88
|
+
path = expanded_bin_paths.detect{|bin_path| File.exist?(File.join(bin_path, executable)) }
|
89
|
+
File.join(path, executable) if path
|
90
|
+
end
|
91
|
+
return false if executable_paths.include?(nil) # not found
|
92
|
+
executable_shebangs =
|
93
|
+
executable_paths.map do |path|
|
94
|
+
[path, File.readlines(path).map{|l|l.chomp}]
|
95
|
+
end
|
96
|
+
return false if executable_shebangs.detect{|path, lines| !(lines[0] =~ /^#!\//) }
|
97
|
+
puts "#{spec.name} #{spec.version}"
|
98
|
+
executable_mode = 0111
|
99
|
+
executable_shebangs.map do |path, lines|
|
100
|
+
lines[0] = "#!#{ExecutableHooksInstaller.env_path} #{wrapper_name}"
|
101
|
+
File.open(path, "w") do |file|
|
102
|
+
file.puts(lines)
|
103
|
+
end
|
104
|
+
mode = File.stat(path).mode
|
105
|
+
File.chmod(mode | executable_mode, path) if mode & executable_mode != executable_mode
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def expanded_bin_paths
|
110
|
+
@expanded_bin_paths ||= begin
|
111
|
+
paths = expanded_gem_paths.map{|path| File.join(path, "bin") }
|
112
|
+
paths << RbConfig::CONFIG["bindir"]
|
113
|
+
# TODO: bindir from options?
|
114
|
+
paths
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def try_to_install_binstubs(spec)
|
119
|
+
org_gem_path = options[:install_dir] || existing_gem_path(spec.full_name) || Gem.dir
|
120
|
+
cache_gem = File.join(org_gem_path, 'cache', spec.file_name)
|
121
|
+
if File.exist? cache_gem
|
122
|
+
puts "#{spec.name} #{spec.version}"
|
123
|
+
installer_method = Gem::Installer.respond_to?(:at) ? :at : :new
|
124
|
+
inst = Gem::Installer.public_send installer_method, Dir[cache_gem].first, :wrappers => true, :force => true, :install_dir => org_gem_path, :bin_dir => options[:bin_dir]
|
125
|
+
ExecutableHooksInstaller.bundler_generate_bin(inst)
|
126
|
+
else
|
127
|
+
false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def existing_gem_path(full_name)
|
132
|
+
expanded_gem_paths.find{|path| File.exists?(File.join(path, 'gems', full_name))}
|
133
|
+
end
|
134
|
+
|
135
|
+
def expanded_gem_paths
|
136
|
+
@expanded_gem_paths ||=
|
137
|
+
Gem.path.map do |path|
|
138
|
+
paths = [path]
|
139
|
+
while File.symlink?(path)
|
140
|
+
path = File.readlink(path)
|
141
|
+
paths << path
|
142
|
+
end
|
143
|
+
paths
|
144
|
+
end.flatten
|
145
|
+
end
|
146
|
+
|
147
|
+
def installed_gems
|
148
|
+
if Gem::VERSION > '1.8' then
|
149
|
+
Gem::Specification.to_a
|
150
|
+
else
|
151
|
+
Gem.source_index.map{|name,spec| spec}
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ExecutableHooks
|
2
|
+
module Specification
|
3
|
+
def self.find
|
4
|
+
@executable_hooks_spec ||=
|
5
|
+
if Gem::Specification.respond_to?(:find_by_name)
|
6
|
+
Gem::Specification.find_by_name("executable-hooks", ">=0", ">=0.alpha")
|
7
|
+
else
|
8
|
+
Gem.source_index.find_name("executable-hooks").last
|
9
|
+
end
|
10
|
+
rescue Gem::LoadError
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
def self.version
|
14
|
+
find ? find.version.to_s : nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'executable-hooks/wrapper'
|
2
|
+
require 'executable-hooks/regenerate_binstubs_command'
|
3
|
+
require 'rubygems/uninstaller'
|
4
|
+
|
5
|
+
module ExecutableHooks
|
6
|
+
def self.uninstall
|
7
|
+
Gem.configuration[:custom_shebang] = "$env #{Gem.default_exec_format % "ruby"}"
|
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
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# install / uninstall wrapper
|
2
|
+
require 'fileutils'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'executable-hooks/specification'
|
5
|
+
|
6
|
+
module ExecutableHooks
|
7
|
+
class Wrapper
|
8
|
+
def self.wrapper_name
|
9
|
+
'ruby_executable_hooks'
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.expanded_wrapper_name
|
13
|
+
Gem.default_exec_format % self.wrapper_name
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :options
|
17
|
+
|
18
|
+
def initialize(options)
|
19
|
+
@options = options || RegenerateBinstubsCommand.default_install_options
|
20
|
+
end
|
21
|
+
|
22
|
+
def install
|
23
|
+
@bindir = options[:bin_dir] if options[:bin_dir]
|
24
|
+
ensure_custom_shebang
|
25
|
+
|
26
|
+
executable_hooks_spec = ExecutableHooks::Specification.find
|
27
|
+
|
28
|
+
if executable_hooks_spec
|
29
|
+
install_from( executable_hooks_spec.full_gem_path )
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
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)
|
37
|
+
|
38
|
+
if File.exist?(wrapper_path) && !same_file(wrapper_path, destination)
|
39
|
+
FileUtils.mkdir_p(bindir) unless File.exist?(bindir)
|
40
|
+
# exception based on Gem::Installer.generate_bin
|
41
|
+
raise Gem::FilePermissionError.new(bindir) unless File.writable?(bindir)
|
42
|
+
FileUtils.cp(wrapper_path, destination)
|
43
|
+
File.chmod(0775, destination)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def same_file(file1, file2)
|
48
|
+
File.exist?(file1) && File.exist?(file2) &&
|
49
|
+
File.read(file1) == File.read(file2)
|
50
|
+
end
|
51
|
+
private :same_file
|
52
|
+
|
53
|
+
def uninstall
|
54
|
+
destination = calculate_destination(calculate_bindir(options))
|
55
|
+
FileUtils.rm_f(destination) if File.exist?(destination)
|
56
|
+
end
|
57
|
+
|
58
|
+
def calculate_bindir(options)
|
59
|
+
return options[:bin_dir] if options[:bin_dir]
|
60
|
+
Gem.respond_to?(:bindir,true) ? Gem.send(:bindir) : File.join(Gem.dir, 'bin')
|
61
|
+
end
|
62
|
+
|
63
|
+
def calculate_destination(bindir)
|
64
|
+
File.expand_path(self.class.expanded_wrapper_name, bindir)
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def ensure_custom_shebang
|
69
|
+
expected_shebang = "$env #{self.class.expanded_wrapper_name}"
|
70
|
+
|
71
|
+
Gem.configuration[:custom_shebang] ||= expected_shebang
|
72
|
+
|
73
|
+
if Gem.configuration[:custom_shebang] != expected_shebang
|
74
|
+
warn("
|
75
|
+
Warning:
|
76
|
+
Found custom_shebang: '#{Gem.configuration[:custom_shebang]}',
|
77
|
+
Expected custom_shebang: '#{expected_shebang}',
|
78
|
+
this can potentially break 'executable-hooks' and gem executables overall!
|
79
|
+
Check your '~/.gemrc' and '/etc/gemrc' for 'custom_shebang' and remove it.
|
80
|
+
")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Simulate require_relative - it's required as the plugin can be called in wrong version or from bundler.
|
2
|
+
require File.expand_path('../executable-hooks/specification.rb', __FILE__)
|
3
|
+
|
4
|
+
called_path, called_version = __FILE__.match(/^(.*\/executable-hooks-([^\/]+)\/lib).*$/)[1..2]
|
5
|
+
|
6
|
+
# continue only if loaded and called versions all the same, and not shared gems disabled in bundler
|
7
|
+
if
|
8
|
+
( $:.include?(called_path) || ExecutableHooks::Specification.version == called_version ) and
|
9
|
+
( !defined?(Bundler) || ( defined?(Bundler) && Bundler::SharedHelpers.in_bundle? && !Bundler.settings[:disable_shared_gems]) )
|
10
|
+
|
11
|
+
require 'rubygems/version'
|
12
|
+
require 'executable-hooks/wrapper'
|
13
|
+
|
14
|
+
# Set the custom_shebang if user did not set one
|
15
|
+
Gem.pre_install do |gem_installer|
|
16
|
+
options = if gem_installer.methods.map{|m|m.to_s}.include?('options')
|
17
|
+
gem_installer.options
|
18
|
+
end
|
19
|
+
ExecutableHooks::Wrapper.new(options).install
|
20
|
+
end
|
21
|
+
|
22
|
+
if Gem::Version.new(Gem::VERSION) < Gem::Version.new('2.0') then
|
23
|
+
# Add custom_shebang support to rubygems
|
24
|
+
require 'executable-hooks/installer'
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'executable-hooks/regenerate_binstubs_command'
|
28
|
+
Gem::CommandManager.instance.register_command :regenerate_binstubs
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
gem install executable-hooks-$(awk -F'"' '/VERSION/{print $2}' < lib/executable-hooks/version.rb).gem --development
|
2
|
+
# match=/installed/
|
3
|
+
wrapper_name=$(ruby -I ./lib/ -r executable-hooks/wrapper -e "puts ExecutableHooks::Wrapper.expanded_wrapper_name")
|
4
|
+
|
5
|
+
gem install haml -v "<5" # match=/installed/
|
6
|
+
head -n 1 $(which haml ) # match=/ruby_executable_hooks/
|
7
|
+
which ${wrapper_name} # status=0
|
8
|
+
|
9
|
+
gem list # match=/haml/
|
10
|
+
executable-hooks-uninstaller # match=/haml/
|
11
|
+
|
12
|
+
head -n 1 $(which haml) # match!=/ruby_executable_hooks/
|
13
|
+
which ${wrapper_name} # status=1
|
14
|
+
|
15
|
+
gem uninstall -x haml # match=/Successfully uninstalled/
|
@@ -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
|
@@ -0,0 +1,16 @@
|
|
1
|
+
gem install executable-hooks-$(awk -F'"' '/VERSION/{print $2}' < lib/executable-hooks/version.rb).gem --development
|
2
|
+
# match=/installed/
|
3
|
+
|
4
|
+
gem install haml -v "4.0.7" # match=/installed/
|
5
|
+
haml_bin=$(which haml )
|
6
|
+
head -n 1 $haml_bin # match=/ruby_executable_hooks/
|
7
|
+
|
8
|
+
## simulate truffleruby style binary with shell code mixed in
|
9
|
+
## \043 - is a # ... somehow it breaks tf
|
10
|
+
( head -n 1 $haml_bin; echo -e 'echo $HOME\n\043!ruby'; tail -n +2 $haml_bin ) > $haml_bin.new
|
11
|
+
mv $haml_bin.new $haml_bin
|
12
|
+
chmod +x $haml_bin
|
13
|
+
|
14
|
+
haml _4.0.7_ -v # match=/4.0.7/
|
15
|
+
|
16
|
+
gem uninstall -x haml -v 4.0.7 # match=/Successfully uninstalled/
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: toy-executable-hooks
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.6.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michal Papis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-01-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: tf
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.4'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.4'
|
27
|
+
description:
|
28
|
+
email:
|
29
|
+
- mpapis@gmail.com
|
30
|
+
executables:
|
31
|
+
- executable-hooks-uninstaller
|
32
|
+
extensions:
|
33
|
+
- ext/wrapper_installer/extconf.rb
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- ".gitignore"
|
37
|
+
- ".travis.yml"
|
38
|
+
- CHANGELOG.md
|
39
|
+
- DEVELOPMENT.md
|
40
|
+
- Gemfile
|
41
|
+
- LICENSE
|
42
|
+
- README.md
|
43
|
+
- bin/executable-hooks-uninstaller
|
44
|
+
- bin/ruby_executable_hooks
|
45
|
+
- executable-hooks.gemspec
|
46
|
+
- ext/wrapper_installer/extconf.rb
|
47
|
+
- lib/executable-hooks/hooks.rb
|
48
|
+
- lib/executable-hooks/installer.rb
|
49
|
+
- lib/executable-hooks/regenerate_binstubs_command.rb
|
50
|
+
- lib/executable-hooks/specification.rb
|
51
|
+
- lib/executable-hooks/uninstaller.rb
|
52
|
+
- lib/executable-hooks/version.rb
|
53
|
+
- lib/executable-hooks/wrapper.rb
|
54
|
+
- lib/rubygems_executable_plugin.rb
|
55
|
+
- lib/rubygems_plugin.rb
|
56
|
+
- test-tf-bundle/bundle_comment_test.sh
|
57
|
+
- test-tf-truffleruby/truffleruby_comment_test.sh
|
58
|
+
- test-tf/rubygems_comment_test.sh
|
59
|
+
homepage: https://github.com/rvm/executable-hooks
|
60
|
+
licenses:
|
61
|
+
- Apache 2.0
|
62
|
+
metadata: {}
|
63
|
+
post_install_message: |
|
64
|
+
# In case of problems run the following command to update binstubs:
|
65
|
+
gem regenerate_binstubs
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubygems_version: 3.3.26
|
81
|
+
signing_key:
|
82
|
+
specification_version: 4
|
83
|
+
summary: Hook into rubygems executables allowing extra actions to be taken before
|
84
|
+
executable is run.
|
85
|
+
test_files: []
|