Merge RubyGems 3.4.6 and Bundler 2.4.6 (#7214)

Merge RubyGems-3.4.6 and Bundler-2.4.6
This commit is contained in:
Hiroshi SHIBATA 2023-02-01 12:05:19 +09:00 committed by GitHub
parent 40e0b1e123
commit f4e6e78410
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 965 additions and 734 deletions

View file

@ -40,7 +40,11 @@ module Bundler
end
if options[:standalone]
next Bundler.ui.warn("Sorry, Bundler can only be run via RubyGems.") if gem_name == "bundler"
if gem_name == "bundler"
Bundler.ui.warn("Sorry, Bundler can only be run via RubyGems.") unless options[:all]
next
end
Bundler.settings.temporary(:path => (Bundler.settings[:path] || Bundler.root)) do
installer.generate_standalone_bundler_executable_stubs(spec, installer_opts)
end

View file

@ -31,6 +31,7 @@
#
def gemfile(install = false, options = {}, &gemfile)
require_relative "../bundler"
Bundler.reset!
opts = options.dup
ui = opts.delete(:ui) { Bundler::UI::Shell.new }
@ -38,9 +39,8 @@ def gemfile(install = false, options = {}, &gemfile)
Bundler.ui = ui
raise ArgumentError, "Unknown options: #{opts.keys.join(", ")}" unless opts.empty?
begin
Bundler.with_unbundled_env do
Bundler.instance_variable_set(:@bundle_path, Pathname.new(Gem.dir))
old_gemfile = ENV["BUNDLE_GEMFILE"]
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", "Gemfile"
Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
@ -65,11 +65,9 @@ def gemfile(install = false, options = {}, &gemfile)
runtime = Bundler::Runtime.new(nil, definition)
runtime.setup.require
end
ensure
if old_gemfile
ENV["BUNDLE_GEMFILE"] = old_gemfile
else
end
if ENV["BUNDLE_GEMFILE"].nil?
ENV["BUNDLE_GEMFILE"] = ""
end
end
end

View file

@ -84,6 +84,9 @@ module Bundler
def reverse_rubygems_kernel_mixin
<<~END
if Gem.respond_to?(:discover_gems_on_require=)
Gem.discover_gems_on_require = false
else
kernel = (class << ::Kernel; self; end)
[kernel, ::Kernel].each do |k|
if k.private_method_defined?(:gem_original_require)
@ -93,6 +96,7 @@ module Bundler
k.send(:private, :require) if private_require
end
end
end
END
end
end

View file

@ -227,6 +227,9 @@ module Bundler
def reverse_rubygems_kernel_mixin
# Disable rubygems' gem activation system
if Gem.respond_to?(:discover_gems_on_require=)
Gem.discover_gems_on_require = false
else
kernel = (class << ::Kernel; self; end)
[kernel, ::Kernel].each do |k|
if k.private_method_defined?(:gem_original_require)
@ -234,6 +237,7 @@ module Bundler
end
end
end
end
def replace_gem(specs, specs_by_name)
reverse_rubygems_kernel_mixin

View file

@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
VERSION = "2.4.5".freeze
VERSION = "2.4.6".freeze
def self.bundler_major_version
@bundler_major_version ||= VERSION.split(".").first.to_i

View file

@ -8,7 +8,7 @@
require "rbconfig"
module Gem
VERSION = "3.4.5".freeze
VERSION = "3.4.6".freeze
end
# Must be first since it unloads the prelude from 1.9.2
@ -181,6 +181,8 @@ module Gem
@default_source_date_epoch = nil
@discover_gems_on_require = true
##
# Try to activate a gem containing +path+. Returns true if
# activation succeeded or wasn't needed because it was already
@ -1163,8 +1165,16 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# RubyGems distributors (like operating system package managers) can
# disable RubyGems update by setting this to error message printed to
# end-users on gem update --system instead of actual update.
attr_accessor :disable_system_update_message
##
# Whether RubyGems should enhance builtin `require` to automatically
# check whether the path required is present in installed gems, and
# automatically activate them and add them to `$LOAD_PATH`.
attr_accessor :discover_gems_on_require
##
# Hash of loaded Gem::Specification keyed by name

View file

@ -34,6 +34,9 @@ module Kernel
# that file has already been loaded is preserved.
def require(path) # :doc:
return gem_original_require(path) unless Gem.discover_gems_on_require
begin
if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
monitor_owned = RUBYGEMS_ACTIVATION_MONITOR.mon_owned?
end
@ -168,6 +171,7 @@ module Kernel
end
end
end
end
private :require

View file

@ -131,8 +131,7 @@ class Gem::Ext::Builder
when /CMakeLists.txt/ then
Gem::Ext::CmakeBuilder
when /Cargo.toml/ then
# We use the spec name here to ensure we invoke the correct init function later
Gem::Ext::CargoBuilder.new(@spec)
Gem::Ext::CargoBuilder.new
else
build_error("No builder for extension '#{extension}'")
end

View file

@ -6,30 +6,60 @@
class Gem::Ext::CargoBuilder < Gem::Ext::Builder
attr_accessor :spec, :runner, :profile
def initialize(spec)
def initialize
require_relative "../command"
require_relative "cargo_builder/link_flag_converter"
@spec = spec
@runner = self.class.method(:run)
@profile = :release
end
def build(_extension, dest_path, results, args = [], lib_dir = nil, cargo_dir = Dir.pwd)
def build(extension, dest_path, results, args = [], lib_dir = nil, cargo_dir = Dir.pwd)
require "tempfile"
require "fileutils"
require "shellwords"
build_crate(dest_path, results, args, cargo_dir)
validate_cargo_build!(dest_path)
rename_cdylib_for_ruby_compatibility(dest_path)
finalize_directory(dest_path, lib_dir, cargo_dir)
results
# Where's the Cargo.toml of the crate we're building
cargo_toml = File.join(cargo_dir, "Cargo.toml")
# What's the crate's name
crate_name = cargo_crate_name(cargo_dir, cargo_toml, results)
begin
# Create a tmp dir to do the build in
tmp_dest = Dir.mktmpdir(".gem.", cargo_dir)
# Run the build
cmd = cargo_command(cargo_toml, tmp_dest, args, crate_name)
runner.call(cmd, results, "cargo", cargo_dir, build_env)
# Where do we expect Cargo to write the compiled library
dylib_path = cargo_dylib_path(tmp_dest, crate_name)
# Helpful error if we didn't find the compiled library
raise DylibNotFoundError, tmp_dest unless File.exist?(dylib_path)
# Cargo and Ruby differ on how the library should be named, rename from
# what Cargo outputs to what Ruby expects
dlext_name = "#{crate_name}.#{makefile_config("DLEXT")}"
dlext_path = File.join(File.dirname(dylib_path), dlext_name)
FileUtils.cp(dylib_path, dlext_path)
nesting = extension_nesting(extension)
# TODO: remove in RubyGems 4
if Gem.install_extension_in_lib && lib_dir
nested_lib_dir = File.join(lib_dir, nesting)
FileUtils.mkdir_p nested_lib_dir
FileUtils.cp_r dlext_path, nested_lib_dir, remove_destination: true
end
def build_crate(dest_path, results, args, cargo_dir)
env = build_env
cmd = cargo_command(cargo_dir, dest_path, args)
runner.call cmd, results, "cargo", cargo_dir, env
# move to final destination
nested_dest_path = File.join(dest_path, nesting)
FileUtils.mkdir_p nested_dest_path
FileUtils.cp_r dlext_path, nested_dest_path, remove_destination: true
ensure
# clean up intermediary build artifacts
FileUtils.rm_rf tmp_dest if tmp_dest
end
results
end
@ -42,39 +72,59 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
build_env
end
def cargo_command(cargo_dir, dest_path, args = [])
manifest = File.join(cargo_dir, "Cargo.toml")
cargo = ENV.fetch("CARGO", "cargo")
def cargo_command(cargo_toml, dest_path, args = [], crate_name = nil)
require "shellwords"
cmd = []
cmd += [cargo, "rustc"]
cmd += ["--crate-type", "cdylib"]
cmd += ["--target", ENV["CARGO_BUILD_TARGET"]] if ENV["CARGO_BUILD_TARGET"]
cmd += ["--target-dir", dest_path]
cmd += ["--manifest-path", manifest]
cmd += ["--manifest-path", cargo_toml]
cmd += ["--lib"]
cmd += ["--profile", profile.to_s]
cmd += ["--locked"]
cmd += Gem::Command.build_args
cmd += args
cmd += ["--"]
cmd += [*cargo_rustc_args(dest_path)]
cmd += [*cargo_rustc_args(dest_path, crate_name)]
cmd
end
private
def cargo
ENV.fetch("CARGO", "cargo")
end
# returns the directory nesting of the extension, ignoring the first part, so
# "ext/foo/bar/Cargo.toml" becomes "foo/bar"
def extension_nesting(extension)
parts = extension.to_s.split(Regexp.union([File::SEPARATOR, File::ALT_SEPARATOR].compact))
parts = parts.each_with_object([]) do |segment, final|
next if segment == "."
if segment == ".."
raise Gem::InstallError, "extension outside of gem root" if final.empty?
next final.pop
end
final << segment
end
File.join(parts[1...-1])
end
def rb_config_env
result = {}
RbConfig::CONFIG.each {|k, v| result["RBCONFIG_#{k}"] = v }
result
end
def cargo_rustc_args(dest_dir)
def cargo_rustc_args(dest_dir, crate_name)
[
*linker_args,
*mkmf_libpath,
*rustc_dynamic_linker_flags(dest_dir),
*rustc_dynamic_linker_flags(dest_dir, crate_name),
*rustc_lib_flags(dest_dir),
*platform_specific_rustc_args(dest_dir),
]
@ -134,42 +184,70 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
makefile_config("ENABLE_SHARED") == "no"
end
# Ruby expects the dylib to follow a file name convention for loading
def rename_cdylib_for_ruby_compatibility(dest_path)
new_path = final_extension_path(dest_path)
FileUtils.cp(cargo_dylib_path(dest_path), new_path)
new_path
end
def validate_cargo_build!(dir)
dylib_path = cargo_dylib_path(dir)
raise DylibNotFoundError, dir unless File.exist?(dylib_path)
dylib_path
end
def final_extension_path(dest_path)
dylib_path = cargo_dylib_path(dest_path)
dlext_name = "#{spec.name}.#{makefile_config("DLEXT")}"
dylib_path.gsub(File.basename(dylib_path), dlext_name)
end
def cargo_dylib_path(dest_path)
def cargo_dylib_path(dest_path, crate_name)
prefix = so_ext == "dll" ? "" : "lib"
path_parts = [dest_path]
path_parts << ENV["CARGO_BUILD_TARGET"] if ENV["CARGO_BUILD_TARGET"]
path_parts += ["release", "#{prefix}#{cargo_crate_name}.#{so_ext}"]
path_parts += ["release", "#{prefix}#{crate_name}.#{so_ext}"]
File.join(*path_parts)
end
def cargo_crate_name
spec.metadata.fetch("cargo_crate_name", spec.name).tr("-", "_")
def cargo_crate_name(cargo_dir, manifest_path, results)
require "open3"
Gem.load_yaml
output, status =
begin
Open3.capture2e(cargo, "metadata", "--no-deps", "--format-version", "1", :chdir => cargo_dir)
rescue => error
raise Gem::InstallError, "cargo metadata failed #{error.message}"
end
def rustc_dynamic_linker_flags(dest_dir)
unless status.success?
if Gem.configuration.really_verbose
puts output
else
results << output
end
exit_reason =
if status.exited?
", exit code #{status.exitstatus}"
elsif status.signaled?
", uncaught signal #{status.termsig}"
end
raise Gem::InstallError, "cargo metadata failed#{exit_reason}"
end
# cargo metadata output is specified as json, but with the
# --format-version 1 option the output is compatible with YAML, so we can
# avoid the json dependency
metadata = Gem::SafeYAML.safe_load(output)
package = metadata["packages"].find {|pkg| normalize_path(pkg["manifest_path"]) == manifest_path }
unless package
found = metadata["packages"].map {|md| "#{md["name"]} at #{md["manifest_path"]}" }
raise Gem::InstallError, <<-EOF
failed to determine cargo package name
looking for: #{manifest_path}
found:
#{found.join("\n")}
EOF
end
package["name"].tr("-", "_")
end
def normalize_path(path)
return path unless File::ALT_SEPARATOR
path.tr(File::ALT_SEPARATOR, File::SEPARATOR)
end
def rustc_dynamic_linker_flags(dest_dir, crate_name)
split_flags("DLDFLAGS")
.map {|arg| maybe_resolve_ldflag_variable(arg, dest_dir) }
.map {|arg| maybe_resolve_ldflag_variable(arg, dest_dir, crate_name) }
.compact
.flat_map {|arg| ldflag_to_link_modifier(arg) }
end
@ -204,7 +282,7 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
end
# Interpolate substitution vars in the arg (i.e. $(DEFFILE))
def maybe_resolve_ldflag_variable(input_arg, dest_dir)
def maybe_resolve_ldflag_variable(input_arg, dest_dir, crate_name)
var_matches = input_arg.match(/\$\((\w+)\)/)
return input_arg unless var_matches
@ -217,19 +295,19 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
# On windows, it is assumed that mkmf has setup an exports file for the
# extension, so we have to to create one ourselves.
when "DEFFILE"
write_deffile(dest_dir)
write_deffile(dest_dir, crate_name)
else
RbConfig::CONFIG[var_name]
end
end
def write_deffile(dest_dir)
deffile_path = File.join(dest_dir, "#{spec.name}-#{RbConfig::CONFIG["arch"]}.def")
def write_deffile(dest_dir, crate_name)
deffile_path = File.join(dest_dir, "#{crate_name}-#{RbConfig::CONFIG["arch"]}.def")
export_prefix = makefile_config("EXPORT_PREFIX") || ""
File.open(deffile_path, "w") do |f|
f.puts "EXPORTS"
f.puts "#{export_prefix.strip}Init_#{spec.name}"
f.puts "#{export_prefix.strip}Init_#{crate_name}"
end
deffile_path
@ -264,44 +342,6 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
RbConfig.expand(val.dup)
end
# Copied from ExtConfBuilder
def finalize_directory(dest_path, lib_dir, extension_dir)
require "fileutils"
require "tempfile"
ext_path = final_extension_path(dest_path)
begin
tmp_dest = Dir.mktmpdir(".gem.", extension_dir)
# Some versions of `mktmpdir` return absolute paths, which will break make
# if the paths contain spaces.
#
# As such, we convert to a relative path.
tmp_dest_relative = get_relative_path(tmp_dest.clone, extension_dir)
full_tmp_dest = File.join(extension_dir, tmp_dest_relative)
# TODO: remove in RubyGems 4
if Gem.install_extension_in_lib && lib_dir
FileUtils.mkdir_p lib_dir
FileUtils.cp_r ext_path, lib_dir, remove_destination: true
end
FileUtils::Entry_.new(full_tmp_dest).traverse do |ent|
destent = ent.class.new(dest_path, ent.rel)
destent.exist? || FileUtils.mv(ent.path, destent.path)
end
ensure
FileUtils.rm_rf tmp_dest if tmp_dest
end
end
def get_relative_path(path, base)
path[0..base.length - 1] = "." if path.start_with?(base)
path
end
# Error raised when no cdylib artifact was created
class DylibNotFoundError < StandardError
def initialize(dir)

View file

@ -466,7 +466,7 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
def validate_rust_extensions(builder) # :nodoc:
rust_extension = @specification.extensions.any? {|s| builder.builder_for(s).is_a? Gem::Ext::CargoBuilder }
missing_cargo_lock = !@specification.files.include?("Cargo.lock")
missing_cargo_lock = !@specification.files.any? {|f| f.end_with?("Cargo.lock") }
error <<-ERROR if rust_extension && missing_cargo_lock
You have specified rust based extension, but Cargo.lock is not part of the gem files. Please run `cargo generate-lockfile` or any other command to generate Cargo.lock and ensure it is added to your gem files section in gemspec.

View file

@ -369,6 +369,7 @@ RSpec.describe "bundle binstubs <gem>" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
gem "rails"
G
end
@ -396,6 +397,26 @@ RSpec.describe "bundle binstubs <gem>" do
expect(bundled_app("bin/rackup.cmd")).to exist
end
end
context "when the gem is bundler" do
it "warns without generating a standalone binstub" do
bundle "binstubs bundler --standalone"
expect(bundled_app("bin/bundle")).not_to exist
expect(bundled_app("bin/bundler")).not_to exist
expect(err).to include("Sorry, Bundler can only be run via RubyGems.")
end
end
context "when specified --all option" do
it "generates standalone binstubs for all gems except bundler" do
bundle "binstubs --standalone --all"
expect(bundled_app("bin/rackup")).to exist
expect(bundled_app("bin/rails")).to exist
expect(bundled_app("bin/bundle")).not_to exist
expect(bundled_app("bin/bundler")).not_to exist
expect(err).not_to include("Sorry, Bundler can only be run via RubyGems.")
end
end
end
context "when the bin already exists" do

View file

@ -2,11 +2,10 @@
RSpec.describe "bundle exec" do
let(:system_gems_to_install) { %w[rack-1.0.0 rack-0.9.1] }
before :each do
system_gems(system_gems_to_install, :path => default_bundle_path)
end
it "works with --gemfile flag" do
system_gems(system_gems_to_install, :path => default_bundle_path)
create_file "CustomGemfile", <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
@ -17,6 +16,8 @@ RSpec.describe "bundle exec" do
end
it "activates the correct gem" do
system_gems(system_gems_to_install, :path => default_bundle_path)
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "0.9.1"
@ -27,6 +28,8 @@ RSpec.describe "bundle exec" do
end
it "works and prints no warnings when HOME is not writable" do
system_gems(system_gems_to_install, :path => default_bundle_path)
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "0.9.1"
@ -209,8 +212,6 @@ RSpec.describe "bundle exec" do
end
context "with default gems" do
let(:system_gems_to_install) { [] }
let(:default_irb_version) { ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", :raise_on_error => false }
context "when not specified in Gemfile" do
@ -402,6 +403,8 @@ RSpec.describe "bundle exec" do
end
it "raises a helpful error when exec'ing to something outside of the bundle" do
system_gems(system_gems_to_install, :path => default_bundle_path)
bundle "config set clean false" # want to keep the rackup binstub
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@ -706,6 +709,8 @@ RSpec.describe "bundle exec" do
RUBY
before do
system_gems(system_gems_to_install, :path => default_bundle_path)
bundled_app(path).open("w") {|f| f << executable }
bundled_app(path).chmod(0o755)

View file

@ -821,6 +821,64 @@ RSpec.describe "bundle install with specific platforms" do
bundle :install
end
it "automatically fixes the lockfile if the specific platform is locked and we move to a newer ruby version for which a native package is not available" do
#
# Given an existing application using native gems (e.g., nokogiri)
# And a lockfile generated with a stable ruby version
# When want test the application against ruby-head and `bundle install`
# Then bundler should fall back to the generic ruby platform gem
#
simulate_platform "x86_64-linux" do
build_repo4 do
build_gem "nokogiri", "1.14.0"
build_gem "nokogiri", "1.14.0" do |s|
s.platform = "x86_64-linux"
s.required_ruby_version = "< #{Gem.ruby_version}"
end
end
gemfile <<~G
source "#{file_uri_for(gem_repo4)}"
gem "nokogiri", "1.14.0"
G
lockfile <<~L
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
nokogiri (1.14.0-x86_64-linux)
PLATFORMS
x86_64-linux
DEPENDENCIES
nokogiri (= 1.14.0)
BUNDLED WITH
#{Bundler::VERSION}
L
bundle :install
expect(lockfile).to eq(<<~L)
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
nokogiri (1.14.0)
PLATFORMS
x86_64-linux
DEPENDENCIES
nokogiri (= 1.14.0)
BUNDLED WITH
#{Bundler::VERSION}
L
end
end
private
def setup_multiplatform_gem

View file

@ -230,6 +230,113 @@ RSpec.describe "bundler/inline#gemfile" do
expect(err).to be_empty
end
it "doesn't reinstall already installed gems" do
system_gems "rack-1.0.0"
script <<-RUBY
require '#{entrypoint}'
ui = Bundler::UI::Shell.new
ui.level = "confirm"
gemfile(true, ui: ui) do
source "#{file_uri_for(gem_repo1)}"
gem "activesupport"
gem "rack"
end
RUBY
expect(out).to include("Installing activesupport")
expect(out).not_to include("Installing rack")
expect(err).to be_empty
end
it "installs gems in later gemfile calls" do
system_gems "rack-1.0.0"
script <<-RUBY
require '#{entrypoint}'
ui = Bundler::UI::Shell.new
ui.level = "confirm"
gemfile(true, ui: ui) do
source "#{file_uri_for(gem_repo1)}"
gem "rack"
end
gemfile(true, ui: ui) do
source "#{file_uri_for(gem_repo1)}"
gem "activesupport"
end
RUBY
expect(out).to include("Installing activesupport")
expect(out).not_to include("Installing rack")
expect(err).to be_empty
end
it "doesn't reinstall already installed gems in later gemfile calls" do
system_gems "rack-1.0.0"
script <<-RUBY
require '#{entrypoint}'
ui = Bundler::UI::Shell.new
ui.level = "confirm"
gemfile(true, ui: ui) do
source "#{file_uri_for(gem_repo1)}"
gem "activesupport"
end
gemfile(true, ui: ui) do
source "#{file_uri_for(gem_repo1)}"
gem "rack"
end
RUBY
expect(out).to include("Installing activesupport")
expect(out).not_to include("Installing rack")
expect(err).to be_empty
end
it "installs gems with native extensions in later gemfile calls" do
system_gems "rack-1.0.0"
build_git "foo" do |s|
s.add_dependency "rake"
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
File.open("\#{path}/foo.rb", "w") do |f|
f.puts "FOO = 'YES'"
end
end
RUBY
end
script <<-RUBY
require '#{entrypoint}'
ui = Bundler::UI::Shell.new
ui.level = "confirm"
gemfile(true, ui: ui) do
source "#{file_uri_for(gem_repo1)}"
gem "rack"
end
gemfile(true, ui: ui) do
source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
end
require 'foo'
puts FOO
puts $:.grep(/ext/)
RUBY
expect(out).to include("YES")
expect(out).to include(Pathname.glob(default_bundle_path("bundler/gems/extensions/**/foo-1.0-*")).first.to_s)
expect(err).to be_empty
end
it "installs inline gems when a Gemfile.lock is present" do
gemfile <<-G
source "https://notaserver.com"

View file

@ -1519,4 +1519,29 @@ end
expect(err).to be_empty
end
end
it "does not undo the Kernel.require decorations", :rubygems => ">= 3.4.6" do
install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
script = bundled_app("bin/script")
create_file(script, <<~RUBY)
module Kernel
module_function
alias_method :require_before_extra_monkeypatches, :require
def require(path)
puts "requiring \#{path} used the monkeypatch"
require_before_extra_monkeypatches(path)
end
end
require "bundler/setup"
require "foo"
RUBY
sys_exec "#{Gem.ruby} #{script}", :raise_on_error => false
expect(out).to include("requiring foo used the monkeypatch")
end
end

View file

@ -0,0 +1,419 @@
require_relative "helper"
class TestBundlerGem < Gem::TestCase
PROJECT_DIR = File.expand_path("../..", __dir__).tap(&Gem::UNTAINT)
def test_self_use_gemdeps
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("-") do
FileUtils.mkdir_p "detect/a/b"
FileUtils.mkdir_p "detect/a/Isolate"
FileUtils.touch "detect/Isolate"
begin
Dir.chdir "detect/a/b"
Gem.use_gemdeps
assert_equal add_bundler_full_name([]), loaded_spec_names
ensure
Dir.chdir @tempdir
end
end
end
end
def test_self_find_files_with_gemfile
with_local_bundler_at(Gem.dir) do
cwd = File.expand_path("test/rubygems", PROJECT_DIR)
actual_load_path = $LOAD_PATH.unshift(cwd).dup
discover_path = File.join "lib", "sff", "discover.rb"
foo1, _ = %w[1 2].map do |version|
spec = quick_gem "sff", version do |s|
s.files << discover_path
end
write_file(File.join "gems", spec.full_name, discover_path) do |fp|
fp.puts "# #{spec.full_name}"
end
spec
end
Gem.refresh
write_file(File.join Dir.pwd, "Gemfile") do |fp|
fp.puts "source 'https://rubygems.org'"
fp.puts "gem '#{foo1.name}', '#{foo1.version}'"
end
Gem.use_gemdeps(File.join Dir.pwd, "Gemfile")
expected = [
File.expand_path("test/rubygems/sff/discover.rb", PROJECT_DIR),
File.join(foo1.full_gem_path, discover_path),
].sort
assert_equal expected, Gem.find_files("sff/discover").sort
assert_equal expected, Gem.find_files("sff/**.rb").sort, "[ruby-core:31730]"
assert_equal cwd, actual_load_path.shift
end
end
def test_auto_activation_of_specific_gemdeps_file
with_local_bundler_at(Gem.dir) do
a = util_spec "a", "1", nil, "lib/a.rb"
b = util_spec "b", "1", nil, "lib/b.rb"
c = util_spec "c", "1", nil, "lib/c.rb"
install_specs a, b, c
path = File.join @tempdir, "gem.deps.rb"
File.open path, "w" do |f|
f.puts "gem 'a'"
f.puts "gem 'b'"
f.puts "gem 'c'"
end
with_rubygems_gemdeps(path) do
Gem.use_gemdeps
assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names
end
end
end
def test_auto_activation_of_used_gemdeps_file
with_local_bundler_at(Gem.dir) do
a = util_spec "a", "1", nil, "lib/a.rb"
b = util_spec "b", "1", nil, "lib/b.rb"
c = util_spec "c", "1", nil, "lib/c.rb"
install_specs a, b, c
path = File.join @tempdir, "gem.deps.rb"
File.open path, "w" do |f|
f.puts "gem 'a'"
f.puts "gem 'b'"
f.puts "gem 'c'"
end
with_rubygems_gemdeps("-") do
expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name)
Gem.use_gemdeps
assert_equal expected_specs, loaded_spec_names
end
end
end
def test_looks_for_gemdeps_files_automatically_from_binstubs
path = File.join(@tempdir, "gd-tmp")
with_local_bundler_at(path) do
a = util_spec "a", "1" do |s|
s.executables = %w[foo]
s.bindir = "exe"
end
write_file File.join(@tempdir, "exe", "foo") do |fp|
fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort"
end
b = util_spec "b", "1", nil, "lib/b.rb"
c = util_spec "c", "1", nil, "lib/c.rb"
install_specs a, b, c
install_gem a, :install_dir => path
install_gem b, :install_dir => path
install_gem c, :install_dir => path
ENV["GEM_PATH"] = path
with_rubygems_gemdeps("-") do
new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
new_RUBYOPT = "-I#{rubygems_path} -I#{bundler_path}"
path = File.join @tempdir, "gem.deps.rb"
File.open path, "w" do |f|
f.puts "gem 'a'"
end
out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
IO.popen("foo", &:read).split(/\n/)
end
File.open path, "a" do |f|
f.puts "gem 'b'"
f.puts "gem 'c'"
end
out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
IO.popen("foo", &:read).split(/\n/)
end
assert_equal ["b-1", "c-1"], out - out0
end
end
end
def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir
path = File.join(@tempdir, "gd-tmp")
with_local_bundler_at(path) do
pend "IO.popen has issues on JRuby when passed :chdir" if Gem.java_platform?
a = util_spec "a", "1" do |s|
s.executables = %w[foo]
s.bindir = "exe"
end
write_file File.join(@tempdir, "exe", "foo") do |fp|
fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort"
end
b = util_spec "b", "1", nil, "lib/b.rb"
c = util_spec "c", "1", nil, "lib/c.rb"
install_specs a, b, c
install_gem a, :install_dir => path
install_gem b, :install_dir => path
install_gem c, :install_dir => path
ENV["GEM_PATH"] = path
with_rubygems_gemdeps("-") do
Dir.mkdir "sub1"
new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
new_RUBYOPT = "-I#{rubygems_path} -I#{bundler_path}"
path = File.join @tempdir, "gem.deps.rb"
File.open path, "w" do |f|
f.puts "gem 'a'"
end
out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
IO.popen("foo", :chdir => "sub1", &:read).split(/\n/)
end
File.open path, "a" do |f|
f.puts "gem 'b'"
f.puts "gem 'c'"
end
out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
IO.popen("foo", :chdir => "sub1", &:read).split(/\n/)
end
Dir.rmdir "sub1"
assert_equal ["b-1", "c-1"], out - out0
end
end
end
def test_use_gemdeps
with_local_bundler_at(Gem.dir) do
gem_deps_file = "gem.deps.rb".tap(&Gem::UNTAINT)
spec = util_spec "a", 1
install_specs spec
spec = Gem::Specification.find {|s| s == spec }
refute spec.activated?
File.open gem_deps_file, "w" do |io|
io.write 'gem "a"'
end
assert_nil Gem.gemdeps
Gem.use_gemdeps gem_deps_file
assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
refute_nil Gem.gemdeps
end
end
def test_use_gemdeps_ENV
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps(nil) do
spec = util_spec "a", 1
refute spec.activated?
File.open "gem.deps.rb", "w" do |io|
io.write 'gem "a"'
end
Gem.use_gemdeps
refute spec.activated?
end
end
end
def test_use_gemdeps_argument_missing
with_local_bundler_at(Gem.dir) do
e = assert_raise ArgumentError do
Gem.use_gemdeps "gem.deps.rb"
end
assert_equal "Unable to find gem dependencies file at gem.deps.rb",
e.message
end
end
def test_use_gemdeps_argument_missing_match_ENV
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("gem.deps.rb") do
e = assert_raise ArgumentError do
Gem.use_gemdeps "gem.deps.rb"
end
assert_equal "Unable to find gem dependencies file at gem.deps.rb",
e.message
end
end
end
def test_use_gemdeps_automatic
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("-") do
spec = util_spec "a", 1
install_specs spec
spec = Gem::Specification.find {|s| s == spec }
refute spec.activated?
File.open "Gemfile", "w" do |io|
io.write 'gem "a"'
end
Gem.use_gemdeps
assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
end
end
end
def test_use_gemdeps_automatic_missing
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("-") do
Gem.use_gemdeps
assert true # count
end
end
end
def test_use_gemdeps_disabled
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("") do
spec = util_spec "a", 1
refute spec.activated?
File.open "gem.deps.rb", "w" do |io|
io.write 'gem "a"'
end
Gem.use_gemdeps
refute spec.activated?
end
end
end
def test_use_gemdeps_missing_gem
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("x") do
File.open "x", "w" do |io|
io.write 'gem "a"'
end
expected = <<-EXPECTED
Could not find gem 'a' in locally installed gems.
You may need to `bundle install` to install missing gems
EXPECTED
Gem::Deprecate.skip_during do
actual_stdout, actual_stderr = capture_output do
Gem.use_gemdeps
end
assert_empty actual_stdout
assert_equal(expected, actual_stderr)
end
end
end
end
def test_use_gemdeps_specific
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("x") do
spec = util_spec "a", 1
install_specs spec
spec = Gem::Specification.find {|s| s == spec }
refute spec.activated?
File.open "x", "w" do |io|
io.write 'gem "a"'
end
Gem.use_gemdeps
assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
end
end
end
private
def add_bundler_full_name(names)
names << "bundler-#{Bundler::VERSION}".freeze
names.sort!
names
end
def with_path_and_rubyopt(path_value, rubyopt_value)
path, ENV["PATH"] = ENV["PATH"], path_value
rubyopt, ENV["RUBYOPT"] = ENV["RUBYOPT"], rubyopt_value
yield
ensure
ENV["PATH"] = path
ENV["RUBYOPT"] = rubyopt
end
def with_rubygems_gemdeps(value)
rubygems_gemdeps, ENV["RUBYGEMS_GEMDEPS"] = ENV["RUBYGEMS_GEMDEPS"], value
yield
ensure
ENV["RUBYGEMS_GEMDEPS"] = rubygems_gemdeps
end
def with_local_bundler_at(path)
require "bundler"
# If bundler gemspec exists, pretend it's installed
bundler_gemspec = File.expand_path("../../bundler/bundler.gemspec", __dir__)
if File.exist?(bundler_gemspec)
target_gemspec_location = "#{path}/specifications/bundler-#{Bundler::VERSION}.gemspec"
FileUtils.mkdir_p File.dirname(target_gemspec_location)
File.write target_gemspec_location, Gem::Specification.load(bundler_gemspec).to_ruby_for_cache
end
yield
ensure
Bundler.reset!
end
end

View file

@ -616,27 +616,6 @@ class TestGem < Gem::TestCase
assert_equal %w[https://rubygems.org/], Gem.default_sources
end
def test_self_use_gemdeps
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("-") do
FileUtils.mkdir_p "detect/a/b"
FileUtils.mkdir_p "detect/a/Isolate"
FileUtils.touch "detect/Isolate"
begin
Dir.chdir "detect/a/b"
Gem.use_gemdeps
assert_equal add_bundler_full_name([]), loaded_spec_names
ensure
Dir.chdir @tempdir
end
end
end
end
def test_self_dir
assert_equal @gemhome, Gem.dir
end
@ -776,43 +755,6 @@ class TestGem < Gem::TestCase
assert_equal cwd, $LOAD_PATH.shift
end
def test_self_find_files_with_gemfile
with_local_bundler_at(Gem.dir) do
cwd = File.expand_path("test/rubygems", PROJECT_DIR)
actual_load_path = $LOAD_PATH.unshift(cwd).dup
discover_path = File.join "lib", "sff", "discover.rb"
foo1, _ = %w[1 2].map do |version|
spec = quick_gem "sff", version do |s|
s.files << discover_path
end
write_file(File.join "gems", spec.full_name, discover_path) do |fp|
fp.puts "# #{spec.full_name}"
end
spec
end
Gem.refresh
write_file(File.join Dir.pwd, "Gemfile") do |fp|
fp.puts "source 'https://rubygems.org'"
fp.puts "gem '#{foo1.name}', '#{foo1.version}'"
end
Gem.use_gemdeps(File.join Dir.pwd, "Gemfile")
expected = [
File.expand_path("test/rubygems/sff/discover.rb", PROJECT_DIR),
File.join(foo1.full_gem_path, discover_path),
].sort
assert_equal expected, Gem.find_files("sff/discover").sort
assert_equal expected, Gem.find_files("sff/**.rb").sort, "[ruby-core:31730]"
assert_equal cwd, actual_load_path.shift
end
end
def test_self_find_latest_files
cwd = File.expand_path("test/rubygems", PROJECT_DIR)
$LOAD_PATH.unshift cwd
@ -1640,168 +1582,6 @@ class TestGem < Gem::TestCase
"Wrong spec selected"
end
def test_auto_activation_of_specific_gemdeps_file
with_local_bundler_at(Gem.dir) do
a = util_spec "a", "1", nil, "lib/a.rb"
b = util_spec "b", "1", nil, "lib/b.rb"
c = util_spec "c", "1", nil, "lib/c.rb"
install_specs a, b, c
path = File.join @tempdir, "gem.deps.rb"
File.open path, "w" do |f|
f.puts "gem 'a'"
f.puts "gem 'b'"
f.puts "gem 'c'"
end
with_rubygems_gemdeps(path) do
Gem.use_gemdeps
assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names
end
end
end
def test_auto_activation_of_used_gemdeps_file
with_local_bundler_at(Gem.dir) do
a = util_spec "a", "1", nil, "lib/a.rb"
b = util_spec "b", "1", nil, "lib/b.rb"
c = util_spec "c", "1", nil, "lib/c.rb"
install_specs a, b, c
path = File.join @tempdir, "gem.deps.rb"
File.open path, "w" do |f|
f.puts "gem 'a'"
f.puts "gem 'b'"
f.puts "gem 'c'"
end
with_rubygems_gemdeps("-") do
expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name)
Gem.use_gemdeps
assert_equal expected_specs, loaded_spec_names
end
end
end
def add_bundler_full_name(names)
names << "bundler-#{Bundler::VERSION}".freeze
names.sort!
names
end
def test_looks_for_gemdeps_files_automatically_from_binstubs
path = File.join(@tempdir, "gd-tmp")
with_local_bundler_at(path) do
a = util_spec "a", "1" do |s|
s.executables = %w[foo]
s.bindir = "exe"
end
write_file File.join(@tempdir, "exe", "foo") do |fp|
fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort"
end
b = util_spec "b", "1", nil, "lib/b.rb"
c = util_spec "c", "1", nil, "lib/c.rb"
install_specs a, b, c
install_gem a, :install_dir => path
install_gem b, :install_dir => path
install_gem c, :install_dir => path
ENV["GEM_PATH"] = path
with_rubygems_gemdeps("-") do
new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
new_RUBYOPT = "-I#{rubygems_path} -I#{bundler_path}"
path = File.join @tempdir, "gem.deps.rb"
File.open path, "w" do |f|
f.puts "gem 'a'"
end
out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
IO.popen("foo", &:read).split(/\n/)
end
File.open path, "a" do |f|
f.puts "gem 'b'"
f.puts "gem 'c'"
end
out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
IO.popen("foo", &:read).split(/\n/)
end
assert_equal ["b-1", "c-1"], out - out0
end
end
end
def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir
path = File.join(@tempdir, "gd-tmp")
with_local_bundler_at(path) do
pend "IO.popen has issues on JRuby when passed :chdir" if Gem.java_platform?
a = util_spec "a", "1" do |s|
s.executables = %w[foo]
s.bindir = "exe"
end
write_file File.join(@tempdir, "exe", "foo") do |fp|
fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort"
end
b = util_spec "b", "1", nil, "lib/b.rb"
c = util_spec "c", "1", nil, "lib/c.rb"
install_specs a, b, c
install_gem a, :install_dir => path
install_gem b, :install_dir => path
install_gem c, :install_dir => path
ENV["GEM_PATH"] = path
with_rubygems_gemdeps("-") do
Dir.mkdir "sub1"
new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
new_RUBYOPT = "-I#{rubygems_path} -I#{bundler_path}"
path = File.join @tempdir, "gem.deps.rb"
File.open path, "w" do |f|
f.puts "gem 'a'"
end
out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
IO.popen("foo", :chdir => "sub1", &:read).split(/\n/)
end
File.open path, "a" do |f|
f.puts "gem 'b'"
f.puts "gem 'c'"
end
out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
IO.popen("foo", :chdir => "sub1", &:read).split(/\n/)
end
Dir.rmdir "sub1"
assert_equal ["b-1", "c-1"], out - out0
end
end
end
def test_register_default_spec
Gem.clear_default_specs
@ -1842,162 +1622,6 @@ class TestGem < Gem::TestCase
assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb")
end
def test_use_gemdeps
with_local_bundler_at(Gem.dir) do
gem_deps_file = "gem.deps.rb".tap(&Gem::UNTAINT)
spec = util_spec "a", 1
install_specs spec
spec = Gem::Specification.find {|s| s == spec }
refute spec.activated?
File.open gem_deps_file, "w" do |io|
io.write 'gem "a"'
end
assert_nil Gem.gemdeps
Gem.use_gemdeps gem_deps_file
assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
refute_nil Gem.gemdeps
end
end
def test_use_gemdeps_ENV
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps(nil) do
spec = util_spec "a", 1
refute spec.activated?
File.open "gem.deps.rb", "w" do |io|
io.write 'gem "a"'
end
Gem.use_gemdeps
refute spec.activated?
end
end
end
def test_use_gemdeps_argument_missing
with_local_bundler_at(Gem.dir) do
e = assert_raise ArgumentError do
Gem.use_gemdeps "gem.deps.rb"
end
assert_equal "Unable to find gem dependencies file at gem.deps.rb",
e.message
end
end
def test_use_gemdeps_argument_missing_match_ENV
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("gem.deps.rb") do
e = assert_raise ArgumentError do
Gem.use_gemdeps "gem.deps.rb"
end
assert_equal "Unable to find gem dependencies file at gem.deps.rb",
e.message
end
end
end
def test_use_gemdeps_automatic
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("-") do
spec = util_spec "a", 1
install_specs spec
spec = Gem::Specification.find {|s| s == spec }
refute spec.activated?
File.open "Gemfile", "w" do |io|
io.write 'gem "a"'
end
Gem.use_gemdeps
assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
end
end
end
def test_use_gemdeps_automatic_missing
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("-") do
Gem.use_gemdeps
assert true # count
end
end
end
def test_use_gemdeps_disabled
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("") do
spec = util_spec "a", 1
refute spec.activated?
File.open "gem.deps.rb", "w" do |io|
io.write 'gem "a"'
end
Gem.use_gemdeps
refute spec.activated?
end
end
end
def test_use_gemdeps_missing_gem
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("x") do
File.open "x", "w" do |io|
io.write 'gem "a"'
end
expected = <<-EXPECTED
Could not find gem 'a' in locally installed gems.
You may need to `bundle install` to install missing gems
EXPECTED
Gem::Deprecate.skip_during do
actual_stdout, actual_stderr = capture_output do
Gem.use_gemdeps
end
assert_empty actual_stdout
assert_equal(expected, actual_stderr)
end
end
end
end
def test_use_gemdeps_specific
with_local_bundler_at(Gem.dir) do
with_rubygems_gemdeps("x") do
spec = util_spec "a", 1
install_specs spec
spec = Gem::Specification.find {|s| s == spec }
refute spec.activated?
File.open "x", "w" do |io|
io.write 'gem "a"'
end
Gem.use_gemdeps
assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
end
end
end
def test_operating_system_defaults
operating_system_defaults = Gem.operating_system_defaults
@ -2110,40 +1734,4 @@ You may need to `bundle install` to install missing gems
def util_cache_dir
File.join Gem.dir, "cache"
end
def with_path_and_rubyopt(path_value, rubyopt_value)
path, ENV["PATH"] = ENV["PATH"], path_value
rubyopt, ENV["RUBYOPT"] = ENV["RUBYOPT"], rubyopt_value
yield
ensure
ENV["PATH"] = path
ENV["RUBYOPT"] = rubyopt
end
def with_rubygems_gemdeps(value)
rubygems_gemdeps, ENV["RUBYGEMS_GEMDEPS"] = ENV["RUBYGEMS_GEMDEPS"], value
yield
ensure
ENV["RUBYGEMS_GEMDEPS"] = rubygems_gemdeps
end
def with_local_bundler_at(path)
require "bundler"
# If bundler gemspec exists, pretend it's installed
bundler_gemspec = File.expand_path("../../bundler/bundler.gemspec", __dir__)
if File.exist?(bundler_gemspec)
target_gemspec_location = "#{path}/specifications/bundler-#{Bundler::VERSION}.gemspec"
FileUtils.mkdir_p File.dirname(target_gemspec_location)
File.write target_gemspec_location, Gem::Specification.load(bundler_gemspec).to_ruby_for_cache
end
yield
ensure
Bundler.reset!
end
end

View file

@ -31,13 +31,12 @@ class TestGemExtCargoBuilder < Gem::TestCase
Dir.chdir @ext do
ENV.update(@rust_envs)
spec = Gem::Specification.new "rust_ruby_example", "0.1.0"
builder = Gem::Ext::CargoBuilder.new(spec)
builder.build nil, @dest_path, output
builder = Gem::Ext::CargoBuilder.new
builder.build "Cargo.toml", @dest_path, output
end
output = output.join "\n"
bundle = File.join(@dest_path, "release/rust_ruby_example.#{RbConfig::CONFIG['DLEXT']}")
bundle = File.join(@dest_path, "rust_ruby_example.#{RbConfig::CONFIG['DLEXT']}")
assert_match(/Finished/, output)
assert_match(/release/, output)
@ -58,13 +57,12 @@ class TestGemExtCargoBuilder < Gem::TestCase
Dir.chdir @ext do
ENV.update(@rust_envs)
spec = Gem::Specification.new "rust_ruby_example", "0.1.0"
builder = Gem::Ext::CargoBuilder.new(spec)
builder.build nil, @dest_path, output
builder = Gem::Ext::CargoBuilder.new
builder.build "Cargo.toml", @dest_path, output
end
output = output.join "\n"
bundle = File.join(@dest_path, "release/rust_ruby_example.#{RbConfig::CONFIG['DLEXT']}")
bundle = File.join(@dest_path, "rust_ruby_example.#{RbConfig::CONFIG['DLEXT']}")
assert_ffi_handle bundle, "hello_from_rubygems"
assert_ffi_handle bundle, "hello_from_rubygems_version"
@ -79,22 +77,17 @@ class TestGemExtCargoBuilder < Gem::TestCase
skip_unsupported_platforms!
setup_rust_gem "rust_ruby_example"
output = []
FileUtils.rm(File.join(@ext, "src/lib.rs"))
error = assert_raise(Gem::InstallError) do
Dir.chdir @ext do
ENV.update(@rust_envs)
spec = Gem::Specification.new "rust_ruby_example", "0.1.0"
builder = Gem::Ext::CargoBuilder.new(spec)
builder.build nil, @dest_path, output
builder = Gem::Ext::CargoBuilder.new
builder.build "Cargo.toml", @dest_path, []
end
end
output = output.join "\n"
assert_match "cargo failed", error.message
assert_match /cargo\s.*\sfailed/, error.message
end
def test_full_integration

View file

@ -1,21 +0,0 @@
if ENV["RUBYOPT"] || defined? Gem
ENV.delete "RUBYOPT"
require "rbconfig"
cmd = [RbConfig.ruby, "--disable-gems", "build.rb", *ARGV]
exec(*cmd)
end
require "tmpdir"
lp = File.expand_path("../../../../lib", __dir__)
gem = ["ruby", "-I#{lp}", File.expand_path("../../../../bin/gem", __dir__)]
gemspec = File.expand_path("custom_name.gemspec", __dir__)
Dir.mktmpdir("custom_name") do |dir|
built_gem = File.expand_path(File.join(dir, "custom_name.gem"))
system(*gem, "build", gemspec, "--output", built_gem)
system(*gem, "install", "--verbose", "--local", built_gem, *ARGV)
system %q(ruby -rcustom_name -e "puts 'Result: ' + CustomName.say_hello")
end

View file

@ -2,9 +2,7 @@ Gem::Specification.new do |s|
s.name = "custom_name"
s.version = "0.1.0"
s.summary = "A Rust extension for Ruby"
s.extensions = ["Cargo.toml"]
s.extensions = ["ext/custom_name_lib/Cargo.toml"]
s.authors = ["Ian Ker-Seymer"]
s.files = ["Cargo.toml", "Cargo.lock", "src/lib.rs"]
s.metadata["cargo_crate_name"] = "custom-name-ext"
s.files = ["lib/custom_name.rb", "ext/custom_name_lib/Cargo.toml", "ext/custom_name_lib/Cargo.lock", "ext/custom_name_lib/src/lib.rs"]
end

View file

@ -12,7 +12,7 @@ unsafe extern "C" fn say_hello(_klass: VALUE) -> VALUE {
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn Init_custom_name() {
pub extern "C" fn Init_custom_name_ext() {
let name = CString::new("CustomName").unwrap();
let function_name = CString::new("say_hello").unwrap();
// bindgen does not properly detect the arity of the ruby callback function, so we have to transmute

View file

@ -0,0 +1 @@
require "custom_name_lib/custom_name_ext"

View file

@ -1,21 +0,0 @@
if ENV["RUBYOPT"] || defined? Gem
ENV.delete "RUBYOPT"
require "rbconfig"
cmd = [RbConfig.ruby, "--disable-gems", "build.rb", *ARGV]
exec(*cmd)
end
require "tmpdir"
lp = File.expand_path("../../../../lib", __dir__)
gem = ["ruby", "-I#{lp}", File.expand_path("../../../../bin/gem", __dir__)]
gemspec = File.expand_path("rust_ruby_example.gemspec", __dir__)
Dir.mktmpdir("rust_ruby_example") do |dir|
built_gem = File.expand_path(File.join(dir, "rust_ruby_example.gem"))
system(*gem, "build", gemspec, "--output", built_gem)
system(*gem, "install", "--verbose", "--local", built_gem, *ARGV)
system %q(ruby -rrust_ruby_example -e "puts 'Result: ' + RustRubyExample.reverse('hello world')")
end

View file

@ -6,8 +6,7 @@ require "rubygems/ext"
class TestGemExtCargoBuilderUnit < Gem::TestCase
def test_cargo_command_passes_args
skip_unsupported_platforms!
spec = Gem::Specification.new "rust_ruby_example", "0.1.0"
builder = Gem::Ext::CargoBuilder.new(spec)
builder = Gem::Ext::CargoBuilder.new
command = builder.cargo_command(Dir.pwd, @tempdir, ["--all-features"])
assert_includes command, "--all-features"
@ -15,8 +14,7 @@ class TestGemExtCargoBuilderUnit < Gem::TestCase
def test_cargo_command_locks_in_release_profile
skip_unsupported_platforms!
spec = Gem::Specification.new "rust_ruby_example", "0.1.0"
builder = Gem::Ext::CargoBuilder.new(spec)
builder = Gem::Ext::CargoBuilder.new
builder.profile = :release
command = builder.cargo_command(Dir.pwd, @tempdir)
@ -27,8 +25,7 @@ class TestGemExtCargoBuilderUnit < Gem::TestCase
skip_unsupported_platforms!
old_cargo = ENV["CARGO"]
ENV["CARGO"] = "mycargo"
spec = Gem::Specification.new "rust_ruby_example", "0.1.0"
builder = Gem::Ext::CargoBuilder.new(spec)
builder = Gem::Ext::CargoBuilder.new
command = builder.cargo_command(Dir.pwd, @tempdir)
assert_includes command, "mycargo"
@ -38,8 +35,7 @@ class TestGemExtCargoBuilderUnit < Gem::TestCase
def test_build_env_includes_rbconfig
skip_unsupported_platforms!
spec = Gem::Specification.new "rust_ruby_example", "0.1.0"
builder = Gem::Ext::CargoBuilder.new(spec)
builder = Gem::Ext::CargoBuilder.new
env = builder.build_env
assert_equal env.fetch("RBCONFIG_RUBY_SO_NAME"), RbConfig::CONFIG["RUBY_SO_NAME"]
@ -49,8 +45,7 @@ class TestGemExtCargoBuilderUnit < Gem::TestCase
skip_unsupported_platforms!
old_cargo = ENV["CARGO_BUILD_TARGET"]
ENV["CARGO_BUILD_TARGET"] = "x86_64-unknown-linux-gnu"
spec = Gem::Specification.new "rust_ruby_example", "0.1.0"
builder = Gem::Ext::CargoBuilder.new(spec)
builder = Gem::Ext::CargoBuilder.new
command = builder.cargo_command(Dir.pwd, @tempdir, ["--locked"])
assert_includes command, "--target"

View file

@ -54,4 +54,4 @@ DEPENDENCIES
webrick (~> 1.6)
BUNDLED WITH
2.4.5
2.4.6

View file

@ -70,4 +70,4 @@ DEPENDENCIES
test-unit
BUNDLED WITH
2.4.5
2.4.6

View file

@ -78,4 +78,4 @@ DEPENDENCIES
test-unit
BUNDLED WITH
2.4.5
2.4.6

View file

@ -42,4 +42,4 @@ DEPENDENCIES
webrick (= 1.7.0)
BUNDLED WITH
2.4.5
2.4.6