Skip to content

Commit b84dffa

Browse files
Merge pull request #7660 from rubygems/deivid-rodriguez/fix-setup-with-destdir
Fix binstubs sometimes not getting regenerated when `--destdir` is given (cherry picked from commit 4814e41)
1 parent 0b268d4 commit b84dffa

File tree

7 files changed

+68
-32
lines changed

7 files changed

+68
-32
lines changed

lib/rubygems/commands/pristine_command.rb

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def initialize
5757
end
5858

5959
add_option("-i", "--install-dir DIR",
60-
"Gem repository to get binstubs and plugins installed") do |value, options|
60+
"Gem repository to get gems restored") do |value, options|
6161
options[:install_dir] = File.expand_path(value)
6262
end
6363

@@ -103,21 +103,25 @@ def usage # :nodoc:
103103
end
104104

105105
def execute
106+
install_dir = options[:install_dir]
107+
108+
specification_record = install_dir ? Gem::SpecificationRecord.from_path(install_dir) : Gem::Specification.specification_record
109+
106110
specs = if options[:all]
107-
Gem::Specification.map
111+
specification_record.map
108112

109113
# `--extensions` must be explicitly given to pristine only gems
110114
# with extensions.
111115
elsif options[:extensions_set] &&
112116
options[:extensions] && options[:args].empty?
113-
Gem::Specification.select do |spec|
117+
specification_record.select do |spec|
114118
spec.extensions && !spec.extensions.empty?
115119
end
116120
elsif options[:only_missing_extensions]
117-
Gem::Specification.select(&:missing_extensions?)
121+
specification_record.select(&:missing_extensions?)
118122
else
119123
get_all_gem_names.sort.map do |gem_name|
120-
Gem::Specification.find_all_by_name(gem_name, options[:version]).reverse
124+
specification_record.find_all_by_name(gem_name, options[:version]).reverse
121125
end.flatten
122126
end
123127

@@ -176,7 +180,6 @@ def execute
176180
end
177181

178182
bin_dir = options[:bin_dir] if options[:bin_dir]
179-
install_dir = options[:install_dir] if options[:install_dir]
180183

181184
installer_options = {
182185
wrappers: true,

lib/rubygems/commands/setup_command.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,8 @@ def regenerate_binstubs(bindir)
585585

586586
args = %w[--all --only-executables --silent]
587587
args << "--bindir=#{bindir}"
588+
args << "--install-dir=#{default_dir}"
589+
588590
if options[:env_shebang]
589591
args << "--env-shebang"
590592
end

lib/rubygems/dependency.rb

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -271,15 +271,7 @@ def merge(other)
271271
end
272272

273273
def matching_specs(platform_only = false)
274-
env_req = Gem.env_requirement(name)
275-
matches = Gem::Specification.stubs_for(name).find_all do |spec|
276-
requirement.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
277-
end.map(&:to_spec)
278-
279-
if prioritizes_bundler?
280-
require_relative "bundler_version_finder"
281-
Gem::BundlerVersionFinder.prioritize!(matches)
282-
end
274+
matches = Gem::Specification.find_all_by_name(name, requirement)
283275

284276
if platform_only
285277
matches.reject! do |spec|
@@ -297,10 +289,6 @@ def specific?
297289
@requirement.specific?
298290
end
299291

300-
def prioritizes_bundler?
301-
name == "bundler" && !specific?
302-
end
303-
304292
def to_specs
305293
matches = matching_specs true
306294

lib/rubygems/installer.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ def install
344344

345345
say spec.post_install_message if options[:post_install_message] && !spec.post_install_message.nil?
346346

347-
Gem::Specification.add_spec(spec)
347+
Gem::Specification.add_spec(spec) unless @install_dir
348348

349349
load_plugin
350350

lib/rubygems/specification.rb

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -925,21 +925,15 @@ def self.dirs=(dirs)
925925
# Enumerate every known spec. See ::dirs= and ::add_spec to set the list of
926926
# specs.
927927

928-
def self.each
929-
return enum_for(:each) unless block_given?
930-
931-
_all.each do |x|
932-
yield x
933-
end
928+
def self.each(&block)
929+
specification_record.each(&block)
934930
end
935931

936932
##
937933
# Returns every spec that matches +name+ and optional +requirements+.
938934

939935
def self.find_all_by_name(name, *requirements)
940-
requirements = Gem::Requirement.default if requirements.empty?
941-
942-
Gem::Dependency.new(name, *requirements).matching_specs
936+
specification_record.find_all_by_name(name, *requirements)
943937
end
944938

945939
##

lib/rubygems/specification_record.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,38 @@ def all_names
111111
all.map(&:full_name)
112112
end
113113

114+
include Enumerable
115+
116+
##
117+
# Enumerate every known spec.
118+
119+
def each
120+
return enum_for(:each) unless block_given?
121+
122+
all.each do |x|
123+
yield x
124+
end
125+
end
126+
127+
##
128+
# Returns every spec in the record that matches +name+ and optional +requirements+.
129+
130+
def find_all_by_name(name, *requirements)
131+
req = Gem::Requirement.create(*requirements)
132+
env_req = Gem.env_requirement(name)
133+
134+
matches = stubs_for(name).find_all do |spec|
135+
req.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
136+
end.map(&:to_spec)
137+
138+
if name == "bundler" && !req.specific?
139+
require_relative "bundler_version_finder"
140+
Gem::BundlerVersionFinder.prioritize!(matches)
141+
end
142+
143+
matches
144+
end
145+
114146
##
115147
# Return the best specification in the record that contains the file matching +path+.
116148

test/rubygems/test_gem_commands_setup_command.rb

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,23 @@ def test_destdir_flag_does_not_try_to_write_to_the_default_gem_home
160160
end
161161
end
162162

163+
def test_destdir_flag_regenerates_binstubs
164+
# install to destdir
165+
destdir = File.join(@tempdir, "foo")
166+
gem_bin_path = gem_install "destdir-only-gem", install_dir: destdir
167+
168+
# change binstub manually
169+
write_file gem_bin_path do |io|
170+
io.puts "I changed it!"
171+
end
172+
173+
@cmd.options[:destdir] = destdir
174+
@cmd.options[:prefix] = "/"
175+
@cmd.execute
176+
177+
assert_match(/\A#!/, File.read(gem_bin_path))
178+
end
179+
163180
def test_files_in
164181
assert_equal %w[rubygems.rb rubygems/requirement.rb rubygems/ssl_certs/rubygems.org/foo.pem],
165182
@cmd.files_in("lib").sort
@@ -414,16 +431,16 @@ def create_dummy_files(list)
414431
end
415432
end
416433

417-
def gem_install(name)
434+
def gem_install(name, **options)
418435
gem = util_spec name do |s|
419436
s.executables = [name]
420437
s.files = %W[bin/#{name}]
421438
end
422439
write_file File.join @tempdir, "bin", name do |f|
423440
f.puts "#!/usr/bin/ruby"
424441
end
425-
install_gem gem
426-
File.join @gemhome, "bin", name
442+
install_gem gem, **options
443+
File.join options[:install_dir] || @gemhome, "bin", name
427444
end
428445

429446
def gem_install_with_plugin(name)

0 commit comments

Comments
 (0)