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 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/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .idea
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
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
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ #ruby=1.8.7
4
+
5
+ gemspec
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,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'executable-hooks/uninstaller'
4
+
5
+ ExecutableHooks.uninstall
@@ -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,3 @@
1
+ module ExecutableHooks
2
+ VERSION = "1.6.2.1"
3
+ 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,3 @@
1
+ Gem.execute do |original_file|
2
+ warn("Executing: #{original_file}") if ENV.key?('ExecutableHooks_DEBUG')
3
+ 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: []