summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2022-05-02 19:42:15 +0900
committernagachika <nagachika@ruby-lang.org>2022-05-18 10:02:42 +0900
commit8ba584ff3c085251865c11c5d7deef0ddfc6d0ff (patch)
tree7574439a57c7ad4f9ee7decf7f8272f48e7fc343 /lib
parentec5dae0d816261719b0b2f9595c072701c7036e0 (diff)
Merge RubyGems-3.3.11 and Bundler-2.3.11
Diffstat (limited to 'lib')
-rw-r--r--lib/bundler.rb2
-rw-r--r--lib/bundler/build_metadata.rb2
-rw-r--r--lib/bundler/cli.rb2
-rw-r--r--lib/bundler/cli/info.rb2
-rw-r--r--lib/bundler/cli/init.rb2
-rw-r--r--lib/bundler/cli/show.rb2
-rw-r--r--lib/bundler/installer.rb4
-rw-r--r--lib/bundler/man/bundle-config.16
-rw-r--r--lib/bundler/man/bundle-config.1.ronn14
-rw-r--r--lib/bundler/shared_helpers.rb8
-rw-r--r--lib/bundler/source/metadata.rb2
-rw-r--r--lib/bundler/templates/Executable6
-rw-r--r--lib/bundler/templates/Executable.bundler2
-rw-r--r--lib/bundler/templates/Executable.standalone6
-rw-r--r--lib/bundler/templates/newgem/github/workflows/main.yml.tt2
-rw-r--r--lib/bundler/templates/newgem/newgem.gemspec.tt2
-rw-r--r--lib/bundler/version.rb2
-rw-r--r--lib/rubygems.rb4
-rw-r--r--lib/rubygems/commands/setup_command.rb2
-rw-r--r--lib/rubygems/ext.rb1
-rw-r--r--lib/rubygems/ext/builder.rb3
-rw-r--r--lib/rubygems/ext/cargo_builder.rb305
-rw-r--r--lib/rubygems/ext/ext_conf_builder.rb2
-rw-r--r--lib/rubygems/gemcutter_utilities.rb39
-rw-r--r--lib/rubygems/request.rb2
-rw-r--r--lib/rubygems/source/git.rb1
26 files changed, 381 insertions, 44 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 0025dee720..47b352177d 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -370,7 +370,7 @@ EOF
if env.key?("RUBYLIB")
rubylib = env["RUBYLIB"].split(File::PATH_SEPARATOR)
- rubylib.delete(File.expand_path("..", __FILE__))
+ rubylib.delete(__dir__)
env["RUBYLIB"] = rubylib.join(File::PATH_SEPARATOR)
end
diff --git a/lib/bundler/build_metadata.rb b/lib/bundler/build_metadata.rb
index 0846e82e06..8bffb2fae7 100644
--- a/lib/bundler/build_metadata.rb
+++ b/lib/bundler/build_metadata.rb
@@ -27,7 +27,7 @@ module Bundler
# If Bundler has been installed without its .git directory and without a
# commit instance variable then we can't determine its commits SHA.
- git_dir = File.join(File.expand_path("../../../..", __FILE__), ".git")
+ git_dir = File.expand_path("../../../.git", __dir__)
if File.directory?(git_dir)
return @git_commit_sha = Dir.chdir(git_dir) { `git rev-parse --short HEAD`.strip.freeze }
end
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index 922ba469a4..e1c284130b 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -610,7 +610,7 @@ module Bundler
private :gem
def self.source_root
- File.expand_path(File.join(File.dirname(__FILE__), "templates"))
+ File.expand_path("templates", __dir__)
end
desc "clean [OPTIONS]", "Cleans up unused gems in your bundler directory", :hide => true
diff --git a/lib/bundler/cli/info.rb b/lib/bundler/cli/info.rb
index 38bc008cb5..0545ce8c75 100644
--- a/lib/bundler/cli/info.rb
+++ b/lib/bundler/cli/info.rb
@@ -47,7 +47,7 @@ module Bundler
def print_gem_path(spec)
name = spec.name
if name == "bundler"
- path = File.expand_path("../../../..", __FILE__)
+ path = File.expand_path("../../..", __dir__)
else
path = spec.full_gem_path
if spec.deleted_gem?
diff --git a/lib/bundler/cli/init.rb b/lib/bundler/cli/init.rb
index d851d02d42..e4f8229c48 100644
--- a/lib/bundler/cli/init.rb
+++ b/lib/bundler/cli/init.rb
@@ -32,7 +32,7 @@ module Bundler
file << spec.to_gemfile
end
else
- FileUtils.cp(File.expand_path("../../templates/#{gemfile}", __FILE__), gemfile)
+ FileUtils.cp(File.expand_path("../templates/#{gemfile}", __dir__), gemfile)
end
puts "Writing new #{gemfile} to #{SharedHelpers.pwd}/#{gemfile}"
diff --git a/lib/bundler/cli/show.rb b/lib/bundler/cli/show.rb
index 5eaaba1ef7..2df13db1fa 100644
--- a/lib/bundler/cli/show.rb
+++ b/lib/bundler/cli/show.rb
@@ -18,7 +18,7 @@ module Bundler
if gem_name
if gem_name == "bundler"
- path = File.expand_path("../../../..", __FILE__)
+ path = File.expand_path("../../..", __dir__)
else
spec = Bundler::CLI::Common.select_spec(gem_name, :regex_match)
return unless spec
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index 61bf1e06d4..ca9df4a21e 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -119,7 +119,7 @@ module Bundler
relative_gemfile_path = relative_gemfile_path
ruby_command = Thor::Util.ruby_command
ruby_command = ruby_command
- template_path = File.expand_path("../templates/Executable", __FILE__)
+ template_path = File.expand_path("templates/Executable", __dir__)
if spec.name == "bundler"
template_path += ".bundler"
spec.executables = %(bundle)
@@ -172,7 +172,7 @@ module Bundler
end
standalone_path = Bundler.root.join(path).relative_path_from(bin_path)
standalone_path = standalone_path
- template = File.read(File.expand_path("../templates/Executable.standalone", __FILE__))
+ template = File.read(File.expand_path("templates/Executable.standalone", __dir__))
ruby_command = Thor::Util.ruby_command
ruby_command = ruby_command
diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
index c84a2b106e..d657910e83 100644
--- a/lib/bundler/man/bundle-config.1
+++ b/lib/bundler/man/bundle-config.1
@@ -36,13 +36,13 @@ Executing \fBbundle config list\fR with will print a list of all bundler configu
Executing \fBbundle config get <name>\fR will print the value of that configuration setting, and where it was set\.
.
.P
-Executing \fBbundle config set <name> <value>\fR will set that configuration to the value specified for all bundles executed as the current user\. The configuration will be stored in \fB~/\.bundle/config\fR\. If \fIname\fR already is set, \fIname\fR will be overridden and user will be warned\.
+Executing \fBbundle config set <name> <value>\fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\. See \fB\-\-local\fR and \fB\-\-global\fR options below\.
.
.P
-Executing \fBbundle config set \-\-global <name> <value>\fR works the same as above\.
+Executing \fBbundle config set \-\-local <name> <value>\fR will set that configuration in the directory for the local application\. The configuration will be stored in \fB<project_root>/\.bundle/config\fR\. If \fBBUNDLE_APP_CONFIG\fR is set, the configuration will be stored in \fB$BUNDLE_APP_CONFIG/config\fR\.
.
.P
-Executing \fBbundle config set \-\-local <name> <value>\fR will set that configuration in the directory for the local application\. The configuration will be stored in \fB<project_root>/\.bundle/config\fR\. If \fBBUNDLE_APP_CONFIG\fR is set, the configuration will be stored in \fB$BUNDLE_APP_CONFIG/config\fR\.
+Executing \fBbundle config set \-\-global <name> <value>\fR will set that configuration to the value specified for all bundles executed as the current user\. The configuration will be stored in \fB~/\.bundle/config\fR\. If \fIname\fR already is set, \fIname\fR will be overridden and user will be warned\.
.
.P
Executing \fBbundle config unset <name>\fR will delete the configuration in both local and global sources\.
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
index e0533e05be..7d1cb271a9 100644
--- a/lib/bundler/man/bundle-config.1.ronn
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -23,18 +23,20 @@ was set.
Executing `bundle config get <name>` will print the value of that configuration
setting, and where it was set.
-Executing `bundle config set <name> <value>` will set that configuration to the
-value specified for all bundles executed as the current user. The configuration
-will be stored in `~/.bundle/config`. If <name> already is set, <name> will be
-overridden and user will be warned.
-
-Executing `bundle config set --global <name> <value>` works the same as above.
+Executing `bundle config set <name> <value>` defaults to setting `local`
+configuration if executing from within a local application, otherwise it will
+set `global` configuration. See `--local` and `--global` options below.
Executing `bundle config set --local <name> <value>` will set that configuration
in the directory for the local application. The configuration will be stored in
`<project_root>/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration
will be stored in `$BUNDLE_APP_CONFIG/config`.
+Executing `bundle config set --global <name> <value>` will set that
+configuration to the value specified for all bundles executed as the current
+user. The configuration will be stored in `~/.bundle/config`. If <name> already
+is set, <name> will be overridden and user will be warned.
+
Executing `bundle config unset <name>` will delete the configuration in both
local and global sources.
diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb
index 8b476c9135..ffdbdee503 100644
--- a/lib/bundler/shared_helpers.rb
+++ b/lib/bundler/shared_helpers.rb
@@ -274,10 +274,10 @@ module Bundler
def set_bundle_variables
# bundler exe & lib folders have same root folder, typical gem installation
- exe_file = File.expand_path("../../../exe/bundle", __FILE__)
+ exe_file = File.expand_path("../../exe/bundle", __dir__)
# for Ruby core repository testing
- exe_file = File.expand_path("../../../libexec/bundle", __FILE__) unless File.exist?(exe_file)
+ exe_file = File.expand_path("../../libexec/bundle", __dir__) unless File.exist?(exe_file)
# bundler is a default gem, exe path is separate
exe_file = Bundler.rubygems.bin_path("bundler", "bundle", VERSION) unless File.exist?(exe_file)
@@ -309,7 +309,7 @@ module Bundler
end
def bundler_ruby_lib
- resolve_path File.expand_path("../..", __FILE__)
+ File.expand_path("..", __dir__)
end
def clean_load_path
@@ -325,7 +325,7 @@ module Bundler
def resolve_path(path)
expanded = File.expand_path(path)
- return expanded unless File.respond_to?(:realpath) && File.exist?(expanded)
+ return expanded unless File.exist?(expanded)
File.realpath(expanded)
end
diff --git a/lib/bundler/source/metadata.rb b/lib/bundler/source/metadata.rb
index 8bdbaa5527..524afd750a 100644
--- a/lib/bundler/source/metadata.rb
+++ b/lib/bundler/source/metadata.rb
@@ -22,7 +22,7 @@ module Bundler
s.summary = "The best way to manage your application's dependencies"
s.executables = %w[bundle]
# can't point to the actual gemspec or else the require paths will be wrong
- s.loaded_from = File.expand_path("..", __FILE__)
+ s.loaded_from = __dir__
end
if local_spec = Bundler.rubygems.find_bundler(VERSION)
diff --git a/lib/bundler/templates/Executable b/lib/bundler/templates/Executable
index 3e8d5b317a..f6487e3c89 100644
--- a/lib/bundler/templates/Executable
+++ b/lib/bundler/templates/Executable
@@ -8,11 +8,9 @@
# this file is here to facilitate running it.
#
-require "pathname"
-ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../<%= relative_gemfile_path %>",
- Pathname.new(__FILE__).realpath)
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("<%= relative_gemfile_path %>", __dir__)
-bundle_binstub = File.expand_path("../bundle", __FILE__)
+bundle_binstub = File.expand_path("bundle", __dir__)
if File.file?(bundle_binstub)
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
diff --git a/lib/bundler/templates/Executable.bundler b/lib/bundler/templates/Executable.bundler
index 6bb5c51090..51650c7664 100644
--- a/lib/bundler/templates/Executable.bundler
+++ b/lib/bundler/templates/Executable.bundler
@@ -41,7 +41,7 @@ m = Module.new do
gemfile = ENV["BUNDLE_GEMFILE"]
return gemfile if gemfile && !gemfile.empty?
- File.expand_path("../<%= relative_gemfile_path %>", __FILE__)
+ File.expand_path("<%= relative_gemfile_path %>", __dir__)
end
def lockfile
diff --git a/lib/bundler/templates/Executable.standalone b/lib/bundler/templates/Executable.standalone
index 4bf0753f44..d591e3fc04 100644
--- a/lib/bundler/templates/Executable.standalone
+++ b/lib/bundler/templates/Executable.standalone
@@ -6,9 +6,7 @@
# this file is here to facilitate running it.
#
-require "pathname"
-path = Pathname.new(__FILE__)
-$:.unshift File.expand_path "../<%= standalone_path %>", path.realpath
+$:.unshift File.expand_path "<%= standalone_path %>", __dir__
require "bundler/setup"
-load File.expand_path "../<%= executable_path %>", path.realpath
+load File.expand_path "<%= executable_path %>", __dir__
diff --git a/lib/bundler/templates/newgem/github/workflows/main.yml.tt b/lib/bundler/templates/newgem/github/workflows/main.yml.tt
index 6570d177af..1ff4b58b7b 100644
--- a/lib/bundler/templates/newgem/github/workflows/main.yml.tt
+++ b/lib/bundler/templates/newgem/github/workflows/main.yml.tt
@@ -17,7 +17,7 @@ jobs:
- '<%= RUBY_VERSION %>'
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt
index 546a28b78a..ceb2e9b28d 100644
--- a/lib/bundler/templates/newgem/newgem.gemspec.tt
+++ b/lib/bundler/templates/newgem/newgem.gemspec.tt
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
+ spec.files = Dir.chdir(__dir__) do
`git ls-files -z`.split("\x0").reject do |f|
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
end
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index 6a5af6c296..f8d69d73e6 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
- VERSION = "2.3.10".freeze
+ VERSION = "2.3.11".freeze
def self.bundler_major_version
@bundler_major_version ||= VERSION.split(".").first.to_i
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 68c0781a50..a99281fef5 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -8,7 +8,7 @@
require 'rbconfig'
module Gem
- VERSION = "3.3.10".freeze
+ VERSION = "3.3.11".freeze
end
# Must be first since it unloads the prelude from 1.9.2
@@ -112,7 +112,7 @@ require_relative 'rubygems/errors'
# -The RubyGems Team
module Gem
- RUBYGEMS_DIR = File.dirname File.expand_path(__FILE__)
+ RUBYGEMS_DIR = __dir__
# Taint support is deprecated in Ruby 2.7.
# This allows switching ".untaint" to ".tap(&Gem::UNTAINT)",
diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb
index 01714f0342..7b6890013c 100644
--- a/lib/rubygems/commands/setup_command.rb
+++ b/lib/rubygems/commands/setup_command.rb
@@ -341,7 +341,7 @@ By default, this RubyGems will install gem as:
fake_spec = Gem::Specification.new 'rubygems', Gem::VERSION
def fake_spec.full_gem_path
- File.expand_path '../../../..', __FILE__
+ File.expand_path '../../..', __dir__
end
generate_ri = options[:document].include? 'ri'
diff --git a/lib/rubygems/ext.rb b/lib/rubygems/ext.rb
index bdd5bd9d82..59fd830437 100644
--- a/lib/rubygems/ext.rb
+++ b/lib/rubygems/ext.rb
@@ -16,3 +16,4 @@ require_relative 'ext/configure_builder'
require_relative 'ext/ext_conf_builder'
require_relative 'ext/rake_builder'
require_relative 'ext/cmake_builder'
+require_relative 'ext/cargo_builder'
diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb
index 6d32be6515..d9aa68c067 100644
--- a/lib/rubygems/ext/builder.rb
+++ b/lib/rubygems/ext/builder.rb
@@ -123,6 +123,9 @@ class Gem::Ext::Builder
Gem::Ext::RakeBuilder
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)
else
build_error("No builder for extension '#{extension}'")
end
diff --git a/lib/rubygems/ext/cargo_builder.rb b/lib/rubygems/ext/cargo_builder.rb
new file mode 100644
index 0000000000..4c16063224
--- /dev/null
+++ b/lib/rubygems/ext/cargo_builder.rb
@@ -0,0 +1,305 @@
+# frozen_string_literal: true
+
+# This class is used by rubygems to build Rust extensions. It is a thin-wrapper
+# over the `cargo rustc` command which takes care of building Rust code in a way
+# that Ruby can use.
+class Gem::Ext::CargoBuilder < Gem::Ext::Builder
+ attr_reader :spec
+
+ def initialize(spec)
+ @spec = spec
+ end
+
+ def build(_extension, dest_path, results, args = [], lib_dir = nil, cargo_dir = Dir.pwd)
+ require "rubygems/command"
+ require "fileutils"
+ require "shellwords"
+
+ build_crate(dest_path, results, args, cargo_dir)
+ ext_path = rename_cdylib_for_ruby_compatibility(dest_path)
+ finalize_directory(ext_path, dest_path, lib_dir, cargo_dir)
+ results
+ end
+
+ private
+
+ def build_crate(dest_path, results, args, cargo_dir)
+ manifest = File.join(cargo_dir, "Cargo.toml")
+
+ given_ruby_static = ENV["RUBY_STATIC"]
+
+ ENV["RUBY_STATIC"] = "true" if ruby_static? && !given_ruby_static
+
+ cargo = ENV.fetch("CARGO", "cargo")
+
+ cmd = []
+ cmd += [cargo, "rustc"]
+ cmd += ["--target-dir", dest_path]
+ cmd += ["--manifest-path", manifest]
+ cmd += ["--lib", "--release", "--locked"]
+ cmd += ["--"]
+ cmd += [*cargo_rustc_args(dest_path)]
+ cmd += Gem::Command.build_args
+ cmd += args
+
+ self.class.run cmd, results, self.class.class_name, cargo_dir
+ results
+ ensure
+ ENV["RUBY_STATIC"] = given_ruby_static
+ end
+
+ def cargo_rustc_args(dest_dir)
+ [
+ *linker_args,
+ *mkmf_libpath,
+ *rustc_dynamic_linker_flags(dest_dir),
+ *rustc_lib_flags(dest_dir),
+ *platform_specific_rustc_args(dest_dir),
+ *debug_flags,
+ ]
+ end
+
+ def platform_specific_rustc_args(dest_dir, flags = [])
+ if mingw_target?
+ # On mingw platforms, mkmf adds libruby to the linker flags
+ flags += libruby_args(dest_dir)
+
+ # Make sure ALSR is used on mingw
+ # see https://github.com/rust-lang/rust/pull/75406/files
+ flags += ["-C", "link-arg=-Wl,--dynamicbase"]
+ flags += ["-C", "link-arg=-Wl,--disable-auto-image-base"]
+
+ # If the gem is installed on a host with build tools installed, but is
+ # run on one that isn't the missing libraries will cause the extension
+ # to fail on start.
+ flags += ["-C", "link-arg=-static-libgcc"]
+ end
+
+ flags
+ end
+
+ # We want to use the same linker that Ruby uses, so that the linker flags from
+ # mkmf work properly.
+ def linker_args
+ # Have to handle CC="cl /nologo" on mswin
+ cc_flag = Shellwords.split(makefile_config("CC"))
+ linker = cc_flag.shift
+ link_args = cc_flag.flat_map {|a| ["-C", "link-arg=#{a}"] }
+
+ ["-C", "linker=#{linker}", *link_args]
+ end
+
+ def libruby_args(dest_dir)
+ libs = makefile_config(ruby_static? ? "LIBRUBYARG_STATIC" : "LIBRUBYARG_SHARED")
+ raw_libs = Shellwords.split(libs)
+ raw_libs.flat_map {|l| ldflag_to_link_modifier(l, dest_dir) }
+ end
+
+ def ruby_static?
+ return true if %w[1 true].include?(ENV["RUBY_STATIC"])
+
+ 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)
+ dylib_path = validate_cargo_build!(dest_path)
+ dlext_name = "#{spec.name}.#{makefile_config("DLEXT")}"
+ new_name = dylib_path.gsub(File.basename(dylib_path), dlext_name)
+ FileUtils.cp(dylib_path, new_name)
+ new_name
+ end
+
+ def validate_cargo_build!(dir)
+ prefix = so_ext == "dll" ? "" : "lib"
+ dylib_path = File.join(dir, "release", "#{prefix}#{cargo_crate_name}.#{so_ext}")
+
+ raise DylibNotFoundError, dir unless File.exist?(dylib_path)
+
+ dylib_path
+ end
+
+ def cargo_crate_name
+ spec.metadata.fetch('cargo_crate_name', spec.name).tr('-', '_')
+ end
+
+ def rustc_dynamic_linker_flags(dest_dir)
+ split_flags("DLDFLAGS")
+ .map {|arg| maybe_resolve_ldflag_variable(arg, dest_dir) }
+ .compact
+ .flat_map {|arg| ldflag_to_link_modifier(arg, dest_dir) }
+ end
+
+ def rustc_lib_flags(dest_dir)
+ split_flags("LIBS").flat_map {|arg| ldflag_to_link_modifier(arg, dest_dir) }
+ end
+
+ def split_flags(var)
+ Shellwords.split(RbConfig::CONFIG.fetch(var, ""))
+ end
+
+ def ldflag_to_link_modifier(arg, dest_dir)
+ flag = arg[0..1]
+ val = arg[2..-1]
+
+ case flag
+ when "-L" then ["-L", "native=#{val}"]
+ when "-l" then ["-l", val.to_s]
+ when "-F" then ["-l", "framework=#{val}"]
+ else ["-C", "link_arg=#{arg}"]
+ end
+ end
+
+ def link_flag(link_name)
+ # These are provided by the CRT with MSVC
+ # @see https://github.com/rust-lang/pkg-config-rs/blob/49a4ac189aafa365167c72e8e503565a7c2697c2/src/lib.rs#L622
+ return [] if msvc_target? && ["m", "c", "pthread"].include?(link_name)
+
+ if link_name.include?("ruby")
+ # Specify the lib kind and give it the name "ruby" for linking
+ kind = ruby_static? ? "static" : "dylib"
+
+ ["-l", "#{kind}=ruby:#{link_name}"]
+ else
+ ["-l", link_name]
+ end
+ end
+
+ def msvc_target?
+ makefile_config("target_os").include?("msvc")
+ end
+
+ def darwin_target?
+ makefile_config("target_os").include?("darwin")
+ end
+
+ def mingw_target?
+ makefile_config("target_os").include?("mingw")
+ end
+
+ def win_target?
+ target_platform = RbConfig::CONFIG["target_os"]
+ !!Gem::WIN_PATTERNS.find {|r| target_platform =~ r }
+ end
+
+ # Intepolate substition vars in the arg (i.e. $(DEFFILE))
+ def maybe_resolve_ldflag_variable(input_arg, dest_dir)
+ str = input_arg.gsub(/\$\((\w+)\)/) do |var_name|
+ case var_name
+ # 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)
+ else
+ RbConfig::CONFIG[var_name]
+ end
+ end.strip
+
+ str == "" ? nil : str
+ end
+
+ def write_deffile(dest_dir)
+ deffile_path = File.join(dest_dir, "#{spec.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}"
+ end
+
+ deffile_path
+ end
+
+ # We have to basically reimplement RbConfig::CONFIG['SOEXT'] here to support
+ # Ruby < 2.5
+ #
+ # @see https://github.com/ruby/ruby/blob/c87c027f18c005460746a74c07cd80ee355b16e4/configure.ac#L3185
+ def so_ext
+ return RbConfig::CONFIG["SOEXT"] if RbConfig::CONFIG.key?("SOEXT")
+
+ if win_target?
+ "dll"
+ elsif darwin_target?
+ "dylib"
+ else
+ "so"
+ end
+ end
+
+ # Corresponds to $(LIBPATH) in mkmf
+ def mkmf_libpath
+ ["-L", "native=#{makefile_config("libdir")}"]
+ end
+
+ def makefile_config(var_name)
+ val = RbConfig::MAKEFILE_CONFIG[var_name]
+
+ return unless val
+
+ RbConfig.expand(val.dup)
+ end
+
+ # Good balance between binary size and debugability
+ def debug_flags
+ ["-C", "debuginfo=1"]
+ end
+
+ # Copied from ExtConfBuilder
+ def finalize_directory(ext_path, dest_path, lib_dir, extension_dir)
+ require "fileutils"
+ require "tempfile"
+
+ begin
+ tmp_dest = Dir.mktmpdir(".gem.", extension_dir)
+
+ # Some versions of `mktmpdir` return absolute paths, which will break make
+ # if the paths contain spaces. However, on Ruby 1.9.x on Windows, relative
+ # paths cause all C extension builds to fail.
+ #
+ # As such, we convert to a relative path unless we are using Ruby 1.9.x on
+ # Windows. This means that when using Ruby 1.9.x on Windows, paths with
+ # spaces do not work.
+ #
+ # Details: https://github.com/rubygems/rubygems/issues/977#issuecomment-171544940
+ tmp_dest_relative = get_relative_path(tmp_dest.clone, extension_dir)
+
+ if tmp_dest_relative
+ full_tmp_dest = File.join(extension_dir, tmp_dest_relative)
+
+ # TODO: remove in RubyGems 3
+ 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
+ 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)
+ files = Dir.glob(File.join(dir, "**", "*")).map {|f| "- #{f}" }.join "\n"
+
+ super <<~MSG
+ Dynamic library not found for Rust extension (in #{dir})
+
+ Make sure you set "crate-type" in Cargo.toml to "cdylib"
+
+ Found files:
+ #{files}
+ MSG
+ end
+ end
+end
diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb
index 3ca3463615..3e8aa950c9 100644
--- a/lib/rubygems/ext/ext_conf_builder.rb
+++ b/lib/rubygems/ext/ext_conf_builder.rb
@@ -39,7 +39,7 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
# workaround for https://github.com/oracle/truffleruby/issues/2115
siteconf_path = RUBY_ENGINE == "truffleruby" ? siteconf.path.dup : siteconf.path
require "shellwords"
- cmd = Gem.ruby.shellsplit << "-I" << File.expand_path("../../..", __FILE__) <<
+ cmd = Gem.ruby.shellsplit << "-I" << File.expand_path('../..', __dir__) <<
"-r" << get_relative_path(siteconf_path, extension_dir) << File.basename(extension)
cmd.push(*args)
diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb
index 0968e1a6f9..7cb5fe9448 100644
--- a/lib/rubygems/gemcutter_utilities.rb
+++ b/lib/rubygems/gemcutter_utilities.rb
@@ -163,12 +163,14 @@ module Gem::GemcutterUtilities
key_name = get_key_name(scope)
scope_params = get_scope_params(scope)
+ mfa_params = get_mfa_params(email, password)
+ all_params = scope_params.merge(mfa_params)
response = rubygems_api_request(:post, "api/v1/api_key",
sign_in_host, scope: scope) do |request|
request.basic_auth email, password
request["OTP"] = otp if otp
- request.body = URI.encode_www_form({ name: key_name }.merge(scope_params))
+ request.body = URI.encode_www_form({ name: key_name }.merge(all_params))
end
with_response response do |resp|
@@ -219,7 +221,7 @@ module Gem::GemcutterUtilities
# +response+ text and no otp provided by options.
def set_api_key(host, key)
- if host == Gem::DEFAULT_HOST
+ if default_host?
Gem.configuration.rubygems_api_key = key
else
Gem.configuration.set_api_key host, key
@@ -243,7 +245,7 @@ module Gem::GemcutterUtilities
end
def pretty_host(host)
- if Gem::DEFAULT_HOST == host
+ if default_host?
'RubyGems.org'
else
host
@@ -258,8 +260,8 @@ module Gem::GemcutterUtilities
else
say "Please select scopes you want to enable for the API key (y/n)"
API_SCOPES.each do |scope|
- selected = ask "#{scope} [y/N]: "
- scope_params[scope] = true if selected =~ /^[yY](es)?$/
+ selected = ask_yes_no("#{scope}", false)
+ scope_params[scope] = true if selected
end
say "\n"
end
@@ -267,6 +269,33 @@ module Gem::GemcutterUtilities
scope_params
end
+ def default_host?
+ self.host == Gem::DEFAULT_HOST
+ end
+
+ def get_mfa_params(email, password)
+ return {} unless default_host?
+
+ mfa_level = get_user_mfa_level(email, password)
+ params = {}
+ if mfa_level == "ui_only" || mfa_level == "ui_and_gem_signin"
+ selected = ask_yes_no("Would you like to enable MFA for this key? (strongly recommended)")
+ params["mfa"] = true if selected
+ end
+ params
+ end
+
+ def get_user_mfa_level(email, password)
+ response = rubygems_api_request(:get, "api/v1/profile/me.yaml") do |request|
+ request.basic_auth email, password
+ end
+
+ with_response response do |resp|
+ body = Gem::SafeYAML.load clean_text(resp.body)
+ body["mfa"]
+ end
+ end
+
def get_key_name(scope)
hostname = Socket.gethostname || "unknown-host"
user = ENV["USER"] || ENV["USERNAME"] || "unknown-user"
diff --git a/lib/rubygems/request.rb b/lib/rubygems/request.rb
index d6100c914b..136b154bee 100644
--- a/lib/rubygems/request.rb
+++ b/lib/rubygems/request.rb
@@ -39,7 +39,7 @@ class Gem::Request
def cert_files; @connection_pool.cert_files; end
def self.get_cert_files
- pattern = File.expand_path("./ssl_certs/*/*.pem", File.dirname(__FILE__))
+ pattern = File.expand_path("./ssl_certs/*/*.pem", __dir__)
Dir.glob(pattern)
end
diff --git a/lib/rubygems/source/git.rb b/lib/rubygems/source/git.rb
index cda5aa8073..8d5dc1f69d 100644
--- a/lib/rubygems/source/git.rb
+++ b/lib/rubygems/source/git.rb
@@ -102,6 +102,7 @@ class Gem::Source::Git < Gem::Source
success = system @git, 'reset', '--quiet', '--hard', rev_parse
if @need_submodules
+ require "open3"
_, status = Open3.capture2e(@git, 'submodule', 'update', '--quiet', '--init', '--recursive')
success &&= status.success?