Merge RubyGems-3.4.10 and Bundler-2.4.10 (#7479)

* Merge RubyGems-3.4.7 and Bundler-2.4.7

* Merge RubyGems-3.4.8 and Bundler-2.4.8

* Skip failing test on MSWin

* Merge RubyGems-3.4.9 and Bundler-2.4.9

* Merge RubyGems-3.4.10 and Bundler-2.4.10

---------

Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
This commit is contained in:
Hiroshi SHIBATA 2023-03-28 20:36:47 +09:00 committed by GitHub
parent f8c775cb41
commit c3c461c4ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
179 changed files with 2882 additions and 469 deletions

View file

@ -39,8 +39,8 @@ module Bundler
environment_preserver.replace_with_backup environment_preserver.replace_with_backup
SUDO_MUTEX = Thread::Mutex.new SUDO_MUTEX = Thread::Mutex.new
SAFE_MARSHAL_CLASSES = [Symbol, TrueClass, String, Array, Hash].freeze SAFE_MARSHAL_CLASSES = [Symbol, TrueClass, String, Array, Hash, Gem::Version, Gem::Specification].freeze
SAFE_MARSHAL_ERROR = "Unexpected class %s present in marshaled data. Only %s are allowed.".freeze SAFE_MARSHAL_ERROR = "Unexpected class %s present in marshaled data. Only %s are allowed."
SAFE_MARSHAL_PROC = proc do |object| SAFE_MARSHAL_PROC = proc do |object|
object.tap do object.tap do
unless SAFE_MARSHAL_CLASSES.include?(object.class) unless SAFE_MARSHAL_CLASSES.include?(object.class)
@ -85,6 +85,7 @@ module Bundler
autoload :StubSpecification, File.expand_path("bundler/stub_specification", __dir__) autoload :StubSpecification, File.expand_path("bundler/stub_specification", __dir__)
autoload :UI, File.expand_path("bundler/ui", __dir__) autoload :UI, File.expand_path("bundler/ui", __dir__)
autoload :URICredentialsFilter, File.expand_path("bundler/uri_credentials_filter", __dir__) autoload :URICredentialsFilter, File.expand_path("bundler/uri_credentials_filter", __dir__)
autoload :URINormalizer, File.expand_path("bundler/uri_normalizer", __dir__)
class << self class << self
def configure def configure
@ -506,7 +507,7 @@ EOF
if File.file?(executable) && File.executable?(executable) if File.file?(executable) && File.executable?(executable)
executable executable
elsif paths = ENV["PATH"] elsif paths = ENV["PATH"]
quote = '"'.freeze quote = '"'
paths.split(File::PATH_SEPARATOR).find do |path| paths.split(File::PATH_SEPARATOR).find do |path|
path = path[1..-2] if path.start_with?(quote) && path.end_with?(quote) path = path[1..-2] if path.start_with?(quote) && path.end_with?(quote)
executable_path = File.expand_path(executable, path) executable_path = File.expand_path(executable, path)
@ -525,12 +526,6 @@ EOF
load_marshal(data, :marshal_proc => SAFE_MARSHAL_PROC) load_marshal(data, :marshal_proc => SAFE_MARSHAL_PROC)
end end
def load_marshal(data, marshal_proc: nil)
Marshal.load(data, marshal_proc)
rescue TypeError => e
raise MarshalError, "#{e.class}: #{e.message}"
end
def load_gemspec(file, validate = false) def load_gemspec(file, validate = false)
@gemspec_cache ||= {} @gemspec_cache ||= {}
key = File.expand_path(file) key = File.expand_path(file)
@ -619,6 +614,12 @@ EOF
private private
def load_marshal(data, marshal_proc: nil)
Marshal.load(data, marshal_proc)
rescue TypeError => e
raise MarshalError, "#{e.class}: #{e.message}"
end
def eval_yaml_gemspec(path, contents) def eval_yaml_gemspec(path, contents)
Kernel.require "psych" Kernel.require "psych"

View file

@ -156,6 +156,7 @@ module Bundler
dependency listed in the gemspec file to the newly created Gemfile. dependency listed in the gemspec file to the newly created Gemfile.
D D
method_option "gemspec", :type => :string, :banner => "Use the specified .gemspec to create the Gemfile" method_option "gemspec", :type => :string, :banner => "Use the specified .gemspec to create the Gemfile"
method_option "gemfile", :type => :string, :banner => "Use the specified name for the gemfile instead of 'Gemfile'"
def init def init
require_relative "cli/init" require_relative "cli/init"
Init.new(options.dup).run Init.new(options.dup).run

View file

@ -32,7 +32,7 @@ module Bundler
file << spec.to_gemfile file << spec.to_gemfile
end end
else else
File.open(File.expand_path("../templates/#{gemfile}", __dir__), "r") do |template| File.open(File.expand_path("../templates/Gemfile", __dir__), "r") do |template|
File.open(gemfile, "wb") do |destination| File.open(gemfile, "wb") do |destination|
IO.copy_stream(template, destination) IO.copy_stream(template, destination)
end end
@ -45,7 +45,7 @@ module Bundler
private private
def gemfile def gemfile
@gemfile ||= Bundler.preferred_gemfile_name @gemfile ||= options[:gemfile] || Bundler.preferred_gemfile_name
end end
end end
end end

View file

@ -22,6 +22,8 @@ module Bundler
2.7 2.7
3.0 3.0
3.1 3.1
3.2
3.3
].freeze ].freeze
KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze

View file

@ -726,6 +726,8 @@ module Bundler
dep.source = sources.get(dep.source) dep.source = sources.get(dep.source)
end end
next if unlocking?
unless locked_dep = @locked_deps[dep.name] unless locked_dep = @locked_deps[dep.name]
changes = true changes = true
next next
@ -886,8 +888,9 @@ module Bundler
end end
def additional_base_requirements_for_resolve(resolution_packages, last_resolve) def additional_base_requirements_for_resolve(resolution_packages, last_resolve)
return resolution_packages unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources) return resolution_packages unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
converge_specs(@originally_locked_specs - last_resolve).each do |locked_spec| converge_specs(@originally_locked_specs - last_resolve).each do |locked_spec|
next if locked_spec.source.is_a?(Source::Path)
resolution_packages.base_requirements[locked_spec.name] = Gem::Requirement.new(">= #{locked_spec.version}") resolution_packages.base_requirements[locked_spec.name] = Gem::Requirement.new(">= #{locked_spec.version}")
end end
resolution_packages resolution_packages
@ -898,6 +901,7 @@ module Bundler
Bundler.local_platform == Gem::Platform::RUBY || Bundler.local_platform == Gem::Platform::RUBY ||
!platforms.include?(Gem::Platform::RUBY) || !platforms.include?(Gem::Platform::RUBY) ||
(@new_platform && platforms.last == Gem::Platform::RUBY) || (@new_platform && platforms.last == Gem::Platform::RUBY) ||
@dependency_changes ||
!@originally_locked_specs.incomplete_ruby_specs?(dependencies) !@originally_locked_specs.incomplete_ruby_specs?(dependencies)
remove_platform(Gem::Platform::RUBY) remove_platform(Gem::Platform::RUBY)

View file

@ -9,7 +9,7 @@ module Bundler
attr_reader :autorequire attr_reader :autorequire
attr_reader :groups, :platforms, :gemfile, :path, :git, :github, :branch, :ref attr_reader :groups, :platforms, :gemfile, :path, :git, :github, :branch, :ref
ALL_RUBY_VERSIONS = ((18..27).to_a + (30..31).to_a).freeze ALL_RUBY_VERSIONS = ((18..27).to_a + (30..33).to_a).freeze
PLATFORM_MAP = { PLATFORM_MAP = {
:ruby => [Gem::Platform::RUBY, ALL_RUBY_VERSIONS], :ruby => [Gem::Platform::RUBY, ALL_RUBY_VERSIONS],
:mri => [Gem::Platform::RUBY, ALL_RUBY_VERSIONS], :mri => [Gem::Platform::RUBY, ALL_RUBY_VERSIONS],

View file

@ -26,10 +26,6 @@ module Bundler
@platform @platform
end end
def identifier
@__identifier ||= [name, version, platform.to_s]
end
# needed for standalone, load required_paths from local gemspec # needed for standalone, load required_paths from local gemspec
# after the gem is installed # after the gem is installed
def require_paths def require_paths

View file

@ -2,7 +2,7 @@
module Bundler module Bundler
class EnvironmentPreserver class EnvironmentPreserver
INTENTIONALLY_NIL = "BUNDLER_ENVIRONMENT_PRESERVER_INTENTIONALLY_NIL".freeze INTENTIONALLY_NIL = "BUNDLER_ENVIRONMENT_PRESERVER_INTENTIONALLY_NIL"
BUNDLER_KEYS = %w[ BUNDLER_KEYS = %w[
BUNDLE_BIN_PATH BUNDLE_BIN_PATH
BUNDLE_GEMFILE BUNDLE_GEMFILE
@ -16,7 +16,7 @@ module Bundler
RUBYLIB RUBYLIB
RUBYOPT RUBYOPT
].map(&:freeze).freeze ].map(&:freeze).freeze
BUNDLER_PREFIX = "BUNDLER_ORIG_".freeze BUNDLER_PREFIX = "BUNDLER_ORIG_"
def self.from_env def self.from_env
new(env_to_hash(ENV), BUNDLER_KEYS) new(env_to_hash(ENV), BUNDLER_KEYS)

View file

@ -102,11 +102,11 @@ module Bundler
uri = Bundler::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz") uri = Bundler::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
if uri.scheme == "file" if uri.scheme == "file"
path = Bundler.rubygems.correct_for_windows_path(uri.path) path = Bundler.rubygems.correct_for_windows_path(uri.path)
Bundler.load_marshal Bundler.rubygems.inflate(Gem.read_binary(path)) Bundler.safe_load_marshal Bundler.rubygems.inflate(Gem.read_binary(path))
elsif cached_spec_path = gemspec_cached_path(spec_file_name) elsif cached_spec_path = gemspec_cached_path(spec_file_name)
Bundler.load_gemspec(cached_spec_path) Bundler.load_gemspec(cached_spec_path)
else else
Bundler.load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body) Bundler.safe_load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body)
end end
rescue MarshalError rescue MarshalError
raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \ raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \

View file

@ -34,14 +34,10 @@ module Bundler
returned_gems = spec_list.map(&:first).uniq returned_gems = spec_list.map(&:first).uniq
specs(deps_list, full_dependency_list + returned_gems, spec_list + last_spec_list) specs(deps_list, full_dependency_list + returned_gems, spec_list + last_spec_list)
rescue MarshalError rescue MarshalError, HTTPError, GemspecError
Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
Bundler.ui.debug "could not fetch from the dependency API, trying the full index" Bundler.ui.debug "could not fetch from the dependency API, trying the full index"
nil nil
rescue HTTPError, GemspecError
Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
Bundler.ui.debug "could not fetch from the dependency API\nit's suggested to retry using the full index via `bundle install --full-index`"
nil
end end
def dependency_specs(gem_names) def dependency_specs(gem_names)

View file

@ -13,8 +13,8 @@ module Bundler
attr_reader :specs, :all_specs, :sources attr_reader :specs, :all_specs, :sources
protected :specs, :all_specs protected :specs, :all_specs
RUBY = "ruby".freeze RUBY = "ruby"
NULL = "\0".freeze NULL = "\0"
def initialize def initialize
@sources = [] @sources = []

View file

@ -2,7 +2,7 @@
module Bundler module Bundler
class Injector class Injector
INJECTED_GEMS = "injected gems".freeze INJECTED_GEMS = "injected gems"
def self.inject(new_deps, options = {}) def self.inject(new_deps, options = {})
injector = new(new_deps, options) injector = new(new_deps, options)

View file

@ -110,12 +110,13 @@ module Bundler
warning = [] warning = []
warning << "Your lockfile doesn't include a valid resolution." warning << "Your lockfile doesn't include a valid resolution."
warning << "You can fix this by regenerating your lockfile or trying to manually editing the bad locked gems to a version that satisfies all dependencies." warning << "You can fix this by regenerating your lockfile or manually editing the bad locked gems to a version that satisfies all dependencies."
warning << "The unmet dependencies are:" warning << "The unmet dependencies are:"
unmet_dependencies.each do |spec, unmet_spec_dependencies| unmet_dependencies.each do |spec, unmet_spec_dependencies|
unmet_spec_dependencies.each do |unmet_spec_dependency| unmet_spec_dependencies.each do |unmet_spec_dependency|
warning << "* #{unmet_spec_dependency}, depended upon #{spec.full_name}, unsatisfied by #{@specs.find {|s| s.name == unmet_spec_dependency.name && !unmet_spec_dependency.matches_spec?(s.spec) }.full_name}" found = @specs.find {|s| s.name == unmet_spec_dependency.name && !unmet_spec_dependency.matches_spec?(s.spec) }
warning << "* #{unmet_spec_dependency}, dependency of #{spec.full_name}, unsatisfied by #{found.full_name}"
end end
end end

View file

@ -52,7 +52,7 @@ module Bundler
def gem_path(path, spec) def gem_path(path, spec)
full_path = Pathname.new(path).absolute? ? path : File.join(spec.full_gem_path, path) full_path = Pathname.new(path).absolute? ? path : File.join(spec.full_gem_path, path)
if spec.source.instance_of?(Source::Path) if spec.source.instance_of?(Source::Path) && spec.source.path.absolute?
full_path full_path
else else
Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s

View file

@ -20,7 +20,7 @@ module Bundler
end end
def full_name def full_name
if platform == Gem::Platform::RUBY @full_name ||= if platform == Gem::Platform::RUBY
"#{@name}-#{@version}" "#{@name}-#{@version}"
else else
"#{@name}-#{@version}-#{platform}" "#{@name}-#{@version}-#{platform}"
@ -28,15 +28,15 @@ module Bundler
end end
def ==(other) def ==(other)
identifier == other.identifier full_name == other.full_name
end end
def eql?(other) def eql?(other)
identifier.eql?(other.identifier) full_name.eql?(other.full_name)
end end
def hash def hash
identifier.hash full_name.hash
end end
## ##
@ -129,10 +129,6 @@ module Bundler
end end
end end
def identifier
@__identifier ||= [name, version, platform.to_s]
end
def git_version def git_version
return unless source.is_a?(Bundler::Source::Git) return unless source.is_a?(Bundler::Source::Git)
" #{source.revision[0..6]}" " #{source.revision[0..6]}"

View file

@ -45,7 +45,7 @@ module Bundler
# gems with the same name, but different platform # gems with the same name, but different platform
# are ordered consistently # are ordered consistently
specs.sort_by(&:full_name).each do |spec| specs.sort_by(&:full_name).each do |spec|
next if spec.name == "bundler".freeze next if spec.name == "bundler"
out << spec.to_lock out << spec.to_lock
end end
end end

View file

@ -4,15 +4,15 @@ module Bundler
class LockfileParser class LockfileParser
attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version
BUNDLED = "BUNDLED WITH".freeze BUNDLED = "BUNDLED WITH"
DEPENDENCIES = "DEPENDENCIES".freeze DEPENDENCIES = "DEPENDENCIES"
PLATFORMS = "PLATFORMS".freeze PLATFORMS = "PLATFORMS"
RUBY = "RUBY VERSION".freeze RUBY = "RUBY VERSION"
GIT = "GIT".freeze GIT = "GIT"
GEM = "GEM".freeze GEM = "GEM"
PATH = "PATH".freeze PATH = "PATH"
PLUGIN = "PLUGIN SOURCE".freeze PLUGIN = "PLUGIN SOURCE"
SPECS = " specs:".freeze SPECS = " specs:"
OPTIONS = /^ ([a-z]+): (.*)$/i.freeze OPTIONS = /^ ([a-z]+): (.*)$/i.freeze
SOURCE = [GIT, GEM, PATH, PLUGIN].freeze SOURCE = [GIT, GEM, PATH, PLUGIN].freeze
@ -86,7 +86,7 @@ module Bundler
send("parse_#{@state}", line) send("parse_#{@state}", line)
end end
end end
@specs = @specs.values.sort_by(&:identifier) @specs = @specs.values.sort_by(&:full_name)
rescue ArgumentError => e rescue ArgumentError => e
Bundler.ui.debug(e) Bundler.ui.debug(e)
raise LockfileError, "Your lockfile is unreadable. Run `rm #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` " \ raise LockfileError, "Your lockfile is unreadable. Run `rm #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` " \
@ -199,7 +199,7 @@ module Bundler
@current_spec.source = @current_source @current_spec.source = @current_source
@current_source.add_dependency_names(name) @current_source.add_dependency_names(name)
@specs[@current_spec.identifier] = @current_spec @specs[@current_spec.full_name] = @current_spec
elsif spaces.size == 6 elsif spaces.size == 6
version = version.split(",").map(&:strip) if version version = version.split(",").map(&:strip) if version
dep = Gem::Dependency.new(name, version) dep = Gem::Dependency.new(name, version)

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-ADD" "1" "January 2023" "" "" .TH "BUNDLE\-ADD" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-BINSTUBS" "1" "January 2023" "" "" .TH "BUNDLE\-BINSTUBS" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-CACHE" "1" "January 2023" "" "" .TH "BUNDLE\-CACHE" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application \fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-CHECK" "1" "January 2023" "" "" .TH "BUNDLE\-CHECK" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-CLEAN" "1" "January 2023" "" "" .TH "BUNDLE\-CLEAN" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory \fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-CONFIG" "1" "January 2023" "" "" .TH "BUNDLE\-CONFIG" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options \fBbundle\-config\fR \- Set bundler configuration options

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-CONSOLE" "1" "January 2023" "" "" .TH "BUNDLE\-CONSOLE" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-console\fR \- Deprecated way to open an IRB session with the bundle pre\-loaded \fBbundle\-console\fR \- Deprecated way to open an IRB session with the bundle pre\-loaded

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-DOCTOR" "1" "January 2023" "" "" .TH "BUNDLE\-DOCTOR" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-doctor\fR \- Checks the bundle for common problems \fBbundle\-doctor\fR \- Checks the bundle for common problems

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-EXEC" "1" "January 2023" "" "" .TH "BUNDLE\-EXEC" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-exec\fR \- Execute a command in the context of the bundle \fBbundle\-exec\fR \- Execute a command in the context of the bundle

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-GEM" "1" "January 2023" "" "" .TH "BUNDLE\-GEM" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem \fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-HELP" "1" "January 2023" "" "" .TH "BUNDLE\-HELP" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-help\fR \- Displays detailed help for each subcommand \fBbundle\-help\fR \- Displays detailed help for each subcommand

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-INFO" "1" "January 2023" "" "" .TH "BUNDLE\-INFO" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-info\fR \- Show information for the given gem in your bundle \fBbundle\-info\fR \- Show information for the given gem in your bundle

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-INIT" "1" "January 2023" "" "" .TH "BUNDLE\-INIT" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory \fBbundle\-init\fR \- Generates a Gemfile into the current working directory
@ -18,6 +18,10 @@ Init generates a default [\fBGemfile(5)\fR][Gemfile(5)] in the current working d
\fB\-\-gemspec\fR \fB\-\-gemspec\fR
Use the specified \.gemspec to create the [\fBGemfile(5)\fR][Gemfile(5)] Use the specified \.gemspec to create the [\fBGemfile(5)\fR][Gemfile(5)]
. .
.TP
\fB\-\-gemfile\fR
Use the specified name for the gemfile instead of \fBGemfile\fR
.
.SH "FILES" .SH "FILES"
Included in the default [\fBGemfile(5)\fR][Gemfile(5)] generated is the line \fB# frozen_string_literal: true\fR\. This is a magic comment supported for the first time in Ruby 2\.3\. The presence of this line results in all string literals in the file being implicitly frozen\. Included in the default [\fBGemfile(5)\fR][Gemfile(5)] generated is the line \fB# frozen_string_literal: true\fR\. This is a magic comment supported for the first time in Ruby 2\.3\. The presence of this line results in all string literals in the file being implicitly frozen\.
. .

View file

@ -16,6 +16,8 @@ created [`Gemfile(5)`][Gemfile(5)].
* `--gemspec`: * `--gemspec`:
Use the specified .gemspec to create the [`Gemfile(5)`][Gemfile(5)] Use the specified .gemspec to create the [`Gemfile(5)`][Gemfile(5)]
* `--gemfile`:
Use the specified name for the gemfile instead of `Gemfile`
## FILES ## FILES

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-INJECT" "1" "January 2023" "" "" .TH "BUNDLE\-INJECT" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile \fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-INSTALL" "1" "January 2023" "" "" .TH "BUNDLE\-INSTALL" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-install\fR \- Install the dependencies specified in your Gemfile \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-LIST" "1" "January 2023" "" "" .TH "BUNDLE\-LIST" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-list\fR \- List all the gems in the bundle \fBbundle\-list\fR \- List all the gems in the bundle

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-LOCK" "1" "January 2023" "" "" .TH "BUNDLE\-LOCK" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-lock\fR \- Creates / Updates a lockfile without installing \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-OPEN" "1" "January 2023" "" "" .TH "BUNDLE\-OPEN" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-OUTDATED" "1" "January 2023" "" "" .TH "BUNDLE\-OUTDATED" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-outdated\fR \- List installed gems with newer versions available \fBbundle\-outdated\fR \- List installed gems with newer versions available

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-PLATFORM" "1" "January 2023" "" "" .TH "BUNDLE\-PLATFORM" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-platform\fR \- Displays platform compatibility information \fBbundle\-platform\fR \- Displays platform compatibility information

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-PLUGIN" "1" "January 2023" "" "" .TH "BUNDLE\-PLUGIN" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-plugin\fR \- Manage Bundler plugins \fBbundle\-plugin\fR \- Manage Bundler plugins

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-PRISTINE" "1" "January 2023" "" "" .TH "BUNDLE\-PRISTINE" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition \fBbundle\-pristine\fR \- Restores installed gems to their pristine condition

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-REMOVE" "1" "January 2023" "" "" .TH "BUNDLE\-REMOVE" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-remove\fR \- Removes gems from the Gemfile \fBbundle\-remove\fR \- Removes gems from the Gemfile

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-SHOW" "1" "January 2023" "" "" .TH "BUNDLE\-SHOW" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem \fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-UPDATE" "1" "January 2023" "" "" .TH "BUNDLE\-UPDATE" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-update\fR \- Update your gems to the latest available versions \fBbundle\-update\fR \- Update your gems to the latest available versions

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-VERSION" "1" "January 2023" "" "" .TH "BUNDLE\-VERSION" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-version\fR \- Prints Bundler version information \fBbundle\-version\fR \- Prints Bundler version information

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-VIZ" "1" "January 2023" "" "" .TH "BUNDLE\-VIZ" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile \fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE" "1" "January 2023" "" "" .TH "BUNDLE" "1" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\fR \- Ruby Dependency Management \fBbundle\fR \- Ruby Dependency Management

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "GEMFILE" "5" "January 2023" "" "" .TH "GEMFILE" "5" "February 2023" "" ""
. .
.SH "NAME" .SH "NAME"
\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs \fBGemfile\fR \- A format for describing gem dependencies for Ruby programs

View file

@ -15,7 +15,7 @@ module Bundler
class UnknownSourceError < PluginError; end class UnknownSourceError < PluginError; end
class PluginInstallError < PluginError; end class PluginInstallError < PluginError; end
PLUGIN_FILE_NAME = "plugins.rb".freeze PLUGIN_FILE_NAME = "plugins.rb"
module_function module_function

View file

@ -83,9 +83,12 @@ module Bundler
Bundler.configure_gem_home_and_path(Plugin.root) Bundler.configure_gem_home_and_path(Plugin.root)
Bundler.settings.temporary(:deployment => false, :frozen => false) do
definition = Definition.new(nil, deps, source_list, true) definition = Definition.new(nil, deps, source_list, true)
install_definition(definition) install_definition(definition)
end end
end
# Installs the plugins and deps from the provided specs and returns map of # Installs the plugins and deps from the provided specs and returns map of
# gems to their paths # gems to their paths

View file

@ -29,12 +29,8 @@ module Bundler
@platform = _remote_specification.platform @platform = _remote_specification.platform
end end
def identifier
@__identifier ||= [name, version, @platform.to_s]
end
def full_name def full_name
if @platform == Gem::Platform::RUBY @full_name ||= if @platform == Gem::Platform::RUBY
"#{@name}-#{@version}" "#{@name}-#{@version}"
else else
"#{@name}-#{@version}-#{@platform}" "#{@name}-#{@version}-#{@platform}"
@ -106,7 +102,7 @@ module Bundler
def _remote_specification def _remote_specification
@_remote_specification ||= @spec_fetcher.fetch_spec([@name, @version, @original_platform]) @_remote_specification ||= @spec_fetcher.fetch_spec([@name, @version, @original_platform])
@_remote_specification || raise(GemspecError, "Gemspec data for #{full_name} was" \ @_remote_specification || raise(GemspecError, "Gemspec data for #{full_name} was" \
" missing from the server! Try installing with `--full-index` as a workaround.") " missing from the server!")
end end
def method_missing(method, *args, &blk) def method_missing(method, *args, &blk)

View file

@ -37,7 +37,9 @@ module Bundler
root_version = Resolver::Candidate.new(0) root_version = Resolver::Candidate.new(0)
@all_specs = Hash.new do |specs, name| @all_specs = Hash.new do |specs, name|
specs[name] = source_for(name).specs.search(name).sort_by {|s| [s.version, s.platform.to_s] } specs[name] = source_for(name).specs.search(name).reject do |s|
s.dependencies.any? {|d| d.name == name && !d.requirement.satisfied_by?(s.version) } # ignore versions that depend on themselves incorrectly
end.sort_by {|s| [s.version, s.platform.to_s] }
end end
@sorted_versions = Hash.new do |candidates, package| @sorted_versions = Hash.new do |candidates, package|
@ -55,7 +57,7 @@ module Bundler
{ root_version => root_dependencies } { root_version => root_dependencies }
else else
Hash.new do |versions, version| Hash.new do |versions, version|
versions[version] = to_dependency_hash(version.dependencies, @packages) versions[version] = to_dependency_hash(version.dependencies.reject {|d| d.name == package.name }, @packages)
end end
end end
end end
@ -186,11 +188,6 @@ module Bundler
package_deps = @cached_dependencies[package] package_deps = @cached_dependencies[package]
sorted_versions = @sorted_versions[package] sorted_versions = @sorted_versions[package]
package_deps[version].map do |dep_package, dep_constraint| package_deps[version].map do |dep_package, dep_constraint|
if package == dep_package
cause = PubGrub::Incompatibility::CircularDependency.new(dep_package, dep_constraint.constraint_string)
return [PubGrub::Incompatibility.new([PubGrub::Term.new(dep_constraint, true)], :cause => cause)]
end
low = high = sorted_versions.index(version) low = high = sorted_versions.index(version)
# find version low such that all >= low share the same dep # find version low such that all >= low share the same dep
@ -243,7 +240,7 @@ module Bundler
ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY) ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
groups << Resolver::Candidate.new(version, :specs => ruby_specs) if ruby_specs.any? groups << Resolver::Candidate.new(version, :specs => ruby_specs) if ruby_specs.any?
next groups if platform_specs == ruby_specs next groups if platform_specs == ruby_specs || package.force_ruby_platform?
groups << Resolver::Candidate.new(version, :specs => platform_specs) groups << Resolver::Candidate.new(version, :specs => platform_specs)
@ -302,7 +299,7 @@ module Bundler
end end
def filter_prereleases(specs, package) def filter_prereleases(specs, package)
return specs unless package.ignores_prereleases? return specs unless package.ignores_prereleases? && specs.size > 1
specs.reject {|s| s.version.prerelease? } specs.reject {|s| s.version.prerelease? }
end end

View file

@ -49,10 +49,18 @@ module Bundler
end end
def unlock_names(names) def unlock_names(names)
names.each do |name| indirect_pins = indirect_pins(names)
@base.delete_by_name(name)
@base_requirements.delete(name) if indirect_pins.any?
loosen_names(indirect_pins)
else
pins = pins(names)
if pins.any?
loosen_names(pins)
else
unrestrict_names(names)
end
end end
end end
@ -64,6 +72,30 @@ module Bundler
private private
def indirect_pins(names)
names.select {|name| @base_requirements[name].exact? && @requirements.none? {|dep| dep.name == name } }
end
def pins(names)
names.select {|name| @base_requirements[name].exact? }
end
def loosen_names(names)
names.each do |name|
version = @base_requirements[name].requirements.first[1]
@base_requirements[name] = Gem::Requirement.new(">= #{version}")
@base.delete_by_name(name)
end
end
def unrestrict_names(names)
names.each do |name|
@base_requirements.delete(name)
end
end
def build_base_requirements def build_base_requirements
base_requirements = {} base_requirements = {}
@base.each do |ls| @base.each do |ls|

View file

@ -453,7 +453,7 @@ module Bundler
fetcher = gem_remote_fetcher fetcher = gem_remote_fetcher
fetcher.headers = { "X-Gemfile-Source" => remote.original_uri.to_s } if remote.original_uri fetcher.headers = { "X-Gemfile-Source" => remote.original_uri.to_s } if remote.original_uri
string = fetcher.fetch_path(path) string = fetcher.fetch_path(path)
Bundler.load_marshal(string) Bundler.safe_load_marshal(string)
rescue Gem::RemoteFetcher::FetchError rescue Gem::RemoteFetcher::FetchError
# it's okay for prerelease to fail # it's okay for prerelease to fail
raise unless name == "prerelease_specs" raise unless name == "prerelease_specs"

View file

@ -495,7 +495,7 @@ module Bundler
uri = $2 uri = $2
suffix = $3 suffix = $3
end end
uri = "#{uri}/" unless uri.end_with?("/") uri = URINormalizer.normalize_suffix(uri)
require_relative "vendored_uri" require_relative "vendored_uri"
uri = Bundler::URI(uri) uri = Bundler::URI(uri)
unless uri.absolute? unless uri.absolute?

View file

@ -12,7 +12,10 @@ if Bundler::SharedHelpers.in_bundle?
Bundler.ui.error e.message Bundler.ui.error e.message
Bundler.ui.warn e.backtrace.join("\n") if ENV["DEBUG"] Bundler.ui.warn e.backtrace.join("\n") if ENV["DEBUG"]
if e.is_a?(Bundler::GemNotFound) if e.is_a?(Bundler::GemNotFound)
Bundler.ui.warn "Run `bundle install` to install missing gems." suggested_cmd = "bundle install"
original_gemfile = Bundler.original_env["BUNDLE_GEMFILE"]
suggested_cmd += " --gemfile #{original_gemfile}" if original_gemfile
Bundler.ui.warn "Run `#{suggested_cmd}` to install missing gems."
end end
exit e.status_code exit e.status_code
end end

View file

@ -160,7 +160,7 @@ module Bundler
" (was expecting #{old_deps.map(&:to_s)}, but the real spec has #{new_deps.map(&:to_s)})" " (was expecting #{old_deps.map(&:to_s)}, but the real spec has #{new_deps.map(&:to_s)})"
raise APIResponseMismatchError, raise APIResponseMismatchError,
"Downloading #{spec.full_name} revealed dependencies not in the API or the lockfile (#{extra_deps.join(", ")})." \ "Downloading #{spec.full_name} revealed dependencies not in the API or the lockfile (#{extra_deps.join(", ")})." \
"\nEither installing with `--full-index` or running `bundle update #{spec.name}` should fix the problem." "\nRunning `bundle update #{spec.name}` should fix the problem."
end end
def pretty_dependency(dep) def pretty_dependency(dep)

View file

@ -19,7 +19,7 @@ module Bundler
# Stringify options that could be set as symbols # Stringify options that could be set as symbols
%w[ref branch tag revision].each {|k| options[k] = options[k].to_s if options[k] } %w[ref branch tag revision].each {|k| options[k] = options[k].to_s if options[k] }
@uri = options["uri"] || "" @uri = URINormalizer.normalize_suffix(options["uri"] || "", :trailing_slash => false)
@safe_uri = URICredentialsFilter.credential_filtered_uri(@uri) @safe_uri = URICredentialsFilter.credential_filtered_uri(@uri)
@branch = options["branch"] @branch = options["branch"]
@ref = options["ref"] || options["branch"] || options["tag"] @ref = options["ref"] || options["branch"] || options["tag"]
@ -173,6 +173,7 @@ module Bundler
end end
def install(spec, options = {}) def install(spec, options = {})
return if Bundler.settings[:no_install]
force = options[:force] force = options[:force]
print_using_message "Using #{version_message(spec, options[:previous_spec])} from #{self}" print_using_message "Using #{version_message(spec, options[:previous_spec])} from #{self}"

View file

@ -28,8 +28,9 @@ module Bundler
def initialize(command, path, extra_info = nil) def initialize(command, path, extra_info = nil)
@command = command @command = command
msg = String.new msg = String.new("Git error: command `#{command}`")
msg << "Git error: command `#{command}` in directory #{path} has failed." msg << " in directory #{path}" if path
msg << " has failed."
msg << "\n#{extra_info}" if extra_info msg << "\n#{extra_info}" if extra_info
super msg super msg
end end
@ -139,8 +140,8 @@ module Bundler
out, err, status = capture(command, path) out, err, status = capture(command, path)
return out if status.success? return out if status.success?
if err.include?("couldn't find remote ref") if err.include?("couldn't find remote ref") || err.include?("not our ref")
raise MissingGitRevisionError.new(command_with_no_credentials, path, explicit_ref, credential_filtered_uri) raise MissingGitRevisionError.new(command_with_no_credentials, path, commit || explicit_ref, credential_filtered_uri)
else else
raise GitCommandError.new(command_with_no_credentials, path, err) raise GitCommandError.new(command_with_no_credentials, path, err)
end end
@ -153,9 +154,20 @@ module Bundler
SharedHelpers.filesystem_access(path.dirname) do |p| SharedHelpers.filesystem_access(path.dirname) do |p|
FileUtils.mkdir_p(p) FileUtils.mkdir_p(p)
end end
git_retry "clone", "--bare", "--no-hardlinks", "--quiet", *extra_clone_args, "--", configured_uri, path.to_s
extra_ref command = ["clone", "--bare", "--no-hardlinks", "--quiet", *extra_clone_args, "--", configured_uri, path.to_s]
command_with_no_credentials = check_allowed(command)
Bundler::Retry.new("`#{command_with_no_credentials}`", [MissingGitRevisionError]).attempts do
_, err, status = capture(command, nil)
return extra_ref if status.success?
if err.include?("Could not find remote branch")
raise MissingGitRevisionError.new(command_with_no_credentials, nil, explicit_ref, credential_filtered_uri)
else
raise GitCommandError.new(command_with_no_credentials, path, err)
end
end
end end
def clone_needs_unshallow? def clone_needs_unshallow?
@ -186,8 +198,6 @@ module Bundler
end end
def refspec def refspec
commit = pinned_to_full_sha? ? ref : @revision
if commit if commit
@commit_ref = "refs/#{commit}-sha" @commit_ref = "refs/#{commit}-sha"
return "#{commit}:#{@commit_ref}" return "#{commit}:#{@commit_ref}"
@ -206,6 +216,10 @@ module Bundler
"#{reference}:#{reference}" "#{reference}:#{reference}"
end end
def commit
@commit ||= pinned_to_full_sha? ? ref : @revision
end
def fully_qualified_ref def fully_qualified_ref
if branch if branch
"refs/heads/#{branch}" "refs/heads/#{branch}"
@ -352,6 +366,11 @@ module Bundler
args += ["--single-branch"] args += ["--single-branch"]
args.unshift("--no-tags") if supports_cloning_with_no_tags? args.unshift("--no-tags") if supports_cloning_with_no_tags?
# If there's a locked revision, no need to clone any specific branch
# or tag, since we will end up checking out that locked revision
# anyways.
return args if @revision
args += ["--branch", branch || tag] if branch || tag args += ["--branch", branch || tag] if branch || tag
args args
end end

View file

@ -11,7 +11,7 @@ module Bundler
protected :original_path protected :original_path
DEFAULT_GLOB = "{,*,*/*}.gemspec".freeze DEFAULT_GLOB = "{,*,*/*}.gemspec"
def initialize(options) def initialize(options)
@options = options.dup @options = options.dup

View file

@ -337,8 +337,7 @@ module Bundler
end end
def normalize_uri(uri) def normalize_uri(uri)
uri = uri.to_s uri = URINormalizer.normalize_suffix(uri.to_s)
uri = "#{uri}/" unless %r{/$}.match?(uri)
require_relative "../vendored_uri" require_relative "../vendored_uri"
uri = Bundler::URI(uri) uri = Bundler::URI(uri)
raise ArgumentError, "The source must be an absolute URI. For example:\n" \ raise ArgumentError, "The source must be an absolute URI. For example:\n" \

View file

@ -24,6 +24,7 @@ module Bundler
name = dep[0].name name = dep[0].name
platform = dep[1] platform = dep[1]
incomplete = false
key = [name, platform] key = [name, platform]
next if handled.key?(key) next if handled.key?(key)
@ -36,14 +37,19 @@ module Bundler
specs_for_dep.first.dependencies.each do |d| specs_for_dep.first.dependencies.each do |d|
next if d.type == :development next if d.type == :development
incomplete = true if d.name != "bundler" && lookup[d.name].empty?
deps << [d, dep[1]] deps << [d, dep[1]]
end end
elsif check else
@incomplete_specs += lookup[name] incomplete = true
end
if incomplete && check
@incomplete_specs += lookup[name].any? ? lookup[name] : [LazySpecification.new(name, nil, nil)]
end end
end end
specs specs.uniq
end end
def [](key) def [](key)
@ -95,6 +101,10 @@ module Bundler
end end
def incomplete_ruby_specs?(deps) def incomplete_ruby_specs?(deps)
return false if @specs.empty?
@incomplete_specs = []
self.for(deps, true, [Gem::Platform::RUBY]) self.for(deps, true, [Gem::Platform::RUBY])
@incomplete_specs.any? @incomplete_specs.any?

View file

@ -47,7 +47,7 @@ m = Module.new do
def lockfile def lockfile
lockfile = lockfile =
case File.basename(gemfile) case File.basename(gemfile)
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) when "gems.rb" then gemfile.sub(/\.rb$/, ".locked")
else "#{gemfile}.lock" else "#{gemfile}.lock"
end end
File.expand_path(lockfile) File.expand_path(lockfile)

View file

@ -1,5 +0,0 @@
# frozen_string_literal: true
source "https://rubygems.org"
# gem "rails"

View file

@ -10,7 +10,7 @@ gem "rake", "~> 13.0"
gem "rake-compiler" gem "rake-compiler"
<%- if config[:ext] == 'rust' -%> <%- if config[:ext] == 'rust' -%>
gem "rb_sys" gem "rb_sys", "~> 0.9.63"
<%- end -%> <%- end -%>
<%- end -%> <%- end -%>
<%- if config[:test] -%> <%- if config[:test] -%>

View file

@ -41,6 +41,15 @@ require "standard/rake"
<% if config[:ext] -%> <% if config[:ext] -%>
<% default_task_names.unshift(:compile) -%> <% default_task_names.unshift(:compile) -%>
<% default_task_names.unshift(:clobber) unless config[:ext] == 'rust' -%> <% default_task_names.unshift(:clobber) unless config[:ext] == 'rust' -%>
<% if config[:ext] == 'rust' -%>
require "rb_sys/extensiontask"
task build: :compile
RbSys::ExtensionTask.new(<%= config[:name].inspect %>) do |ext|
ext.lib_dir = "lib/<%= config[:namespaced_path] %>"
end
<% else -%>
require "rake/extensiontask" require "rake/extensiontask"
task build: :compile task build: :compile
@ -48,6 +57,7 @@ task build: :compile
Rake::ExtensionTask.new("<%= config[:underscored_name] %>") do |ext| Rake::ExtensionTask.new("<%= config[:underscored_name] %>") do |ext|
ext.lib_dir = "lib/<%= config[:namespaced_path] %>" ext.lib_dir = "lib/<%= config[:namespaced_path] %>"
end end
<% end -%>
<% end -%> <% end -%>
<% if default_task_names.size == 1 -%> <% if default_task_names.size == 1 -%>

View file

@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
<%- if config[:ext] == 'rust' -%> <%- if config[:ext] == 'rust' -%>
- name: Set up Ruby & Rust - name: Set up Ruby & Rust
uses: oxidize-rb/actions/setup-ruby-and-rust@main uses: oxidize-rb/actions/setup-ruby-and-rust@v1
with: with:
ruby-version: ${{ matrix.ruby }} ruby-version: ${{ matrix.ruby }}
bundler-cache: true bundler-cache: true

View file

@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git. # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir.chdir(__dir__) do spec.files = Dir.chdir(__dir__) do
`git ls-files -z`.split("\x0").reject do |f| `git ls-files -z`.split("\x0").reject do |f|
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)}) (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
end end
end end
spec.bindir = "exe" spec.bindir = "exe"

View file

@ -0,0 +1,23 @@
# frozen_string_literal: true
module Bundler
module URINormalizer
module_function
# Normalizes uri to a consistent version, either with or without trailing
# slash.
#
# TODO: Currently gem sources are locked with a trailing slash, while git
# sources are locked without a trailing slash. This should be normalized but
# the inconsistency is there for now to avoid changing all lockfiles
# including GIT sources. We could normalize this on the next major.
#
def normalize_suffix(uri, trailing_slash: true)
if trailing_slash
uri.end_with?("/") ? uri : "#{uri}/"
else
uri.end_with?("/") ? uri.delete_suffix("/") : uri
end
end
end
end

View file

@ -8,9 +8,6 @@ module Bundler::PubGrub
InvalidDependency = Struct.new(:package, :constraint) do InvalidDependency = Struct.new(:package, :constraint) do
end end
CircularDependency = Struct.new(:package, :constraint) do
end
NoVersions = Struct.new(:constraint) do NoVersions = Struct.new(:constraint) do
end end
@ -66,8 +63,6 @@ module Bundler::PubGrub
"#{terms[0].to_s(allow_every: true)} depends on #{terms[1].invert}" "#{terms[0].to_s(allow_every: true)} depends on #{terms[1].invert}"
when Bundler::PubGrub::Incompatibility::InvalidDependency when Bundler::PubGrub::Incompatibility::InvalidDependency
"#{terms[0].to_s(allow_every: true)} depends on unknown package #{cause.package}" "#{terms[0].to_s(allow_every: true)} depends on unknown package #{cause.package}"
when Bundler::PubGrub::Incompatibility::CircularDependency
"#{terms[0].to_s(allow_every: true)} depends on itself"
when Bundler::PubGrub::Incompatibility::NoVersions when Bundler::PubGrub::Incompatibility::NoVersions
"no versions satisfy #{cause.constraint}" "no versions satisfy #{cause.constraint}"
when Bundler::PubGrub::Incompatibility::ConflictCause when Bundler::PubGrub::Incompatibility::ConflictCause
@ -76,9 +71,13 @@ module Bundler::PubGrub
elsif terms.length == 1 elsif terms.length == 1
term = terms[0] term = terms[0]
if term.positive? if term.positive?
"#{terms[0].to_s(allow_every: true)} is forbidden" if term.constraint.any?
"#{term.package} cannot be used"
else else
"#{terms[0].invert} is required" "#{term.to_s(allow_every: true)} cannot be used"
end
else
"#{term.invert} is required"
end end
else else
if terms.all?(&:positive?) if terms.all?(&:positive?)

View file

@ -19,7 +19,14 @@ module Bundler::PubGrub
version = Gem::Version.new(version) version = Gem::Version.new(version)
@packages[name] ||= {} @packages[name] ||= {}
raise ArgumentError, "#{name} #{version} declared twice" if @packages[name].key?(version) raise ArgumentError, "#{name} #{version} declared twice" if @packages[name].key?(version)
@packages[name][version] = deps @packages[name][version] = clean_deps(name, version, deps)
end
private
# Exclude redundant self-referencing dependencies
def clean_deps(name, version, deps)
deps.reject {|dep_name, req| name == dep_name && Bundler::PubGrub::RubyGems.parse_range(req).include?(version) }
end end
end end

View file

@ -15,15 +15,16 @@ module Bundler::PubGrub
package.hash ^ range.hash package.hash ^ range.hash
end end
def ==(other)
package == other.package &&
range == other.range
end
def eql?(other) def eql?(other)
package.eql?(other.package) && package.eql?(other.package) &&
range.eql?(other.range) range.eql?(other.range)
end end
def ==(other)
package == other.package && range == other.range
end
class << self class << self
def exact(package, version) def exact(package, version)
range = VersionRange.new(min: version, max: version, include_min: true, include_max: true) range = VersionRange.new(min: version, max: version, include_min: true, include_max: true)

View file

@ -19,7 +19,7 @@ module Bundler::PubGrub
true true
end end
def eql? def eql?(other)
other.empty? other.empty?
end end
@ -65,6 +65,7 @@ module Bundler::PubGrub
end end
EMPTY = Empty.new EMPTY = Empty.new
Empty.singleton_class.undef_method(:new)
def self.empty def self.empty
EMPTY EMPTY
@ -88,6 +89,7 @@ module Bundler::PubGrub
def eql?(other) def eql?(other)
if other.is_a?(VersionRange) if other.is_a?(VersionRange)
!other.empty? &&
min.eql?(other.min) && min.eql?(other.min) &&
max.eql?(other.max) && max.eql?(other.max) &&
include_min.eql?(other.include_min) && include_min.eql?(other.include_min) &&

View file

@ -125,6 +125,7 @@ module Bundler::PubGrub
package = next_package_to_try package = next_package_to_try
unsatisfied_term = solution.unsatisfied.find { |t| t.package == package } unsatisfied_term = solution.unsatisfied.find { |t| t.package == package }
version = source.versions_for(package, unsatisfied_term.constraint.range).first version = source.versions_for(package, unsatisfied_term.constraint.range).first
logger.debug { "attempting #{package} #{version}" }
if version.nil? if version.nil?
add_incompatibility source.no_versions_incompatibility_for(package, unsatisfied_term) add_incompatibility source.no_versions_incompatibility_for(package, unsatisfied_term)
@ -148,9 +149,11 @@ module Bundler::PubGrub
end end
unless conflict unless conflict
logger.info { "selecting #{package} #{version}" } logger.info { "selected #{package} #{version}" }
solution.decide(package, version) solution.decide(package, version)
else
logger.info { "conflict: #{conflict.inspect}" }
end end
package package

View file

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

View file

@ -8,7 +8,7 @@
require "rbconfig" require "rbconfig"
module Gem module Gem
VERSION = "3.4.6".freeze VERSION = "3.4.10"
end end
# Must be first since it unloads the prelude from 1.9.2 # Must be first since it unloads the prelude from 1.9.2
@ -824,7 +824,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
def self.env_requirement(gem_name) def self.env_requirement(gem_name)
@env_requirements_by_name ||= {} @env_requirements_by_name ||= {}
@env_requirements_by_name[gem_name] ||= begin @env_requirements_by_name[gem_name] ||= begin
req = ENV["GEM_REQUIREMENT_#{gem_name.upcase}"] || ">= 0".freeze req = ENV["GEM_REQUIREMENT_#{gem_name.upcase}"] || ">= 0"
Gem::Requirement.create(req) Gem::Requirement.create(req)
end end
end end
@ -1301,7 +1301,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
## ##
# Location of Marshal quick gemspecs on remote repositories # Location of Marshal quick gemspecs on remote repositories
MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/".freeze MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/"
autoload :ConfigFile, File.expand_path("rubygems/config_file", __dir__) autoload :ConfigFile, File.expand_path("rubygems/config_file", __dir__)
autoload :Dependency, File.expand_path("rubygems/dependency", __dir__) autoload :Dependency, File.expand_path("rubygems/dependency", __dir__)

View file

@ -21,7 +21,7 @@ module Gem::BundlerVersionFinder
end end
def self.bundle_update_bundler_version def self.bundle_update_bundler_version
return unless File.basename($0) == "bundle".freeze return unless File.basename($0) == "bundle"
return unless "update".start_with?(ARGV.first || " ") return unless "update".start_with?(ARGV.first || " ")
bundler_version = nil bundler_version = nil
update_index = nil update_index = nil

View file

@ -201,13 +201,17 @@ class Gem::Command
# respectively. # respectively.
def get_all_gem_names_and_versions def get_all_gem_names_and_versions
get_all_gem_names.map do |name| get_all_gem_names.map do |name|
extract_gem_name_and_version(name)
end
end
def extract_gem_name_and_version(name) # :nodoc:
if /\A(.*):(#{Gem::Requirement::PATTERN_RAW})\z/ =~ name if /\A(.*):(#{Gem::Requirement::PATTERN_RAW})\z/ =~ name
[$1, $2] [$1, $2]
else else
[name] [name]
end end
end end
end
## ##
# Get a single gem name from the command line. Fail if there is no gem name # Get a single gem name from the command line. Fail if there is no gem name
@ -624,7 +628,7 @@ class Gem::Command
# :stopdoc: # :stopdoc:
HELP = <<-HELP.freeze HELP = <<-HELP
RubyGems is a package manager for Ruby. RubyGems is a package manager for Ruby.
Usage: Usage:

View file

@ -43,6 +43,7 @@ class Gem::CommandManager
:contents, :contents,
:dependency, :dependency,
:environment, :environment,
:exec,
:fetch, :fetch,
:generate_index, :generate_index,
:help, :help,

View file

@ -0,0 +1,248 @@
# frozen_string_literal: true
require_relative "../command"
require_relative "../dependency_installer"
require_relative "../gem_runner"
require_relative "../package"
require_relative "../version_option"
class Gem::Commands::ExecCommand < Gem::Command
include Gem::VersionOption
def initialize
super "exec", "Run a command from a gem", {
version: Gem::Requirement.default,
}
add_version_option
add_prerelease_option "to be installed"
add_option "-g", "--gem GEM", "run the executable from the given gem" do |value, options|
options[:gem_name] = value
end
add_option(:"Install/Update", "--conservative",
"Prefer the most recent installed version, ",
"rather than the latest version overall") do |value, options|
options[:conservative] = true
end
end
def arguments # :nodoc:
"COMMAND the executable command to run"
end
def defaults_str # :nodoc:
"--version '#{Gem::Requirement.default}'"
end
def description # :nodoc:
<<-EOF
The exec command handles installing (if necessary) and running an executable
from a gem, regardless of whether that gem is currently installed.
The exec command can be thought of as a shortcut to running `gem install` and
then the executable from the installed gem.
For example, `gem exec rails new .` will run `rails new .` in the current
directory, without having to manually run `gem install rails`.
Additionally, the exec command ensures the most recent version of the gem
is used (unless run with `--conservative`), and that the gem is not installed
to the same gem path as user-installed gems.
EOF
end
def usage # :nodoc:
"#{program_name} [options --] COMMAND [args]"
end
def execute
gem_paths = { "GEM_HOME" => Gem.paths.home, "GEM_PATH" => Gem.paths.path.join(File::PATH_SEPARATOR), "GEM_SPEC_CACHE" => Gem.paths.spec_cache_dir }.compact
check_executable
print_command
if options[:gem_name] == "gem" && options[:executable] == "gem"
set_gem_exec_install_paths
Gem::GemRunner.new.run options[:args]
return
elsif options[:conservative]
install_if_needed
else
install
activate!
end
load!
ensure
ENV.update(gem_paths) if gem_paths
Gem.clear_paths
end
private
def handle_options(args)
args = add_extra_args(args)
check_deprecated_options(args)
@options = Marshal.load Marshal.dump @defaults # deep copy
parser.order!(args) do |v|
# put the non-option back at the front of the list of arguments
args.unshift(v)
# stop parsing once we hit the first non-option,
# so you can call `gem exec rails --version` and it prints the rails
# version rather than rubygem's
break
end
@options[:args] = args
options[:executable], gem_version = extract_gem_name_and_version(options[:args].shift)
options[:gem_name] ||= options[:executable]
if gem_version
if options[:version].none?
options[:version] = Gem::Requirement.new(gem_version)
else
options[:version].concat [gem_version]
end
end
if options[:prerelease] && !options[:version].prerelease?
if options[:version].none?
options[:version] = Gem::Requirement.default_prerelease
else
options[:version].concat [Gem::Requirement.default_prerelease]
end
end
end
def check_executable
if options[:executable].nil?
raise Gem::CommandLineError,
"Please specify an executable to run (e.g. #{program_name} COMMAND)"
end
end
def print_command
verbose "running #{program_name} with:\n"
opts = options.reject {|_, v| v.nil? || Array(v).empty? }
max_length = opts.map {|k, _| k.size }.max
opts.each do |k, v|
next if v.nil?
verbose "\t#{k.to_s.rjust(max_length)}: #{v}"
end
verbose ""
end
def install_if_needed
activate!
rescue Gem::MissingSpecError
verbose "#{Gem::Dependency.new(options[:gem_name], options[:version])} not available locally, installing from remote"
install
activate!
end
def set_gem_exec_install_paths
home = File.join(Gem.dir, "gem_exec")
ENV["GEM_PATH"] = ([home] + Gem.path).join(File::PATH_SEPARATOR)
ENV["GEM_HOME"] = home
Gem.clear_paths
end
def install
set_gem_exec_install_paths
gem_name = options[:gem_name]
gem_version = options[:version]
install_options = options.merge(
minimal_deps: false,
wrappers: true
)
suppress_always_install do
dep_installer = Gem::DependencyInstaller.new install_options
request_set = dep_installer.resolve_dependencies gem_name, gem_version
verbose "Gems to install:"
request_set.sorted_requests.each do |activation_request|
verbose "\t#{activation_request.full_name}"
end
request_set.install install_options
end
Gem::Specification.reset
rescue Gem::InstallError => e
alert_error "Error installing #{gem_name}:\n\t#{e.message}"
terminate_interaction 1
rescue Gem::GemNotFoundException => e
show_lookup_failure e.name, e.version, e.errors, false
terminate_interaction 2
rescue Gem::UnsatisfiableDependencyError => e
show_lookup_failure e.name, e.version, e.errors, false,
"'#{gem_name}' (#{gem_version})"
terminate_interaction 2
end
def activate!
gem(options[:gem_name], options[:version])
Gem.finish_resolve
verbose "activated #{options[:gem_name]} (#{Gem.loaded_specs[options[:gem_name]].version})"
end
def load!
argv = ARGV.clone
ARGV.replace options[:args]
exe = executable = options[:executable]
contains_executable = Gem.loaded_specs.values.select do |spec|
spec.executables.include?(executable)
end
if contains_executable.any? {|s| s.name == executable }
contains_executable.select! {|s| s.name == executable }
end
if contains_executable.empty?
if (spec = Gem.loaded_specs[executable]) && (exe = spec.executable)
contains_executable << spec
else
alert_error "Failed to load executable `#{executable}`," \
" are you sure the gem `#{options[:gem_name]}` contains it?"
terminate_interaction 1
end
end
if contains_executable.size > 1
alert_error "Ambiguous which gem `#{executable}` should come from: " \
"the options are #{contains_executable.map(&:name)}, " \
"specify one via `-g`"
terminate_interaction 1
end
load Gem.activate_bin_path(contains_executable.first.name, exe, ">= 0.a")
ensure
ARGV.replace argv
end
def suppress_always_install
name = :always_install
cls = ::Gem::Resolver::InstallerSet
method = cls.instance_method(name)
cls.remove_method(name)
cls.define_method(name) { [] }
begin
yield
ensure
cls.remove_method(name)
cls.define_method(name, method)
end
end
end

View file

@ -3,7 +3,7 @@ require_relative "../command"
class Gem::Commands::HelpCommand < Gem::Command class Gem::Commands::HelpCommand < Gem::Command
# :stopdoc: # :stopdoc:
EXAMPLES = <<-EOF.freeze EXAMPLES = <<-EOF
Some examples of 'gem' usage. Some examples of 'gem' usage.
* Install 'rake', either from local directory or remote server: * Install 'rake', either from local directory or remote server:
@ -52,7 +52,7 @@ Some examples of 'gem' usage.
gem update --system gem update --system
EOF EOF
GEM_DEPENDENCIES = <<-EOF.freeze GEM_DEPENDENCIES = <<-EOF
A gem dependencies file allows installation of a consistent set of gems across A gem dependencies file allows installation of a consistent set of gems across
multiple environments. The RubyGems implementation is designed to be multiple environments. The RubyGems implementation is designed to be
compatible with Bundler's Gemfile format. You can see additional compatible with Bundler's Gemfile format. You can see additional
@ -229,7 +229,7 @@ default. This may be overridden with the :development_group option:
EOF EOF
PLATFORMS = <<-'EOF'.freeze PLATFORMS = <<-'EOF'
RubyGems platforms are composed of three parts, a CPU, an OS, and a RubyGems platforms are composed of three parts, a CPU, an OS, and a
version. These values are taken from values in rbconfig.rb. You can view version. These values are taken from values in rbconfig.rb. You can view
your current platform by running `gem environment`. your current platform by running `gem environment`.

View file

@ -34,6 +34,11 @@ class Gem::Commands::PristineCommand < Gem::Command
options[:extensions] = value options[:extensions] = value
end end
add_option("--only-missing-extensions",
"Only restore gems with missing extensions") do |value, options|
options[:only_missing_extensions] = value
end
add_option("--only-executables", add_option("--only-executables",
"Only restore executables") do |value, options| "Only restore executables") do |value, options|
options[:only_executables] = value options[:only_executables] = value
@ -107,6 +112,10 @@ extensions will be restored.
Gem::Specification.select do |spec| Gem::Specification.select do |spec|
spec.extensions && !spec.extensions.empty? spec.extensions && !spec.extensions.empty?
end end
elsif options[:only_missing_extensions]
Gem::Specification.select do |spec|
spec.missing_extensions?
end
else else
get_all_gem_names.sort.map do |gem_name| get_all_gem_names.sort.map do |gem_name|
Gem::Specification.find_all_by_name(gem_name, options[:version]).reverse Gem::Specification.find_all_by_name(gem_name, options[:version]).reverse

View file

@ -125,6 +125,9 @@ that is a dependency of an existing gem. You can use the
def execute def execute
check_version check_version
# Consider only gem specifications installed at `--install-dir`
Gem::Specification.dirs = options[:install_dir] if options[:install_dir]
if options[:all] && !options[:args].empty? if options[:all] && !options[:args].empty?
uninstall_specific uninstall_specific
elsif options[:all] elsif options[:all]

View file

@ -37,9 +37,6 @@ module Kernel
return gem_original_require(path) unless Gem.discover_gems_on_require return gem_original_require(path) unless Gem.discover_gems_on_require
begin begin
if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
monitor_owned = RUBYGEMS_ACTIVATION_MONITOR.mon_owned?
end
RUBYGEMS_ACTIVATION_MONITOR.enter RUBYGEMS_ACTIVATION_MONITOR.enter
path = path.to_path if path.respond_to? :to_path path = path.to_path if path.respond_to? :to_path
@ -163,13 +160,6 @@ module Kernel
end end
raise load_error raise load_error
ensure
if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
if monitor_owned != (ow = RUBYGEMS_ACTIVATION_MONITOR.mon_owned?)
STDERR.puts [$$, Thread.current, $!, $!.backtrace].inspect if $!
raise "CRITICAL: RUBYGEMS_ACTIVATION_MONITOR.owned?: before #{monitor_owned} -> after #{ow}"
end
end
end end
end end

View file

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
module Gem module Gem
DEFAULT_HOST = "https://rubygems.org".freeze DEFAULT_HOST = "https://rubygems.org"
@post_install_hooks ||= [] @post_install_hooks ||= []
@done_installing_hooks ||= [] @done_installing_hooks ||= []
@ -158,7 +158,7 @@ module Gem
# The path to standard location of the user's state directory. # The path to standard location of the user's state directory.
def self.state_home def self.state_home
@data_home ||= (ENV["XDG_STATE_HOME"] || File.join(Gem.user_home, ".local", "state")) @state_home ||= (ENV["XDG_STATE_HOME"] || File.join(Gem.user_home, ".local", "state"))
end end
## ##

View file

@ -299,7 +299,7 @@ class Gem::Dependency
end end
def prioritizes_bundler? def prioritizes_bundler?
name == "bundler".freeze && !specific? name == "bundler" && !specific?
end end
def to_specs def to_specs

View file

@ -143,7 +143,7 @@ module Gem::Deprecate
end end
# Deprecation method to deprecate Rubygems commands # Deprecation method to deprecate Rubygems commands
def rubygems_deprecate_command def rubygems_deprecate_command(version = Gem::Deprecate.next_rubygems_major_version)
class_eval do class_eval do
define_method "deprecated?" do define_method "deprecated?" do
true true
@ -151,7 +151,7 @@ module Gem::Deprecate
define_method "deprecation_warning" do define_method "deprecation_warning" do
msg = [ "#{self.command} command is deprecated", msg = [ "#{self.command} command is deprecated",
". It will be removed in Rubygems #{Gem::Deprecate.next_rubygems_major_version}.\n", ". It will be removed in Rubygems #{version}.\n",
] ]
alert_warning "#{msg.join}" unless Gem::Deprecate.skip alert_warning "#{msg.join}" unless Gem::Deprecate.skip

View file

@ -55,6 +55,23 @@ class Gem::Ext::Builder
end end
end end
def self.ruby
require "shellwords"
# Gem.ruby is quoted if it contains whitespace
cmd = Gem.ruby.shellsplit
# This load_path is only needed when running rubygems test without a proper installation.
# Prepending it in a normal installation will cause problem with order of $LOAD_PATH.
# Therefore only add load_path if it is not present in the default $LOAD_PATH.
load_path = File.expand_path("../..", __dir__)
case load_path
when RbConfig::CONFIG["sitelibdir"], RbConfig::CONFIG["vendorlibdir"], RbConfig::CONFIG["rubylibdir"]
cmd
else
cmd << "-I#{load_path}"
end
end
def self.run(command, results, command_name = nil, dir = Dir.pwd, env = {}) def self.run(command, results, command_name = nil, dir = Dir.pwd, env = {})
verbose = Gem.configuration.really_verbose verbose = Gem.configuration.really_verbose

View file

@ -21,8 +21,7 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
destdir = ENV["DESTDIR"] destdir = ENV["DESTDIR"]
begin begin
require "shellwords" cmd = ruby << File.basename(extension)
cmd = Gem.ruby.shellsplit << "-I" << File.expand_path("../..", __dir__) << File.basename(extension)
cmd.push(*args) cmd.push(*args)
run(cmd, results, class_name, extension_dir) do |s, r| run(cmd, results, class_name, extension_dir) do |s, r|

View file

@ -18,7 +18,7 @@ class Gem::Ext::RakeBuilder < Gem::Ext::Builder
rake = rake.shellsplit rake = rake.shellsplit
else else
begin begin
rake = [Gem.ruby, "-I#{File.expand_path("../..", __dir__)}", "-rrubygems", Gem.bin_path("rake", "rake")] rake = ruby << "-rrubygems" << Gem.bin_path("rake", "rake")
rescue Gem::Exception rescue Gem::Exception
rake = [Gem.default_exec_format % "rake"] rake = [Gem.default_exec_format % "rake"]
end end

View file

@ -208,7 +208,7 @@ class Gem::Package::TarHeader
private private
def calculate_checksum(header) def calculate_checksum(header)
header.unpack("C*").inject {|a, b| a + b } header.sum(0)
end end
def header(checksum = @checksum) def header(checksum = @checksum)

View file

@ -53,39 +53,11 @@ class Gem::Package::TarReader
def each def each
return enum_for __method__ unless block_given? return enum_for __method__ unless block_given?
use_seek = @io.respond_to?(:seek)
until @io.eof? do until @io.eof? do
header = Gem::Package::TarHeader.from @io header = Gem::Package::TarHeader.from @io
return if header.empty? return if header.empty?
entry = Gem::Package::TarReader::Entry.new header, @io entry = Gem::Package::TarReader::Entry.new header, @io
size = entry.header.size
yield entry yield entry
skip = (512 - (size % 512)) % 512
pending = size - entry.bytes_read
if use_seek
begin
# avoid reading if the @io supports seeking
@io.seek pending, IO::SEEK_CUR
pending = 0
rescue Errno::EINVAL
end
end
# if seeking isn't supported or failed
while pending > 0 do
bytes_read = @io.read([pending, 4096].min).size
raise UnexpectedEOF if @io.eof?
pending -= bytes_read
end
@io.read skip # discard trailing zeros
# make sure nobody can use #read, #getc or #rewind anymore
entry.close entry.close
end end
end end

View file

@ -8,6 +8,20 @@
# Class for reading entries out of a tar file # Class for reading entries out of a tar file
class Gem::Package::TarReader::Entry class Gem::Package::TarReader::Entry
##
# Creates a new tar entry for +header+ that will be read from +io+
# If a block is given, the entry is yielded and then closed.
def self.open(header, io, &block)
entry = new header, io
return entry unless block_given?
begin
yield entry
ensure
entry.close
end
end
## ##
# Header for this tar entry # Header for this tar entry
@ -21,6 +35,7 @@ class Gem::Package::TarReader::Entry
@header = header @header = header
@io = io @io = io
@orig_pos = @io.pos @orig_pos = @io.pos
@end_pos = @orig_pos + @header.size
@read = 0 @read = 0
end end
@ -39,7 +54,14 @@ class Gem::Package::TarReader::Entry
# Closes the tar entry # Closes the tar entry
def close def close
return if closed?
# Seek to the end of the entry if it wasn't fully read
seek(0, IO::SEEK_END)
# discard trailing zeros
skip = (512 - (@header.size % 512)) % 512
@io.read(skip)
@closed = true @closed = true
nil
end end
## ##
@ -117,6 +139,14 @@ class Gem::Package::TarReader::Entry
bytes_read bytes_read
end end
##
# Seek to the position in the tar entry
def pos=(new_pos)
seek(new_pos, IO::SEEK_SET)
new_pos
end
def size def size
@header.size @header.size
end end
@ -130,9 +160,10 @@ class Gem::Package::TarReader::Entry
def read(len = nil) def read(len = nil)
check_closed check_closed
return nil if @read >= @header.size
len ||= @header.size - @read len ||= @header.size - @read
return nil if len > 0 && @read >= @header.size
max_read = [len, @header.size - @read].min max_read = [len, @header.size - @read].min
ret = @io.read max_read ret = @io.read max_read
@ -144,9 +175,10 @@ class Gem::Package::TarReader::Entry
def readpartial(maxlen = nil, outbuf = "".b) def readpartial(maxlen = nil, outbuf = "".b)
check_closed check_closed
raise EOFError if @read >= @header.size
maxlen ||= @header.size - @read maxlen ||= @header.size - @read
raise EOFError if maxlen > 0 && @read >= @header.size
max_read = [maxlen, @header.size - @read].min max_read = [maxlen, @header.size - @read].min
@io.readpartial(max_read, outbuf) @io.readpartial(max_read, outbuf)
@ -155,13 +187,62 @@ class Gem::Package::TarReader::Entry
outbuf outbuf
end end
##
# Seeks to +offset+ bytes into the tar file entry
# +whence+ can be IO::SEEK_SET, IO::SEEK_CUR, or IO::SEEK_END
def seek(offset, whence = IO::SEEK_SET)
check_closed
new_pos =
case whence
when IO::SEEK_SET then @orig_pos + offset
when IO::SEEK_CUR then @io.pos + offset
when IO::SEEK_END then @end_pos + offset
else
raise ArgumentError, "invalid whence"
end
if new_pos < @orig_pos
new_pos = @orig_pos
elsif new_pos > @end_pos
new_pos = @end_pos
end
pending = new_pos - @io.pos
if @io.respond_to?(:seek)
begin
# avoid reading if the @io supports seeking
@io.seek new_pos, IO::SEEK_SET
pending = 0
rescue Errno::EINVAL
end
end
# if seeking isn't supported or failed
# negative seek requires that we rewind and read
if pending < 0
@io.rewind
pending = new_pos
end
while pending > 0 do
size_read = @io.read([pending, 4096].min).size
raise UnexpectedEOF if @io.eof?
pending -= size_read
end
@read = @io.pos - @orig_pos
0
end
## ##
# Rewinds to the beginning of the tar file entry # Rewinds to the beginning of the tar file entry
def rewind def rewind
check_closed check_closed
seek(0, IO::SEEK_SET)
@io.pos = @orig_pos
@read = 0
end end
end end

View file

@ -235,11 +235,11 @@ class Gem::Platform
# A pure-Ruby gem that may use Gem::Specification#extensions to build # A pure-Ruby gem that may use Gem::Specification#extensions to build
# binary files. # binary files.
RUBY = "ruby".freeze RUBY = "ruby"
## ##
# A platform-specific gem that is built for the packaging Ruby's platform. # A platform-specific gem that is built for the packaging Ruby's platform.
# This will be replaced with Gem::Platform::local. # This will be replaced with Gem::Platform::local.
CURRENT = "current".freeze CURRENT = "current"
end end

View file

@ -435,7 +435,6 @@ Gem dependencies file #{@path} requires #{name} more than once.
reference ||= ref reference ||= ref
reference ||= branch reference ||= branch
reference ||= tag reference ||= tag
reference ||= "master"
if ref && branch if ref && branch
warn <<-WARNING warn <<-WARNING

View file

@ -22,7 +22,7 @@ class Gem::Requirement
SOURCE_SET_REQUIREMENT = Struct.new(:for_lockfile).new "!" # :nodoc: SOURCE_SET_REQUIREMENT = Struct.new(:for_lockfile).new "!" # :nodoc:
quoted = OPS.keys.map {|k| Regexp.quote k }.join "|" quoted = OPS.keys.map {|k| Regexp.quote k }.join "|"
PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*".freeze # :nodoc: PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*" # :nodoc:
## ##
# A regular expression that matches a requirement # A regular expression that matches a requirement

View file

@ -32,7 +32,7 @@ class Gem::Resolver::Stats
@iterations += 1 @iterations += 1
end end
PATTERN = "%20s: %d\n".freeze PATTERN = "%20s: %d\n"
def display def display
$stdout.puts "=== Resolver Statistics ===" $stdout.puts "=== Resolver Statistics ==="

View file

@ -53,7 +53,7 @@ class Gem::Source::Git < Gem::Source
@uri = Gem::Uri.parse(repository) @uri = Gem::Uri.parse(repository)
@name = name @name = name
@repository = repository @repository = repository
@reference = reference @reference = reference || "HEAD"
@need_submodules = submodules @need_submodules = submodules
@remote = true @remote = true

View file

@ -338,7 +338,7 @@ class Gem::Specification < Gem::BasicSpecification
# The simplest way is to specify the standard SPDX ID # The simplest way is to specify the standard SPDX ID
# https://spdx.org/licenses/ for the license. # https://spdx.org/licenses/ for the license.
# Ideally, you should pick one that is OSI (Open Source Initiative) # Ideally, you should pick one that is OSI (Open Source Initiative)
# http://opensource.org/licenses/alphabetical approved. # https://opensource.org/licenses/ approved.
# #
# The most commonly used OSI-approved licenses are MIT and Apache-2.0. # The most commonly used OSI-approved licenses are MIT and Apache-2.0.
# GitHub also provides a license picker at http://choosealicense.com/. # GitHub also provides a license picker at http://choosealicense.com/.
@ -1021,6 +1021,12 @@ class Gem::Specification < Gem::BasicSpecification
Gem::Dependency.new(name, *requirements).to_spec Gem::Dependency.new(name, *requirements).to_spec
end end
##
# Find the best specification matching a +full_name+.
def self.find_by_full_name(full_name)
stubs.find {|s| s.full_name == full_name }&.to_spec
end
## ##
# Return the best specification that contains the file matching +path+. # Return the best specification that contains the file matching +path+.
@ -1606,6 +1612,8 @@ class Gem::Specification < Gem::BasicSpecification
def build_extensions # :nodoc: def build_extensions # :nodoc:
return if extensions.empty? return if extensions.empty?
return if default_gem? return if default_gem?
# we need to fresh build when same name and version of default gems
return if self.class.find_by_full_name(full_name)&.default_gem?
return if File.exist? gem_build_complete_path return if File.exist? gem_build_complete_path
return if !File.writable?(base_dir) return if !File.writable?(base_dir)
return if !File.exist?(File.join(base_dir, "extensions")) return if !File.exist?(File.join(base_dir, "extensions"))

View file

@ -173,6 +173,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
end end
## ##
# Checks that the gem does not depend on itself.
# Checks that dependencies use requirements as we recommend. Warnings are # Checks that dependencies use requirements as we recommend. Warnings are
# issued when dependencies are open-ended or overly strict for semantic # issued when dependencies are open-ended or overly strict for semantic
# versioning. # versioning.
@ -180,6 +181,10 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
def validate_dependencies # :nodoc: def validate_dependencies # :nodoc:
warning_messages = [] warning_messages = []
@specification.dependencies.each do |dep| @specification.dependencies.each do |dep|
if dep.name == @specification.name # warn on self reference
warning_messages << "Self referencing dependency is unnecessary and strongly discouraged."
end
prerelease_dep = dep.requirements_list.any? do |req| prerelease_dep = dep.requirements_list.any? do |req|
Gem::Requirement.new(req).prerelease? Gem::Requirement.new(req).prerelease?
end end

View file

@ -6,10 +6,10 @@
class Gem::StubSpecification < Gem::BasicSpecification class Gem::StubSpecification < Gem::BasicSpecification
# :nodoc: # :nodoc:
PREFIX = "# stub: ".freeze PREFIX = "# stub: "
# :nodoc: # :nodoc:
OPEN_MODE = "r:UTF-8:-".freeze OPEN_MODE = "r:UTF-8:-"
class StubLine # :nodoc: all class StubLine # :nodoc: all
attr_reader :name, :version, :platform, :require_paths, :extensions, attr_reader :name, :version, :platform, :require_paths, :extensions,
@ -19,9 +19,9 @@ class Gem::StubSpecification < Gem::BasicSpecification
# These are common require paths. # These are common require paths.
REQUIRE_PATHS = { # :nodoc: REQUIRE_PATHS = { # :nodoc:
"lib" => "lib".freeze, "lib" => "lib",
"test" => "test".freeze, "test" => "test",
"ext" => "ext".freeze, "ext" => "ext",
}.freeze }.freeze
# These are common require path lists. This hash is used to optimize # These are common require path lists. This hash is used to optimize
@ -33,7 +33,7 @@ class Gem::StubSpecification < Gem::BasicSpecification
}.freeze }.freeze
def initialize(data, extensions) def initialize(data, extensions)
parts = data[PREFIX.length..-1].split(" ".freeze, 4) parts = data[PREFIX.length..-1].split(" ", 4)
@name = parts[0].freeze @name = parts[0].freeze
@version = if Gem::Version.correct?(parts[1]) @version = if Gem::Version.correct?(parts[1])
Gem::Version.new(parts[1]) Gem::Version.new(parts[1])
@ -50,7 +50,7 @@ class Gem::StubSpecification < Gem::BasicSpecification
end end
path_list = parts.last path_list = parts.last
@require_paths = REQUIRE_PATH_LIST[path_list] || path_list.split("\0".freeze).map! do |x| @require_paths = REQUIRE_PATH_LIST[path_list] || path_list.split("\0").map! do |x|
REQUIRE_PATHS[x] || x REQUIRE_PATHS[x] || x
end end
end end

Some files were not shown because too many files have changed in this diff Show more