Sync latest development version of bundler & rubygems

This commit is contained in:
David Rodríguez 2021-02-01 16:17:16 +01:00 коммит произвёл Hiroshi SHIBATA
Родитель 2ab6b7a751
Коммит 53468cc111
161 изменённых файлов: 2544 добавлений и 1016 удалений

Просмотреть файл

@ -63,7 +63,6 @@ module Bundler
autoload :Resolver, File.expand_path("bundler/resolver", __dir__)
autoload :Retry, File.expand_path("bundler/retry", __dir__)
autoload :RubyDsl, File.expand_path("bundler/ruby_dsl", __dir__)
autoload :RubyGemsGemInstaller, File.expand_path("bundler/rubygems_gem_installer", __dir__)
autoload :RubyVersion, File.expand_path("bundler/ruby_version", __dir__)
autoload :Runtime, File.expand_path("bundler/runtime", __dir__)
autoload :Settings, File.expand_path("bundler/settings", __dir__)
@ -441,7 +440,7 @@ EOF
end
def local_platform
return Gem::Platform::RUBY if settings[:force_ruby_platform]
return Gem::Platform::RUBY if settings[:force_ruby_platform] || Gem.platforms == [Gem::Platform::RUBY]
Gem::Platform.local
end

Просмотреть файл

@ -586,6 +586,7 @@ module Bundler
method_option :git, :type => :boolean, :default => true, :desc => "Initialize a git repo inside your library."
method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`."
method_option :rubocop, :type => :boolean, :desc => "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`."
method_option :changelog, :type => :boolean, :desc => "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`."
method_option :test, :type => :string, :lazy_default => Bundler.settings["gem.test"] || "", :aliases => "-t", :banner => "Use the specified test framework for your library",
:desc => "Generate a test directory for your library, either rspec, minitest or test-unit. Set a default with `bundle config set --global gem.test (rspec|minitest|test-unit)`."
method_option :ci, :type => :string, :lazy_default => Bundler.settings["gem.ci"] || "",

Просмотреть файл

@ -30,6 +30,7 @@ module Bundler
require_relative "install"
options = self.options.dup
options["local"] = false if Bundler.settings[:cache_all_platforms]
options["no-cache"] = true
Bundler::CLI::Install.new(options).run
end

Просмотреть файл

@ -39,11 +39,11 @@ module Bundler
constant_name = name.gsub(/-[_-]*(?![_-]|$)/) { "::" }.gsub(/([_-]+|(::)|^)(.|$)/) { $2.to_s + $3.upcase }
constant_array = constant_name.split("::")
git_installed = Bundler.git_present?
use_git = Bundler.git_present? && options[:git]
git_author_name = git_installed ? `git config user.name`.chomp : ""
github_username = git_installed ? `git config github.user`.chomp : ""
git_user_email = git_installed ? `git config user.email`.chomp : ""
git_author_name = use_git ? `git config user.name`.chomp : ""
github_username = use_git ? `git config github.user`.chomp : ""
git_user_email = use_git ? `git config user.email`.chomp : ""
config = {
:name => name,
@ -58,7 +58,9 @@ module Bundler
:ext => options[:ext],
:exe => options[:exe],
:bundler_version => bundler_dependency_version,
:git => use_git,
:github_username => github_username.empty? ? "[USERNAME]" : github_username,
:required_ruby_version => Gem.ruby_version < Gem::Version.new("2.4.a") ? "2.3.0" : "2.4.0",
}
ensure_safe_gem_name(name, constant_array)
@ -78,7 +80,7 @@ module Bundler
bin/setup
]
templates.merge!("gitignore.tt" => ".gitignore") if Bundler.git_present?
templates.merge!("gitignore.tt" => ".gitignore") if use_git
if test_framework = ask_and_set_test_framework
config[:test] = test_framework
@ -141,12 +143,25 @@ module Bundler
templates.merge!("CODE_OF_CONDUCT.md.tt" => "CODE_OF_CONDUCT.md")
end
if ask_and_set(:changelog, "Do you want to include a changelog?",
"A changelog is a file which contains a curated, chronologically ordered list of notable " \
"changes for each version of a project. To make it easier for users and contributors to" \
" see precisely what notable changes have been made between each release (or version) of" \
" the project. Whether consumers or developers, the end users of software are" \
" human beings who care about what's in the software. When the software changes, people " \
"want to know why and how. see https://keepachangelog.com")
config[:changelog] = true
Bundler.ui.info "Changelog enabled in config"
templates.merge!("CHANGELOG.md.tt" => "CHANGELOG.md")
end
if ask_and_set(:rubocop, "Do you want to add rubocop as a dependency for gems you generate?",
"RuboCop is a static code analyzer that has out-of-the-box rules for many " \
"of the guidelines in the community style guide. " \
"For more information, see the RuboCop docs (https://docs.rubocop.org/en/stable/) " \
"and the Ruby Style Guides (https://github.com/rubocop-hq/ruby-style-guide).")
config[:rubocop] = true
config[:rubocop_version] = Gem.ruby_version < Gem::Version.new("2.4.a") ? "0.81.0" : "1.7"
Bundler.ui.info "RuboCop enabled in config"
templates.merge!("rubocop.yml.tt" => ".rubocop.yml")
end
@ -161,24 +176,31 @@ module Bundler
)
end
if File.exist?(target) && !File.directory?(target)
Bundler.ui.error "Couldn't create a new gem named `#{gem_name}` because there's an existing file named `#{gem_name}`."
exit Bundler::BundlerError.all_errors[Bundler::GenericSystemCallError]
end
if use_git
Bundler.ui.info "Initializing git repo in #{target}"
`git init #{target}`
config[:git_default_branch] = File.read("#{target}/.git/HEAD").split("/").last.chomp
end
templates.each do |src, dst|
destination = target.join(dst)
SharedHelpers.filesystem_access(destination) do
thor.template("newgem/#{src}", destination, config)
end
thor.template("newgem/#{src}", destination, config)
end
executables.each do |file|
SharedHelpers.filesystem_access(target.join(file)) do |path|
executable = (path.stat.mode | 0o111)
path.chmod(executable)
end
path = target.join(file)
executable = (path.stat.mode | 0o111)
path.chmod(executable)
end
if Bundler.git_present? && options[:git]
Bundler.ui.info "Initializing git repo in #{target}"
if use_git
Dir.chdir(target) do
`git init`
`git add .`
end
end
@ -188,8 +210,6 @@ module Bundler
Bundler.ui.info "Gem '#{name}' was successfully created. " \
"For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html"
rescue Errno::EEXIST => e
raise GenericSystemCallError.new(e, "There was a conflict while creating the new gem.")
end
private

Просмотреть файл

@ -1,8 +1,6 @@
# frozen_string_literal: true
require_relative "../vendored_fileutils"
require "stringio"
require "zlib"
module Bundler
class CompactIndexClient
@ -45,24 +43,18 @@ module Bundler
else
"bytes=#{local_temp_path.size}-"
end
else
# Fastly ignores Range when Accept-Encoding: gzip is set
headers["Accept-Encoding"] = "gzip"
end
response = @fetcher.call(remote_path, headers)
return nil if response.is_a?(Net::HTTPNotModified)
content = response.body
if response["Content-Encoding"] == "gzip"
content = Zlib::GzipReader.new(StringIO.new(content)).read
end
SharedHelpers.filesystem_access(local_temp_path) do
if response.is_a?(Net::HTTPPartialContent) && local_temp_path.size.nonzero?
local_temp_path.open("a") {|f| f << slice_body(content, 1..-1) }
else
local_temp_path.open("w") {|f| f << content }
local_temp_path.open("wb") {|f| f << content }
end
end

Просмотреть файл

@ -1,7 +1,6 @@
# frozen_string_literal: true
require_relative "lockfile_parser"
require "set"
module Bundler
class Definition
@ -88,11 +87,7 @@ module Bundler
@lockfile_contents = Bundler.read_file(lockfile)
@locked_gems = LockfileParser.new(@lockfile_contents)
@locked_platforms = @locked_gems.platforms
if Bundler.settings[:force_ruby_platform]
@platforms = [Gem::Platform::RUBY]
else
@platforms = @locked_platforms.dup
end
@platforms = @locked_platforms.dup
@locked_bundler_version = @locked_gems.bundler_version
@locked_ruby_version = @locked_gems.ruby_version
@ -264,23 +259,18 @@ module Bundler
def resolve
@resolve ||= begin
last_resolve = converge_locked_specs
resolve =
if Bundler.frozen_bundle?
Bundler.ui.debug "Frozen, using resolution from the lockfile"
last_resolve
elsif !unlocking? && nothing_changed?
Bundler.ui.debug("Found no changes, using resolution from the lockfile")
last_resolve
else
# Run a resolve against the locally available gems
Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
end
# filter out gems that _can_ be installed on multiple platforms, but don't need
# to be
resolve.for(expand_dependencies(dependencies, true), [], false, false, false)
if Bundler.frozen_bundle?
Bundler.ui.debug "Frozen, using resolution from the lockfile"
last_resolve
elsif !unlocking? && nothing_changed?
Bundler.ui.debug("Found no changes, using resolution from the lockfile")
last_resolve
else
# Run a resolve against the locally available gems
Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
end
end
end
@ -611,7 +601,7 @@ module Bundler
deps_for_source = @dependencies.select {|s| s.source == source }
locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
Set.new(deps_for_source) != Set.new(locked_deps_for_source)
deps_for_source.uniq.sort != locked_deps_for_source.sort
end
def specs_for_source_changed?(source)
@ -673,19 +663,20 @@ module Bundler
def converge_rubygems_sources
return false if Bundler.feature_flag.disable_multisource?
changes = false
# Get the RubyGems sources from the Gemfile.lock
locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
return false if locked_gem_sources.empty?
# Get the RubyGems remotes from the Gemfile
actual_remotes = sources.rubygems_remotes
return false if actual_remotes.empty?
changes = false
# If there is a RubyGems source in both
if !locked_gem_sources.empty? && !actual_remotes.empty?
locked_gem_sources.each do |locked_gem|
# Merge the remotes from the Gemfile into the Gemfile.lock
changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
end
locked_gem_sources.each do |locked_gem|
# Merge the remotes from the Gemfile into the Gemfile.lock
changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
end
changes
@ -825,11 +816,6 @@ module Bundler
# commonly happens if the version changed in the gemspec
next unless new_spec
new_runtime_deps = new_spec.dependencies.select {|d| d.type != :development }
old_runtime_deps = s.dependencies.select {|d| d.type != :development }
# If the dependencies of the path source have changed and locked spec can't satisfy new dependencies, unlock it
next unless new_runtime_deps.sort == old_runtime_deps.sort || new_runtime_deps.all? {|d| satisfies_locked_spec?(d) }
s.dependencies.replace(new_spec.dependencies)
end
@ -896,7 +882,7 @@ module Bundler
dependencies.each do |dep|
dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
next unless remote || dep.current_platform?
target_platforms = dep.gem_platforms(remote ? Resolver.sort_platforms(@platforms) : [generic_local_platform])
target_platforms = dep.gem_platforms(remote ? @platforms : [generic_local_platform])
deps += expand_dependency_with_platforms(dep, target_platforms)
end
deps
@ -904,7 +890,7 @@ module Bundler
def expand_dependency_with_platforms(dep, platforms)
platforms.map do |p|
DepProxy.new(dep, p)
DepProxy.get_proxy(dep, p)
end
end
@ -915,29 +901,18 @@ module Bundler
# Record the specs available in each gem's source, so that those
# specs will be available later when the resolver knows where to
# look for that gemspec (or its dependencies)
default = sources.default_source
source_requirements = { :default => default }
default = nil unless Bundler.feature_flag.disable_multisource?
dependencies.each do |dep|
next unless source = dep.source || default
source_requirements[dep.name] = source
end
source_requirements = { :default => sources.default_source }.merge(dependency_source_requirements)
metadata_dependencies.each do |dep|
source_requirements[dep.name] = sources.metadata_source
end
source_requirements[:global] = index unless Bundler.feature_flag.disable_multisource?
source_requirements[:default_bundler] = source_requirements["bundler"] || source_requirements[:default]
source_requirements["bundler"] = sources.metadata_source # needs to come last to override
source_requirements
end
def pinned_spec_names(skip = nil)
pinned_names = []
default = Bundler.feature_flag.disable_multisource? && sources.default_source
@dependencies.each do |dep|
next unless dep_source = dep.source || default
next if dep_source == skip
pinned_names << dep.name
end
pinned_names
dependency_source_requirements.reject {|_, source| source == skip }.keys
end
def requested_groups
@ -984,7 +959,7 @@ module Bundler
next requirements if @locked_gems.dependencies[name] != dependency
next requirements if dependency.source.is_a?(Source::Path)
dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
requirements[name] = DepProxy.new(dep, locked_spec.platform)
requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform)
requirements
end.values
end
@ -994,5 +969,17 @@ module Bundler
Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
end
def dependency_source_requirements
@dependency_source_requirements ||= begin
source_requirements = {}
default = sources.default_source
dependencies.each do |dep|
dep_source = dep.source || default
source_requirements[dep.name] = dep_source
end
source_requirements
end
end
end
end

Просмотреть файл

@ -4,19 +4,18 @@ module Bundler
class DepProxy
attr_reader :__platform, :dep
@proxies = {}
def self.get_proxy(dep, platform)
@proxies[[dep, platform]] ||= new(dep, platform).freeze
end
def initialize(dep, platform)
@dep = dep
@__platform = platform
end
def hash
@hash ||= [dep, __platform].hash
end
def ==(other)
return false if other.class != self.class
dep == other.dep && __platform == other.__platform
end
private_class_method :new
alias_method :eql?, :==
@ -39,6 +38,14 @@ module Bundler
s
end
def dup
raise NoMethodError.new("DepProxy cannot be duplicated")
end
def clone
raise NoMethodError.new("DepProxy cannot be cloned")
end
private
def method_missing(*args, &blk)

Просмотреть файл

@ -24,6 +24,9 @@ module Bundler
def initialize
@source = nil
@sources = SourceList.new
@global_rubygems_sources = []
@git_sources = {}
@dependencies = []
@groups = []
@ -45,6 +48,7 @@ module Bundler
@gemfiles << expanded_gemfile_path
contents ||= Bundler.read_file(@gemfile.to_s)
instance_eval(contents.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1)
check_primary_source_safety
rescue Exception => e # rubocop:disable Lint/RescueException
message = "There was an error " \
"#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@ -164,8 +168,7 @@ module Bundler
elsif block_given?
with_source(@sources.add_rubygems_source("remotes" => source), &blk)
else
check_primary_source_safety(@sources)
@sources.global_rubygems_source = source
@global_rubygems_sources << source
end
end
@ -183,24 +186,14 @@ module Bundler
end
def path(path, options = {}, &blk)
unless block_given?
msg = "You can no longer specify a path source by itself. Instead, \n" \
"either use the :path option on a gem, or specify the gems that \n" \
"bundler should find in the path source by passing a block to \n" \
"the path method, like: \n\n" \
" path 'dir/containing/rails' do\n" \
" gem 'rails'\n" \
" end\n\n"
raise DeprecatedError, msg if Bundler.feature_flag.disable_multisource?
SharedHelpers.major_deprecation(2, msg.strip)
end
source_options = normalize_hash(options).merge(
"path" => Pathname.new(path),
"root_path" => gemfile_root,
"gemspec" => gemspecs.find {|g| g.name == options["name"] }
)
source_options["global"] = true unless block_given?
source = @sources.add_path_source(source_options)
with_source(source, &blk)
end
@ -279,6 +272,11 @@ module Bundler
raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile"
end
def check_primary_source_safety
check_path_source_safety
check_rubygems_source_safety
end
private
def add_git_sources
@ -440,17 +438,33 @@ repo_name ||= user_name
end
end
def check_primary_source_safety(source_list)
return if source_list.rubygems_primary_remotes.empty? && source_list.global_rubygems_source.nil?
def check_path_source_safety
return if @sources.global_path_source.nil?
msg = "You can no longer specify a path source by itself. Instead, \n" \
"either use the :path option on a gem, or specify the gems that \n" \
"bundler should find in the path source by passing a block to \n" \
"the path method, like: \n\n" \
" path 'dir/containing/rails' do\n" \
" gem 'rails'\n" \
" end\n\n"
SharedHelpers.major_deprecation(2, msg.strip)
end
def check_rubygems_source_safety
@sources.global_rubygems_source = @global_rubygems_sources.shift
return if @global_rubygems_sources.empty?
@global_rubygems_sources.each do |source|
@sources.add_rubygems_remote(source)
end
if Bundler.feature_flag.disable_multisource?
msg = "This Gemfile contains multiple primary sources. " \
"Each source after the first must include a block to indicate which gems " \
"should come from that source"
unless Bundler.feature_flag.bundler_2_mode?
msg += ". To downgrade this error to a warning, run " \
"`bundle config unset disable_multisource`"
end
"should come from that source. To downgrade this error to a warning, run " \
"`bundle config unset disable_multisource`"
raise GemfileEvalError, msg
else
Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \

Просмотреть файл

@ -27,7 +27,6 @@ module Bundler
(1..10).each {|v| define_method("bundler_#{v}_mode?") { major_version >= v } }
settings_flag(:allow_bundler_dependency_conflicts) { bundler_3_mode? }
settings_flag(:allow_offline_install) { bundler_3_mode? }
settings_flag(:auto_clean_without_path) { bundler_3_mode? }
settings_flag(:cache_all) { bundler_3_mode? }

Просмотреть файл

@ -137,7 +137,6 @@ module Bundler
end
specs.each do |name, version, platform, dependencies, metadata|
next if name == "bundler"
spec = if dependencies
EndpointSpecification.new(name, version, platform, dependencies, metadata)
else

Просмотреть файл

@ -116,19 +116,21 @@ module Bundler
def git_push(remote = nil)
remote ||= default_remote
perform_git_push remote
perform_git_push "#{remote} refs/heads/#{current_branch}"
perform_git_push "#{remote} refs/tags/#{version_tag}"
Bundler.ui.confirm "Pushed git commits and release tag."
end
def default_remote
remote_for_branch, status = sh_with_status(%W[git config --get branch.#{current_branch}.remote])
return "origin" unless status.success?
remote_for_branch.strip
end
def current_branch
# We can replace this with `git branch --show-current` once we drop support for git < 2.22.0
current_branch = sh(%w[git rev-parse --abbrev-ref HEAD]).gsub(%r{\Aheads/}, "").strip
remote_for_branch = sh(%W[git config --get branch.#{current_branch}.remote]).strip
return "origin" if remote_for_branch.empty?
remote_for_branch
sh(%w[git rev-parse --abbrev-ref HEAD]).gsub(%r{\Aheads/}, "").strip
end
def allowed_push_host

Просмотреть файл

@ -81,8 +81,8 @@ module Bundler
sort_dep_specs(spec_groups, locked_spec)
end.tap do |specs|
if DEBUG
warn before_result
warn " after sort_versions: #{debug_format_result(dep, specs).inspect}"
puts before_result
puts " after sort_versions: #{debug_format_result(dep, specs).inspect}"
end
end
end

Просмотреть файл

@ -1,7 +1,5 @@
# frozen_string_literal: true
require "set"
module Bundler
class Index
include Enumerable
@ -65,11 +63,14 @@ module Bundler
def unsorted_search(query, base)
results = local_search(query, base)
seen = results.map(&:full_name).to_set unless @sources.empty?
seen = results.map(&:full_name).uniq unless @sources.empty?
@sources.each do |source|
source.unsorted_search(query, base).each do |spec|
results << spec if seen.add?(spec.full_name)
next if seen.include?(spec.full_name)
seen << spec.full_name
results << spec
end
end
@ -170,7 +171,7 @@ module Bundler
def dependencies_eql?(spec, other_spec)
deps = spec.dependencies.select {|d| d.type != :development }
other_deps = other_spec.dependencies.select {|d| d.type != :development }
Set.new(deps) == Set.new(other_deps)
deps.sort == other_deps.sort
end
def add_source(index)

Просмотреть файл

@ -50,6 +50,7 @@ def gemfile(install = false, options = {}, &gemfile)
Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
builder = Bundler::Dsl.new
builder.instance_eval(&gemfile)
builder.check_primary_source_safety
Bundler.settings.temporary(:frozen => false) do
definition = builder.to_definition(nil, true)

Просмотреть файл

@ -82,7 +82,6 @@ module Bundler
if resolve_if_needed(options)
ensure_specs_are_compatible!
warn_on_incompatible_bundler_deps
load_plugins
options.delete(:jobs)
else
@ -90,6 +89,8 @@ module Bundler
end
install(options)
Gem::Specification.reset # invalidate gem specification cache so that installed gems are immediately available
lock unless Bundler.frozen_bundle?
Standalone.new(options[:standalone], @definition).generate if options[:standalone]
end
@ -265,22 +266,6 @@ module Bundler
end
end
def warn_on_incompatible_bundler_deps
bundler_version = Gem::Version.create(Bundler::VERSION)
@definition.specs.each do |spec|
spec.dependencies.each do |dep|
next if dep.type == :development
next unless dep.name == "bundler".freeze
next if dep.requirement.satisfied_by?(bundler_version)
Bundler.ui.warn "#{spec.name} (#{spec.version}) has dependency" \
" #{SharedHelpers.pretty_dependency(dep)}" \
", which is unsatisfied by the current bundler version #{VERSION}" \
", so the dependency is being ignored"
end
end
end
def install_in_parallel(size, standalone, force = false)
spec_installations = ParallelInstaller.call(self, @definition.specs, size, standalone, force)
spec_installations.each do |installation|

Просмотреть файл

@ -15,6 +15,7 @@ module Bundler
file.puts "ruby_engine = RUBY_ENGINE"
file.puts "ruby_version = RbConfig::CONFIG[\"ruby_version\"]"
file.puts "path = File.expand_path('..', __FILE__)"
file.puts reverse_rubygems_kernel_mixin
paths.each do |path|
file.puts %($:.unshift File.expand_path("\#{path}/#{path}"))
end
@ -48,5 +49,19 @@ module Bundler
error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
raise Gem::InvalidSpecificationException.new(error_message)
end
def reverse_rubygems_kernel_mixin
<<~END
kernel = (class << ::Kernel; self; end)
[kernel, ::Kernel].each do |k|
if k.private_method_defined?(:gem_original_require)
private_require = k.private_method_defined?(:require)
k.send(:remove_method, :require)
k.send(:define_method, :require, k.instance_method(:gem_original_require))
k.send(:private, :require) if private_require
end
end
END
end
end
end

Просмотреть файл

@ -4,22 +4,6 @@ require_relative "match_platform"
module Bundler
class LazySpecification
Identifier = Struct.new(:name, :version, :platform)
class Identifier
include Comparable
def <=>(other)
return unless other.is_a?(Identifier)
[name, version, platform_string] <=> [other.name, other.version, other.platform_string]
end
protected
def platform_string
platform_string = platform.to_s
platform_string == Index::RUBY ? Index::NULL : platform_string
end
end
include MatchPlatform
attr_reader :name, :version, :dependencies, :platform
@ -108,7 +92,7 @@ module Bundler
end
def identifier
@__identifier ||= Identifier.new(name, version, platform)
@__identifier ||= [name, version, platform_string]
end
def git_version
@ -116,6 +100,13 @@ module Bundler
" #{source.revision[0..6]}"
end
protected
def platform_string
platform_string = platform.to_s
platform_string == Index::RUBY ? Index::NULL : platform_string
end
private
def to_ary
@ -140,7 +131,7 @@ module Bundler
# explicitly add a more specific platform.
#
def ruby_platform_materializes_to_ruby_platform?
!Bundler.most_specific_locked_platform?(Gem::Platform::RUBY)
!Bundler.most_specific_locked_platform?(Gem::Platform::RUBY) || Bundler.settings[:force_ruby_platform]
end
end
end

Просмотреть файл

@ -64,8 +64,6 @@ module Bundler
@state = nil
@specs = {}
@rubygems_aggregate = Source::Rubygems.new
if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
raise LockfileError, "Your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} contains merge conflicts.\n" \
"Run `git checkout HEAD -- #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` first to get a clean lock."
@ -89,7 +87,6 @@ module Bundler
send("parse_#{@state}", line)
end
end
@sources << @rubygems_aggregate unless Bundler.feature_flag.disable_multisource?
@specs = @specs.values.sort_by(&:identifier)
warn_for_outdated_bundler_version
rescue ArgumentError => e
@ -134,16 +131,19 @@ module Bundler
@sources << @current_source
end
when GEM
if Bundler.feature_flag.disable_multisource?
source_remotes = Array(@opts["remote"])
if source_remotes.size == 1
@opts["remotes"] = @opts.delete("remote")
@current_source = TYPES[@type].from_lock(@opts)
@sources << @current_source
else
Array(@opts["remote"]).each do |url|
@rubygems_aggregate.add_remote(url)
source_remotes.each do |url|
rubygems_aggregate.add_remote(url)
end
@current_source = @rubygems_aggregate
@current_source = rubygems_aggregate
end
@sources << @current_source
when PLUGIN
@current_source = Plugin.source_from_lock(@opts)
@sources << @current_source
@ -245,5 +245,9 @@ module Bundler
def parse_ruby(line)
@ruby_version = line.strip
end
def rubygems_aggregate
@rubygems_aggregate ||= Source::Rubygems.new
end
end
end

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "BUNDLE\-CONFIG" "1" "December 2020" "" ""
.TH "BUNDLE\-CONFIG" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options
@ -136,9 +136,6 @@ Any periods in the configuration keys must be replaced with two underscores when
The following is a list of all configuration keys and their purpose\. You can learn more about their operation in bundle install(1) \fIbundle\-install\.1\.html\fR\.
.
.IP "\(bu" 4
\fBallow_bundler_dependency_conflicts\fR (\fBBUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS\fR): Allow resolving to specifications that have dependencies on \fBbundler\fR that are incompatible with the running Bundler version\.
.
.IP "\(bu" 4
\fBallow_deployment_source_credential_changes\fR (\fBBUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES\fR): When in deployment mode, allow changing the credentials to a gem\'s source\. Ex: \fBhttps://some\.host\.com/gems/path/\fR \-> \fBhttps://user_name:password@some\.host\.com/gems/path\fR
.
.IP "\(bu" 4
@ -184,6 +181,9 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBdisable_local_branch_check\fR (\fBBUNDLE_DISABLE_LOCAL_BRANCH_CHECK\fR): Allow Bundler to use a local git override without a branch specified in the Gemfile\.
.
.IP "\(bu" 4
\fBdisable_local_revision_check\fR (\fBBUNDLE_DISABLE_LOCAL_REVISION_CHECK\fR): Allow Bundler to use a local git override without checking if the revision present in the lockfile is present in the repository\.
.
.IP "\(bu" 4
\fBdisable_multisource\fR (\fBBUNDLE_DISABLE_MULTISOURCE\fR): When set, Gemfiles containing multiple sources will produce errors instead of warnings\. Use \fBbundle config unset disable_multisource\fR to unset\.
.
.IP "\(bu" 4

Просмотреть файл

@ -133,9 +133,6 @@ the environment variable `BUNDLE_LOCAL__RACK`.
The following is a list of all configuration keys and their purpose. You can
learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `allow_bundler_dependency_conflicts` (`BUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS`):
Allow resolving to specifications that have dependencies on `bundler` that
are incompatible with the running Bundler version.
* `allow_deployment_source_credential_changes` (`BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES`):
When in deployment mode, allow changing the credentials to a gem's source.
Ex: `https://some.host.com/gems/path/` -> `https://user_name:password@some.host.com/gems/path`
@ -178,6 +175,9 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `disable_local_branch_check` (`BUNDLE_DISABLE_LOCAL_BRANCH_CHECK`):
Allow Bundler to use a local git override without a branch specified in the
Gemfile.
* `disable_local_revision_check` (`BUNDLE_DISABLE_LOCAL_REVISION_CHECK`):
Allow Bundler to use a local git override without checking if the revision
present in the lockfile is present in the repository.
* `disable_multisource` (`BUNDLE_DISABLE_MULTISOURCE`):
When set, Gemfiles containing multiple sources will produce errors
instead of warnings.

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "BUNDLE\-INIT" "1" "December 2020" "" ""
.TH "BUNDLE\-INIT" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -105,6 +105,7 @@ module Bundler
else
builder.eval_gemfile(gemfile)
end
builder.check_primary_source_safety
definition = builder.to_definition(nil, true)
return if definition.dependencies.empty?

Просмотреть файл

@ -16,15 +16,13 @@ module Bundler
version = options[:version] || [">= 0"]
Bundler.settings.temporary(:disable_multisource => false) do
if options[:git]
install_git(names, version, options)
elsif options[:local_git]
install_local_git(names, version, options)
else
sources = options[:source] || Bundler.rubygems.sources
install_rubygems(names, version, sources)
end
if options[:git]
install_git(names, version, options)
elsif options[:local_git]
install_local_git(names, version, options)
else
sources = options[:source] || Bundler.rubygems.sources
install_rubygems(names, version, sources)
end
end
@ -79,7 +77,7 @@ module Bundler
source_list = SourceList.new
source_list.add_git_source(git_source_options) if git_source_options
source_list.add_rubygems_source("remotes" => rubygems_source) if rubygems_source
source_list.global_rubygems_source = rubygems_source if rubygems_source
deps = names.map {|name| Dependency.new name, version }

Просмотреть файл

@ -17,6 +17,10 @@ module Bundler
path_sources + git_sources + rubygems_sources + [metadata_source]
end
def default_source
git_sources.first || global_rubygems_source
end
private
def rubygems_aggregate_class

Просмотреть файл

@ -5,6 +5,8 @@ module Bundler
require_relative "vendored_molinillo"
require_relative "resolver/spec_group"
include GemHelpers
# Figures out the best possible configuration of gems that satisfies
# the list of passed dependencies and any child dependencies without
# causing any gem activation errors.
@ -15,31 +17,38 @@ module Bundler
# ==== Returns
# <GemBundle>,nil:: If the list of dependencies can be resolved, a
# collection of gemspecs is returned. Otherwise, nil is returned.
def self.resolve(requirements, index, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
platforms = Set.new(platforms) if platforms
def self.resolve(requirements, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
base = SpecSet.new(base) unless base.is_a?(SpecSet)
resolver = new(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
result = resolver.start(requirements)
SpecSet.new(result)
end
def initialize(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
@index = index
def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
@source_requirements = source_requirements
@index_requirements = source_requirements.each_with_object({}) do |source_requirement, index_requirements|
name, source = source_requirement
index_requirements[name] = name == :global ? source : source.specs
end
@base = base
@resolver = Molinillo::Resolver.new(self, self)
@search_for = {}
@base_dg = Molinillo::DependencyGraph.new
@base.each do |ls|
dep = Dependency.new(ls.name, ls.version)
@base_dg.add_vertex(ls.name, DepProxy.new(dep, ls.platform), true)
@base_dg.add_vertex(ls.name, DepProxy.get_proxy(dep, ls.platform), true)
end
additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
@platforms = platforms
@platforms = platforms.reject {|p| p != Gem::Platform::RUBY && (platforms - [p]).any? {|pl| generic(pl) == p } }
@resolving_only_for_ruby = platforms == [Gem::Platform::RUBY]
@gem_version_promoter = gem_version_promoter
@allow_bundler_dependency_conflicts = Bundler.feature_flag.allow_bundler_dependency_conflicts?
@use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
@lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.disable_multisource?
@no_aggregate_global_source = @source_requirements[:global].nil?
@variant_specific_names = []
@generic_names = ["Ruby\0", "RubyGems\0"]
end
def start(requirements)
@ -75,7 +84,7 @@ module Bundler
return unless debug?
debug_info = yield
debug_info = debug_info.inspect unless debug_info.is_a?(String)
puts debug_info.split("\n").map {|s| "BUNDLER: " + " " * depth + s }
puts debug_info.split("\n").map {|s| depth == 0 ? "BUNDLER: #{s}" : "BUNDLER(#{depth}): #{s}" }
end
def debug?
@ -103,16 +112,25 @@ module Bundler
include Molinillo::SpecificationProvider
def dependencies_for(specification)
specification.dependencies_for_activated_platforms
all_dependencies = specification.dependencies_for_activated_platforms
if @variant_specific_names.include?(specification.name)
@variant_specific_names |= all_dependencies.map(&:name) - @generic_names
else
generic_names, variant_specific_names = specification.partitioned_dependency_names_for_activated_platforms
@variant_specific_names |= variant_specific_names - @generic_names
@generic_names |= generic_names
end
all_dependencies
end
def search_for(dependency_proxy)
platform = dependency_proxy.__platform
dependency = dependency_proxy.dep
@search_for[dependency_proxy] ||= begin
name = dependency.name
index = index_for(dependency)
results = index.search(dependency, @base[name])
name = dependency.name
search_result = @search_for[dependency_proxy] ||= begin
results = results_for(dependency, @base[name])
if vertex = @base_dg.vertex_named(name)
locked_requirement = vertex.payload.requirement
@ -137,55 +155,67 @@ module Bundler
end
nested.reduce([]) do |groups, (version, specs)|
next groups if locked_requirement && !locked_requirement.satisfied_by?(version)
spec_group = SpecGroup.new(specs)
spec_group.ignores_bundler_dependencies = @allow_bundler_dependency_conflicts
groups << spec_group
specs_by_platform = Hash.new do |current_specs, current_platform|
current_specs[current_platform] = select_best_platform_match(specs, current_platform)
end
spec_group_ruby = SpecGroup.create_for(specs_by_platform, [Gem::Platform::RUBY], Gem::Platform::RUBY)
groups << spec_group_ruby if spec_group_ruby
next groups if @resolving_only_for_ruby
spec_group = SpecGroup.create_for(specs_by_platform, @platforms, platform)
groups << spec_group if spec_group
groups
end
else
[]
end
# GVP handles major itself, but it's still a bit risky to trust it with it
# until we get it settled with new behavior. For 2.x it can take over all cases.
search = if !@use_gvp
if !@use_gvp
spec_groups
else
@gem_version_promoter.sort_versions(dependency, spec_groups)
end
selected_sgs = []
search.each do |sg|
next unless sg.for?(platform)
sg_all_platforms = sg.copy_for(self.class.sort_platforms(@platforms).reverse)
next unless sg_all_platforms
selected_sgs << sg_all_platforms
next if sg_all_platforms.activated_platforms == [Gem::Platform::RUBY]
# Add a spec group for "non platform specific spec" as the fallback
# spec group.
sg_ruby = sg.copy_for([Gem::Platform::RUBY])
selected_sgs.insert(-2, sg_ruby) if sg_ruby
end
selected_sgs
end
unless search_result.empty?
specific_dependency = @variant_specific_names.include?(name)
return search_result unless specific_dependency
search_result.each do |sg|
if @generic_names.include?(name)
@variant_specific_names -= [name]
sg.activate_all_platforms!
else
sg.activate_platform!(platform)
end
end
end
search_result
end
def index_for(dependency)
source = @source_requirements[dependency.name]
source = @index_requirements[dependency.name]
if source
source.specs
elsif @lockfile_uses_separate_rubygems_sources
source
elsif @no_aggregate_global_source
Index.build do |idx|
if dependency.all_sources
dependency.all_sources.each {|s| idx.add_source(s.specs) if s }
else
idx.add_source @source_requirements[:default].specs
end
dependency.all_sources.each {|s| idx.add_source(s.specs) }
end
else
@index
@index_requirements[:global]
end
end
def results_for(dependency, base)
index_for(dependency).search(dependency, base)
end
def name_for(dependency)
dependency.name
end
@ -206,21 +236,27 @@ module Bundler
requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
end
def dependencies_equal?(dependencies, other_dependencies)
dependencies.map(&:dep) == other_dependencies.map(&:dep)
end
def relevant_sources_for_vertex(vertex)
if vertex.root?
[@source_requirements[vertex.name]]
elsif @lockfile_uses_separate_rubygems_sources
elsif @no_aggregate_global_source
vertex.recursive_predecessors.map do |v|
@source_requirements[v.name]
end << @source_requirements[:default]
end.compact << @source_requirements[:default]
else
[]
end
end
def sort_dependencies(dependencies, activated, conflicts)
dependencies.sort_by do |dependency|
dependency.all_sources = relevant_sources_for_vertex(activated.vertex_named(dependency.name))
name = name_for(dependency)
vertex = activated.vertex_named(name)
dependency.all_sources = relevant_sources_for_vertex(vertex)
[
@base_dg.vertex_named(name) ? 0 : 1,
vertex.payload ? 0 : 1,
@ -233,13 +269,6 @@ module Bundler
end
end
# Sort platforms from most general to most specific
def self.sort_platforms(platforms)
platforms.sort_by do |platform|
platform_sort_key(platform)
end
end
def self.platform_sort_key(platform)
# Prefer specific platform to not specific platform
return ["99-LAST", "", "", ""] if Gem::Platform::RUBY == platform
@ -294,7 +323,7 @@ module Bundler
"If you are updating multiple gems in your Gemfile at once,\n" \
"try passing them all to `bundle update`"
elsif source = @source_requirements[name]
specs = source.specs[name]
specs = source.specs.search(name)
versions_with_platforms = specs.map {|s| [s.version, s.platform] }
message = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source}#{cache_message}.\n")
message << if versions_with_platforms.any?
@ -303,7 +332,7 @@ module Bundler
"The source does not contain any versions of '#{name}'"
end
else
message = "Could not find gem '#{requirement}' in any of the gem sources " \
message = "Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in any of the gem sources " \
"listed in your Gemfile#{cache_message}."
end
raise GemNotFound, message
@ -324,10 +353,16 @@ module Bundler
def version_conflict_message(e)
# only show essential conflicts, if possible
conflicts = e.conflicts.dup
conflicts.delete_if do |_name, conflict|
deps = conflict.requirement_trees.map(&:last).flatten(1)
!Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
if conflicts["bundler"]
conflicts.replace("bundler" => conflicts["bundler"])
else
conflicts.delete_if do |_name, conflict|
deps = conflict.requirement_trees.map(&:last).flatten(1)
!Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
end
end
e = Molinillo::VersionConflict.new(conflicts, e.specification_provider) unless conflicts.empty?
solver_name = "Bundler"
@ -355,15 +390,25 @@ module Bundler
:additional_message_for_conflict => lambda do |o, name, conflict|
if name == "bundler"
o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new(Bundler::VERSION))
end
if name == "bundler" && other_bundler_required
o << "\n"
o << "This Gemfile requires a different version of Bundler.\n"
o << "Perhaps you need to update Bundler by running `gem install bundler`?\n"
end
if conflict.locked_requirement
conflict_dependency = conflict.requirement
conflict_requirement = conflict_dependency.requirement
other_bundler_required = !conflict_requirement.satisfied_by?(Gem::Version.new(Bundler::VERSION))
if other_bundler_required
o << "\n\n"
candidate_specs = @index_requirements[:default_bundler].search(conflict_dependency)
if candidate_specs.any?
target_version = candidate_specs.last.version
new_command = [File.basename($PROGRAM_NAME), "_#{target_version}_", *ARGV].join(" ")
o << "Your bundle requires a different version of Bundler than the one you're running.\n"
o << "Install the necessary version with `gem install bundler:#{target_version}` and rerun bundler using `#{new_command}`\n"
else
o << "Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n"
end
end
elsif conflict.locked_requirement
o << "\n"
o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
o << %(the gems in your Gemfile, which may resolve the conflict.\n)
@ -372,14 +417,8 @@ module Bundler
relevant_sources = if conflict.requirement.source
[conflict.requirement.source]
elsif conflict.requirement.all_sources
conflict.requirement.all_sources
elsif @lockfile_uses_separate_rubygems_sources
# every conflict should have an explicit group of sources when we
# enforce strict pinning
raise "no source set for #{conflict}"
else
[]
conflict.requirement.all_sources
end.compact.map(&:to_s).uniq.sort
metadata_requirement = name.end_with?("\0")
@ -416,23 +455,21 @@ module Bundler
def validate_resolved_specs!(resolved_specs)
resolved_specs.each do |v|
name = v.name
next unless sources = relevant_sources_for_vertex(v)
sources.compact!
sources = relevant_sources_for_vertex(v)
next unless sources.any?
if default_index = sources.index(@source_requirements[:default])
sources.delete_at(default_index)
end
sources.reject! {|s| s.specs[name].empty? }
sources.reject! {|s| s.specs.search(name).empty? }
sources.uniq!
next if sources.size <= 1
multisource_disabled = Bundler.feature_flag.disable_multisource?
msg = ["The gem '#{name}' was found in multiple relevant sources."]
msg.concat sources.map {|s| " * #{s}" }.sort
msg << "You #{multisource_disabled ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
msg << "You #{@no_aggregate_global_source ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
msg = msg.join("\n")
raise SecurityError, msg if multisource_disabled
raise SecurityError, msg if @no_aggregate_global_source
Bundler.ui.warn "Warning: #{msg}"
end
end

Просмотреть файл

@ -3,28 +3,37 @@
module Bundler
class Resolver
class SpecGroup
include GemHelpers
attr_accessor :name, :version, :source
attr_accessor :ignores_bundler_dependencies, :activated_platforms
attr_accessor :activated_platforms
def initialize(all_specs)
@all_specs = all_specs
raise ArgumentError, "cannot initialize with an empty value" unless exemplary_spec = all_specs.first
def self.create_for(specs, all_platforms, specific_platform)
specific_platform_specs = specs[specific_platform]
return unless specific_platform_specs.any?
platforms = all_platforms.select {|p| specs[p].any? }
new(specific_platform_specs.first, specs, platforms)
end
def initialize(exemplary_spec, specs, relevant_platforms)
@exemplary_spec = exemplary_spec
@name = exemplary_spec.name
@version = exemplary_spec.version
@source = exemplary_spec.source
@activated_platforms = []
@dependencies = nil
@specs = Hash.new do |specs, platform|
specs[platform] = select_best_platform_match(all_specs, platform)
@all_platforms = relevant_platforms
@activated_platforms = relevant_platforms
@dependencies = Hash.new do |dependencies, platforms|
dependencies[platforms] = dependencies_for(platforms)
end
@ignores_bundler_dependencies = true
@partitioned_dependency_names = Hash.new do |partitioned_dependency_names, platforms|
partitioned_dependency_names[platforms] = partitioned_dependency_names_for(platforms)
end
@specs = specs
end
def to_specs
@activated_platforms.map do |p|
activated_platforms.map do |p|
specs = @specs[p]
next unless specs.any?
@ -36,18 +45,12 @@ module Bundler
end.flatten.compact.uniq
end
def copy_for(platforms)
platforms.select! {|p| for?(p) }
return unless platforms.any?
copied_sg = self.class.new(@all_specs)
copied_sg.ignores_bundler_dependencies = @ignores_bundler_dependencies
copied_sg.activated_platforms = platforms
copied_sg
def activate_platform!(platform)
self.activated_platforms = [platform]
end
def for?(platform)
@specs[platform].any?
def activate_all_platforms!
self.activated_platforms = @all_platforms
end
def to_s
@ -56,11 +59,11 @@ module Bundler
end
def dependencies_for_activated_platforms
dependencies = @activated_platforms.map {|p| __dependencies[p] }
metadata_dependencies = @activated_platforms.map do |platform|
metadata_dependencies(@specs[platform].first, platform)
end
dependencies.concat(metadata_dependencies).flatten
@dependencies[activated_platforms]
end
def partitioned_dependency_names_for_activated_platforms
@partitioned_dependency_names[activated_platforms]
end
def ==(other)
@ -86,34 +89,43 @@ module Bundler
protected
def sorted_activated_platforms
@activated_platforms.sort_by(&:to_s)
activated_platforms.sort_by(&:to_s)
end
private
def __dependencies
@dependencies = Hash.new do |dependencies, platform|
dependencies[platform] = []
specs = @specs[platform]
if spec = specs.first
spec.dependencies.each do |dep|
next if dep.type == :development
next if @ignores_bundler_dependencies && dep.name == "bundler".freeze
dependencies[platform] << DepProxy.new(dep, platform)
end
end
dependencies[platform]
end
def dependencies_for(platforms)
platforms.map do |platform|
__dependencies(platform) + metadata_dependencies(platform)
end.flatten
end
def metadata_dependencies(spec, platform)
return [] unless spec && spec.is_a?(Gem::Specification)
def partitioned_dependency_names_for(platforms)
return @dependencies[platforms].map(&:name), [] if platforms.size == 1
@dependencies[platforms].partition do |dep_proxy|
@dependencies[platforms].count {|dp| dp.dep == dep_proxy.dep } == platforms.size
end.map {|deps| deps.map(&:name) }
end
def __dependencies(platform)
dependencies = []
@specs[platform].first.dependencies.each do |dep|
next if dep.type == :development
dependencies << DepProxy.get_proxy(dep, platform)
end
dependencies
end
def metadata_dependencies(platform)
spec = @specs[platform].first
return [] unless spec.is_a?(Gem::Specification)
dependencies = []
if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
dependencies << DepProxy.new(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
dependencies << DepProxy.get_proxy(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
end
if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
dependencies << DepProxy.new(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
dependencies << DepProxy.get_proxy(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
end
dependencies
end

Просмотреть файл

@ -158,6 +158,22 @@ module Gem
end
end
if Gem::Requirement.new("~> 2.0").hash == Gem::Requirement.new("~> 2.0.0").hash
class Requirement
module CorrectHashForLambdaOperator
def hash
if requirements.any? {|r| r.first == "~>" }
requirements.map {|r| r.first == "~>" ? [r[0], r[1].to_s] : r }.sort.hash
else
super
end
end
end
prepend CorrectHashForLambdaOperator
end
end
class Platform
JAVA = Gem::Platform.new("java") unless defined?(JAVA)
MSWIN = Gem::Platform.new("mswin32") unless defined?(MSWIN)

Просмотреть файл

@ -8,6 +8,53 @@ module Bundler
# Bundler needs to install gems regardless of binstub overwriting
end
def install
pre_install_checks
run_pre_install_hooks
spec.loaded_from = spec_file
# Completely remove any previous gem files
FileUtils.rm_rf gem_dir
FileUtils.rm_rf spec.extension_dir
FileUtils.mkdir_p gem_dir, :mode => 0o755
extract_files
build_extensions
write_build_info_file
run_post_build_hooks
generate_bin
generate_plugins
write_spec
write_cache_file
say spec.post_install_message unless spec.post_install_message.nil?
run_post_install_hooks
spec
end
def generate_plugins
return unless Gem::Installer.instance_methods(false).include?(:generate_plugins)
latest = Gem::Specification.stubs_for(spec.name).first
return if latest && latest.version > spec.version
ensure_writable_dir @plugins_dir
if spec.plugins.empty?
remove_plugins_for(spec, @plugins_dir)
else
regenerate_plugins_for(spec, @plugins_dir)
end
end
def pre_install_checks
super && validate_bundler_checksum(options[:bundler_expected_checksum])
end

Просмотреть файл

@ -7,7 +7,6 @@ module Bundler
autoload :Validator, File.expand_path("settings/validator", __dir__)
BOOL_KEYS = %w[
allow_bundler_dependency_conflicts
allow_deployment_source_credential_changes
allow_offline_install
auto_clean_without_path
@ -20,6 +19,7 @@ module Bundler
disable_checksum_validation
disable_exec_load
disable_local_branch_check
disable_local_revision_check
disable_multisource
disable_shared_gems
disable_version_check

Просмотреть файл

@ -187,11 +187,11 @@ module Bundler
return @md5_available if defined?(@md5_available)
@md5_available = begin
require "openssl"
OpenSSL::Digest.digest("MD5", "")
::OpenSSL::Digest.digest("MD5", "")
true
rescue LoadError
true
rescue OpenSSL::Digest::DigestError
rescue ::OpenSSL::Digest::DigestError
false
end
end

Просмотреть файл

@ -22,7 +22,7 @@ module Bundler
@uri = options["uri"] || ""
@safe_uri = URICredentialsFilter.credential_filtered_uri(@uri)
@branch = options["branch"]
@ref = options["ref"] || options["branch"] || options["tag"] || "master"
@ref = options["ref"] || options["branch"] || options["tag"]
@submodules = options["submodules"]
@name = options["name"]
@version = options["version"].to_s.strip.gsub("-", ".pre.")
@ -60,25 +60,27 @@ module Bundler
alias_method :==, :eql?
def to_s
at = if local?
path
elsif user_ref = options["ref"]
if ref =~ /\A[a-z0-9]{4,}\z/i
shortref_for_display(user_ref)
begin
at = if local?
path
elsif user_ref = options["ref"]
if ref =~ /\A[a-z0-9]{4,}\z/i
shortref_for_display(user_ref)
else
user_ref
end
elsif ref
ref
else
user_ref
git_proxy.branch
end
else
ref
rev = " (at #{at}@#{shortref_for_display(revision)})"
rescue GitError
""
end
rev = begin
"@#{shortref_for_display(revision)}"
rescue GitError
nil
end
"#{@safe_uri} (at #{at}#{rev})"
"#{@safe_uri}#{rev}"
end
def name
@ -146,7 +148,7 @@ module Bundler
changed = cached_revision && cached_revision != git_proxy.revision
if changed && !@unlocked && !git_proxy.contains?(cached_revision)
if !Bundler.settings[:disable_local_revision_check] && changed && !@unlocked && !git_proxy.contains?(cached_revision)
raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \
"but the current branch in your local override for #{name} does not contain such commit. " \
"Please make sure your branch is up to date."

Просмотреть файл

@ -17,7 +17,7 @@ module Bundler
class GitNotAllowedError < GitError
def initialize(command)
msg = String.new
msg << "Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, "
msg << "Bundler is trying to run `#{command}` at runtime. You probably need to run `bundle install`. However, "
msg << "this error message could probably be more useful. Please submit a ticket at https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md "
msg << "with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}"
super msg
@ -27,11 +27,11 @@ module Bundler
class GitCommandError < GitError
attr_reader :command
def initialize(command, path, destination_path, extra_info = nil)
def initialize(command, path, extra_info = nil)
@command = command
msg = String.new
msg << "Git error: command `git #{command}` in directory #{destination_path} has failed."
msg << "Git error: command `#{command}` in directory #{path} has failed."
msg << "\n#{extra_info}" if extra_info
msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path.exist?
super msg
@ -39,9 +39,9 @@ module Bundler
end
class MissingGitRevisionError < GitCommandError
def initialize(command, path, destination_path, ref, repo)
def initialize(command, destination_path, ref, repo)
msg = "Revision #{ref} does not exist in the repository #{repo}. Maybe you misspelled it?"
super command, path, destination_path, msg
super command, destination_path, msg
end
end
@ -132,7 +132,7 @@ module Bundler
begin
git "reset", "--hard", @revision, :dir => destination
rescue GitCommandError => e
raise MissingGitRevisionError.new(e.command, path, destination, @revision, URICredentialsFilter.credential_filtered_uri(uri))
raise MissingGitRevisionError.new(e.command, destination, @revision, URICredentialsFilter.credential_filtered_uri(uri))
end
if submodules
@ -145,32 +145,36 @@ module Bundler
private
def git_null(*command, dir: SharedHelpers.pwd)
def git_null(*command, dir: nil)
check_allowed(command)
out, status = SharedHelpers.with_clean_git_env do
capture_and_ignore_stderr("git", "-C", dir.to_s, *command)
capture_and_ignore_stderr(*capture3_args_for(command, dir))
end
[URICredentialsFilter.credential_filtered_string(out, uri), status]
end
def git_retry(*command, dir: SharedHelpers.pwd)
Bundler::Retry.new("`git -C #{dir} #{URICredentialsFilter.credential_filtered_string(command.shelljoin, uri)}`", GitNotAllowedError).attempts do
def git_retry(*command, dir: nil)
command_with_no_credentials = check_allowed(command)
Bundler::Retry.new("`#{command_with_no_credentials}` at #{dir || SharedHelpers.pwd}").attempts do
git(*command, :dir => dir)
end
end
def git(*command, dir: SharedHelpers.pwd)
def git(*command, dir: nil)
command_with_no_credentials = check_allowed(command)
out, status = SharedHelpers.with_clean_git_env do
capture_and_filter_stderr("git", "-C", dir.to_s, *command)
capture_and_filter_stderr(*capture3_args_for(command, dir))
end
raise GitCommandError.new(command_with_no_credentials, path, dir) unless status.success?
filtered_out = URICredentialsFilter.credential_filtered_string(out, uri)
URICredentialsFilter.credential_filtered_string(out, uri)
raise GitCommandError.new(command_with_no_credentials, dir || SharedHelpers.pwd, filtered_out) unless status.success?
filtered_out
end
def has_revision_cached?
@ -187,10 +191,10 @@ module Bundler
def find_local_revision
allowed_with_path do
git("rev-parse", "--verify", ref, :dir => path).strip
git("rev-parse", "--verify", ref || "HEAD", :dir => path).strip
end
rescue GitCommandError => e
raise MissingGitRevisionError.new(e.command, path, path, ref, URICredentialsFilter.credential_filtered_uri(uri))
raise MissingGitRevisionError.new(e.command, path, ref, URICredentialsFilter.credential_filtered_uri(uri))
end
# Adds credentials to the URI as Fetcher#configured_uri_for does
@ -220,7 +224,7 @@ module Bundler
end
def check_allowed(command)
command_with_no_credentials = URICredentialsFilter.credential_filtered_string(command.shelljoin, uri)
command_with_no_credentials = URICredentialsFilter.credential_filtered_string("git #{command.shelljoin}", uri)
raise GitNotAllowedError.new(command_with_no_credentials) unless allow?
command_with_no_credentials
end
@ -237,6 +241,20 @@ module Bundler
return_value, _, status = Open3.capture3(*cmd)
[return_value, status]
end
def capture3_args_for(cmd, dir)
return ["git", *cmd] unless dir
if Bundler.feature_flag.bundler_3_mode? || supports_minus_c?
["git", "-C", dir.to_s, *cmd]
else
["git", *cmd, { :chdir => dir.to_s }]
end
end
def supports_minus_c?
@supports_minus_c ||= Gem::Version.new(version) >= Gem::Version.new("1.8.5")
end
end
end
end

Просмотреть файл

@ -1,5 +1,7 @@
# frozen_string_literal: true
require_relative "../../rubygems_gem_installer"
module Bundler
class Source
class Path

Просмотреть файл

@ -145,6 +145,8 @@ module Bundler
Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
require_relative "../rubygems_gem_installer"
installed_spec = Bundler::RubyGemsGemInstaller.at(
path,
:install_dir => install_path.to_s,
@ -351,7 +353,6 @@ module Bundler
def installed_specs
@installed_specs ||= Index.build do |idx|
Bundler.rubygems.all_specs.reverse_each do |spec|
next if spec.name == "bundler"
spec.source = self
if Bundler.rubygems.spec_missing_extensions?(spec, false)
Bundler.ui.debug "Source #{self} is ignoring #{spec} because it is missing extensions"

Просмотреть файл

@ -1,21 +1,23 @@
# frozen_string_literal: true
require "set"
module Bundler
class SourceList
attr_reader :path_sources,
:git_sources,
:plugin_sources,
:global_rubygems_source,
:global_path_source,
:metadata_source
def global_rubygems_source
@global_rubygems_source ||= rubygems_aggregate_class.new
end
def initialize
@path_sources = []
@git_sources = []
@plugin_sources = []
@global_rubygems_source = nil
@rubygems_aggregate = rubygems_aggregate_class.new
@global_path_source = nil
@rubygems_sources = []
@metadata_source = Source::Metadata.new
end
@ -24,7 +26,9 @@ module Bundler
if options["gemspec"]
add_source_to_list Source::Gemspec.new(options), path_sources
else
add_source_to_list Source::Path.new(options), path_sources
path_source = add_source_to_list Source::Path.new(options), path_sources
@global_path_source ||= path_source if options["global"]
path_source
end
end
@ -43,24 +47,20 @@ module Bundler
end
def global_rubygems_source=(uri)
if Bundler.feature_flag.disable_multisource?
@global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
end
add_rubygems_remote(uri)
@global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
end
def add_rubygems_remote(uri)
return if Bundler.feature_flag.disable_multisource?
@rubygems_aggregate.add_remote(uri)
@rubygems_aggregate
global_rubygems_source.add_remote(uri)
global_rubygems_source
end
def default_source
global_rubygems_source || @rubygems_aggregate
global_path_source || global_rubygems_source
end
def rubygems_sources
@rubygems_sources + [default_source]
@rubygems_sources + [global_rubygems_source]
end
def rubygems_remotes
@ -96,10 +96,9 @@ module Bundler
replacement_rubygems = !Bundler.feature_flag.disable_multisource? &&
replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
@rubygems_aggregate = replacement_rubygems if replacement_rubygems
@global_rubygems_source = replacement_rubygems if replacement_rubygems
return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
return true if replacement_rubygems && rubygems_remotes.to_set != replacement_rubygems.remotes.to_set
false
end
@ -112,10 +111,6 @@ module Bundler
all_sources.each(&:remote!)
end
def rubygems_primary_remotes
@rubygems_aggregate.remotes
end
private
def rubygems_aggregate_class
@ -153,7 +148,7 @@ module Bundler
end
def equal_sources?(lock_sources, replacement_sources)
lock_sources.to_set == replacement_sources.to_set
lock_sources.sort_by(&:to_s) == replacement_sources.sort_by(&:to_s)
end
def equal_source?(source, other_source)

Просмотреть файл

@ -1,7 +1,6 @@
# frozen_string_literal: true
require "tsort"
require "set"
module Bundler
class SpecSet
@ -13,14 +12,16 @@ module Bundler
end
def for(dependencies, skip = [], check = false, match_current_platform = false, raise_on_missing = true)
handled = Set.new
handled = []
deps = dependencies.dup
specs = []
skip += ["bundler"]
loop do
break unless dep = deps.shift
next if !handled.add?(dep) || skip.include?(dep.name)
next if handled.include?(dep) || skip.include?(dep.name)
handled << dep
specs_for_dep = spec_for_dependency(dep, match_current_platform)
if specs_for_dep.any?
@ -28,7 +29,7 @@ module Bundler
specs_for_dep.first.dependencies.each do |d|
next if d.type == :development
d = DepProxy.new(d, dep.__platform) unless match_current_platform
d = DepProxy.get_proxy(d, dep.__platform) unless match_current_platform
deps << d
end
elsif check

Просмотреть файл

@ -26,11 +26,19 @@ module Bundler
# @!group Stub Delegates
def manually_installed?
# This is for manually installed gems which are gems that were fixed in place after a
# failed installation. Once the issue was resolved, the user then manually created
# the gem specification using the instructions provided by `gem help install`
installed_by_version == Gem::Version.new(0)
end
# This is defined directly to avoid having to loading the full spec
def missing_extensions?
return false if default_gem?
return false if extensions.empty?
return false if File.exist? gem_build_complete_path
return false if manually_installed?
true
end

Просмотреть файл

@ -0,0 +1,5 @@
## [Unreleased]
## [0.1.0] - <%= Time.now.strftime('%F') %>
- Initial release

Просмотреть файл

@ -16,5 +16,5 @@ gem "<%= config[:test] %>", "~> <%= config[:test_framework_version] %>"
<%- end -%>
<%- if config[:rubocop] -%>
gem "rubocop", "~> 0.80"
gem "rubocop", "~> <%= config[:rubocop_version] %>"
<%- end -%>

Просмотреть файл

@ -29,19 +29,21 @@ TODO: Write usage instructions here
After checking out the repo, run `bin/setup` to install dependencies.<% if config[:test] %> Then, run `rake <%= config[:test].sub('mini', '').sub('rspec', 'spec') %>` to run the tests.<% end %> You can also run `bin/console` for an interactive prompt that will allow you to experiment.<% if config[:bin] %> Run `bundle exec <%= config[:name] %>` to use the gem in this directory, ignoring other installed copies of this gem.<% end %>
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
<% if config[:git] -%>
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/<%= config[:github_username] %>/<%= config[:name] %>.<% if config[:coc] %> This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/master/CODE_OF_CONDUCT.md).<% end %>
Bug reports and pull requests are welcome on GitHub at https://github.com/<%= config[:github_username] %>/<%= config[:name] %>.<% if config[:coc] %> This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/<%= config[:git_default_branch] %>/CODE_OF_CONDUCT.md).<% end %>
<% end -%>
<% if config[:mit] -%>
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
<% end -%>
<% if config[:coc] -%>
<% if config[:git] && config[:coc] -%>
## Code of Conduct
Everyone interacting in the <%= config[:constant_name] %> project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/master/CODE_OF_CONDUCT.md).
Everyone interacting in the <%= config[:constant_name] %> project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/<%= config[:git_default_branch] %>/CODE_OF_CONDUCT.md).
<% end -%>

Просмотреть файл

@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
<%- if config[:mit] -%>
spec.license = "MIT"
<%- end -%>
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
spec.required_ruby_version = Gem::Requirement.new(">= <%= config[:required_ruby_version] %>")
spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"

Просмотреть файл

@ -1,3 +1,6 @@
AllCops:
TargetRubyVersion: <%= ::Gem::Version.new(config[:required_ruby_version]).segments[0..1].join(".") %>
Style/StringLiterals:
Enabled: true
EnforcedStyle: double_quotes

Просмотреть файл

@ -26,6 +26,13 @@ module Bundler::Molinillo
end
end
# (see Bundler::Molinillo::SpecificationProvider#dependencies_equal?)
def dependencies_equal?(dependencies, other_dependencies)
with_no_such_dependency_error_handling do
specification_provider.dependencies_equal?(dependencies, other_dependencies)
end
end
# (see Bundler::Molinillo::SpecificationProvider#name_for)
def name_for(dependency)
with_no_such_dependency_error_handling do

Просмотреть файл

@ -1,6 +1,5 @@
# frozen_string_literal: true
require 'set'
require 'tsort'
require_relative 'dependency_graph/log'

Просмотреть файл

@ -59,7 +59,7 @@ module Bundler::Molinillo
# @param [Set<Vertex>] vertices the set to add the predecessors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is a
# {#descendent?}
def _recursive_predecessors(vertices = Set.new)
def _recursive_predecessors(vertices = new_vertex_set)
incoming_edges.each do |edge|
vertex = edge.origin
next unless vertices.add?(vertex)
@ -85,7 +85,7 @@ module Bundler::Molinillo
# @param [Set<Vertex>] vertices the set to add the successors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is an
# {#ancestor?}
def _recursive_successors(vertices = Set.new)
def _recursive_successors(vertices = new_vertex_set)
outgoing_edges.each do |edge|
vertex = edge.destination
next unless vertices.add?(vertex)
@ -128,7 +128,7 @@ module Bundler::Molinillo
# Is there a path from `self` to `other` following edges in the
# dependency graph?
# @return true iff there is a path following edges within this {#graph}
# @return whether there is a path following edges within this {#graph}
def path_to?(other)
_path_to?(other)
end
@ -138,7 +138,7 @@ module Bundler::Molinillo
# @param [Vertex] other the vertex to check if there's a path to
# @param [Set<Vertex>] visited the vertices of {#graph} that have been visited
# @return [Boolean] whether there is a path to `other` from `self`
def _path_to?(other, visited = Set.new)
def _path_to?(other, visited = new_vertex_set)
return false unless visited.add?(self)
return true if equal?(other)
successors.any? { |v| v._path_to?(other, visited) }
@ -147,12 +147,18 @@ module Bundler::Molinillo
# Is there a path from `other` to `self` following edges in the
# dependency graph?
# @return true iff there is a path following edges within this {#graph}
# @return whether there is a path following edges within this {#graph}
def ancestor?(other)
other.path_to?(self)
end
alias is_reachable_from? ancestor?
def new_vertex_set
require 'set'
Set.new
end
private :new_vertex_set
end
end
end

Просмотреть файл

@ -34,7 +34,7 @@ module Bundler::Molinillo
# An error caused by attempting to fulfil a dependency that was circular
#
# @note This exception will be thrown iff a {Vertex} is added to a
# @note This exception will be thrown if and only if a {Vertex} is added to a
# {DependencyGraph} that has a {DependencyGraph::Vertex#path_to?} an
# existing {DependencyGraph::Vertex}
class CircularDependencyError < ResolverError
@ -121,7 +121,7 @@ module Bundler::Molinillo
t = ''.dup
depth = 2
tree.each do |req|
t << ' ' * depth << req.to_s
t << ' ' * depth << printable_requirement.call(req)
unless tree.last == req
if spec = conflict.activated_by_name[name_for(req)]
t << %( was resolved to #{version_for_spec.call(spec)}, which)

Просмотреть файл

@ -45,6 +45,17 @@ module Bundler::Molinillo
true
end
# Determines whether two arrays of dependencies are equal, and thus can be
# grouped.
#
# @param [Array<Object>] dependencies
# @param [Array<Object>] other_dependencies
# @return [Boolean] whether `dependencies` and `other_dependencies` should
# be considered equal.
def dependencies_equal?(dependencies, other_dependencies)
dependencies == other_dependencies
end
# Returns the name for the given `dependency`.
# @note This method should be 'pure', i.e. the return value should depend
# only on the `dependency` parameter.

Просмотреть файл

@ -329,11 +329,11 @@ module Bundler::Molinillo
# Look for past conflicts that could be unwound to affect the
# requirement tree for the current conflict
all_reqs = last_detail_for_current_unwind.all_requirements
all_reqs_size = all_reqs.size
relevant_unused_unwinds = unused_unwind_options.select do |alternative|
intersecting_requirements =
last_detail_for_current_unwind.all_requirements &
alternative.requirements_unwound_to_instead
next if intersecting_requirements.empty?
diff_reqs = all_reqs - alternative.requirements_unwound_to_instead
next if diff_reqs.size == all_reqs_size
# Find the highest index unwind whilst looping through
current_detail = alternative if alternative > current_detail
alternative
@ -344,8 +344,12 @@ module Bundler::Molinillo
state.unused_unwind_options += unwind_details.reject { |detail| detail.state_index == -1 }
# Update the requirements_unwound_to_instead on any relevant unused unwinds
relevant_unused_unwinds.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
unwind_details.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
relevant_unused_unwinds.each do |d|
(d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
end
unwind_details.each do |d|
(d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
end
current_detail
end
@ -803,7 +807,7 @@ module Bundler::Molinillo
possibilities.reverse_each do |possibility|
dependencies = dependencies_for(possibility)
if current_possibility_set && current_possibility_set.dependencies == dependencies
if current_possibility_set && dependencies_equal?(current_possibility_set.dependencies, dependencies)
current_possibility_set.possibilities.unshift(possibility)
else
possibility_sets.unshift(PossibilitySet.new(dependencies, [possibility]))

11
lib/bundler/vendor/thor/lib/thor.rb поставляемый
Просмотреть файл

@ -1,7 +1,7 @@
require "set"
require_relative "thor/base"
class Bundler::Thor
$thor_runner ||= false
class << self
# Allows for custom "Command" package naming.
#
@ -323,7 +323,7 @@ class Bundler::Thor
# ==== Parameters
# Symbol ...:: A list of commands that should be affected.
def stop_on_unknown_option!(*command_names)
stop_on_unknown_option.merge(command_names)
@stop_on_unknown_option = stop_on_unknown_option | command_names
end
def stop_on_unknown_option?(command) #:nodoc:
@ -337,7 +337,7 @@ class Bundler::Thor
# ==== Parameters
# Symbol ...:: A list of commands that should be affected.
def disable_required_check!(*command_names)
disable_required_check.merge(command_names)
@disable_required_check = disable_required_check | command_names
end
def disable_required_check?(command) #:nodoc:
@ -347,12 +347,12 @@ class Bundler::Thor
protected
def stop_on_unknown_option #:nodoc:
@stop_on_unknown_option ||= Set.new
@stop_on_unknown_option ||= []
end
# help command has the required check disabled by default.
def disable_required_check #:nodoc:
@disable_required_check ||= Set.new([:help])
@disable_required_check ||= [:help]
end
# The method responsible for dispatching given the args.
@ -398,7 +398,6 @@ class Bundler::Thor
# the namespace should be displayed as arguments.
#
def banner(command, namespace = nil, subcommand = false)
$thor_runner ||= false
command.formatted_usage(self, $thor_runner, subcommand).split("\n").map do |formatted_usage|
"#{basename} #{formatted_usage}"
end.join("\n")

2
lib/bundler/vendor/thor/lib/thor/actions.rb поставляемый
Просмотреть файл

@ -219,7 +219,7 @@ class Bundler::Thor
contents = if is_uri
require "open-uri"
open(path, "Accept" => "application/x-thor-template", &:read)
URI.open(path, "Accept" => "application/x-thor-template", &:read)
else
open(path, &:read)
end

Просмотреть файл

@ -251,7 +251,8 @@ class Bundler::Thor
# path<String>:: path of the file to be changed
# flag<Regexp|String>:: the regexp or string to be replaced
# replacement<String>:: the replacement, can be also given as a block
# config<Hash>:: give :verbose => false to not log the status.
# config<Hash>:: give :verbose => false to not log the status, and
# :force => true, to force the replacement regardles of runner behavior.
#
# ==== Example
#
@ -262,9 +263,10 @@ class Bundler::Thor
# end
#
def gsub_file(path, flag, *args, &block)
return unless behavior == :invoke
config = args.last.is_a?(Hash) ? args.pop : {}
return unless behavior == :invoke || config.fetch(:force, false)
path = File.expand_path(path, destination_root)
say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)

2
lib/bundler/vendor/thor/lib/thor/error.rb поставляемый
Просмотреть файл

@ -1,5 +1,5 @@
class Bundler::Thor
Correctable = if defined?(DidYouMean::SpellChecker) && defined?(DidYouMean::Correctable)
Correctable = if defined?(DidYouMean::SpellChecker) && defined?(DidYouMean::Correctable) # rubocop:disable Naming/ConstantName
# In order to support versions of Ruby that don't have keyword
# arguments, we need our own spell checker class that doesn't take key
# words. Even though this code wouldn't be hit because of the check

Просмотреть файл

@ -30,7 +30,11 @@ class Bundler::Thor
arguments.each do |argument|
if !argument.default.nil?
@assigns[argument.human_name] = argument.default
begin
@assigns[argument.human_name] = argument.default.dup
rescue TypeError # Compatibility shim for un-dup-able Fixnum in Ruby < 2.4
@assigns[argument.human_name] = argument.default
end
elsif argument.required?
@non_assigned_required << argument
end

Просмотреть файл

@ -133,15 +133,16 @@ class Bundler::Thor
protected
def assign_result!(option, result)
if option.repeatable && option.type == :hash
(@assigns[option.human_name] ||= {}).merge!(result)
elsif option.repeatable
(@assigns[option.human_name] ||= []) << result
else
@assigns[option.human_name] = result
def assign_result!(option, result)
if option.repeatable && option.type == :hash
(@assigns[option.human_name] ||= {}).merge!(result)
elsif option.repeatable
(@assigns[option.human_name] ||= []) << result
else
@assigns[option.human_name] = result
end
end
end
# Check if the current value in peek is a registered switch.
#
# Two booleans are returned. The first is true if the current value

Просмотреть файл

@ -94,6 +94,8 @@ class Bundler::Thor
# say("I know you knew that.")
#
def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
return if quiet?
buffer = prepare_message(message, *color)
buffer << "\n" if force_new_line && !message.to_s.end_with?("\n")
@ -230,8 +232,9 @@ class Bundler::Thor
paras = message.split("\n\n")
paras.map! do |unwrapped|
counter = 0
unwrapped.split(" ").inject do |memo, word|
words = unwrapped.split(" ")
counter = words.first.length
words.inject do |memo, word|
word = word.gsub(/\n\005/, "\n").gsub(/\005/, "\n")
counter = 0 if word.include? "\n"
if (counter + word.length + 1) < width

Просмотреть файл

@ -97,7 +97,11 @@ class Bundler::Thor
protected
def can_display_colors?
stdout.tty? && !are_colors_disabled?
are_colors_supported? && !are_colors_disabled?
end
def are_colors_supported?
stdout.tty? && ENV["TERM"] != "dumb"
end
def are_colors_disabled?

2
lib/bundler/vendor/thor/lib/thor/version.rb поставляемый
Просмотреть файл

@ -1,3 +1,3 @@
class Bundler::Thor
VERSION = "1.0.1"
VERSION = "1.1.0"
end

Просмотреть файл

@ -275,7 +275,7 @@ module Gem
unless spec = specs.first
msg = "can't find gem #{dep} with executable #{exec_name}"
if name == "bundler" && bundler_message = Gem::BundlerVersionFinder.missing_version_message
if dep.filters_bundler? && bundler_message = Gem::BundlerVersionFinder.missing_version_message
msg = bundler_message
end
raise Gem::GemNotFoundException, msg
@ -469,7 +469,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
next if File.exist? subdir
begin
FileUtils.mkdir_p subdir, **options
rescue Errno::EACCES
rescue SystemCallError
end
end
ensure

Просмотреть файл

@ -634,6 +634,7 @@ RubyGems is a package manager for Ruby.
gem install rake
gem list --local
gem build package.gemspec
gem push package-0.0.1.gem
gem help install
Further help:

Просмотреть файл

@ -45,6 +45,7 @@ class Gem::ConfigFile
DEFAULT_UPDATE_SOURCES = true
DEFAULT_CONCURRENT_DOWNLOADS = 8
DEFAULT_CERT_EXPIRATION_LENGTH_DAYS = 365
DEFAULT_IPV4_FALLBACK_ENABLED = false
##
# For Ruby packagers to set configuration defaults. Set in
@ -140,6 +141,12 @@ class Gem::ConfigFile
attr_accessor :cert_expiration_length_days
##
# == Experimental ==
# Fallback to IPv4 when IPv6 is not reachable or slow (default: false)
attr_accessor :ipv4_fallback_enabled
##
# Path name of directory or file of openssl client certificate, used for remote https connection with client authentication
@ -175,6 +182,7 @@ class Gem::ConfigFile
@update_sources = DEFAULT_UPDATE_SOURCES
@concurrent_downloads = DEFAULT_CONCURRENT_DOWNLOADS
@cert_expiration_length_days = DEFAULT_CERT_EXPIRATION_LENGTH_DAYS
@ipv4_fallback_enabled = ENV['IPV4_FALLBACK_ENABLED'] == 'true' || DEFAULT_IPV4_FALLBACK_ENABLED
operating_system_config = Marshal.load Marshal.dump(OPERATING_SYSTEM_DEFAULTS)
platform_config = Marshal.load Marshal.dump(PLATFORM_DEFAULTS)
@ -203,6 +211,7 @@ class Gem::ConfigFile
@disable_default_gem_server = @hash[:disable_default_gem_server] if @hash.key? :disable_default_gem_server
@sources = @hash[:sources] if @hash.key? :sources
@cert_expiration_length_days = @hash[:cert_expiration_length_days] if @hash.key? :cert_expiration_length_days
@ipv4_fallback_enabled = @hash[:ipv4_fallback_enabled] if @hash.key? :ipv4_fallback_enabled
@ssl_verify_mode = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode
@ssl_ca_cert = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert

Просмотреть файл

@ -0,0 +1,52 @@
require 'socket'
module CoreExtensions
module TCPSocketExt
def self.prepended(base)
base.prepend Initializer
end
module Initializer
CONNECTION_TIMEOUT = 5
IPV4_DELAY_SECONDS = 0.1
def initialize(host, serv, *rest)
mutex = Mutex.new
addrs = []
threads = []
cond_var = ConditionVariable.new
Addrinfo.foreach(host, serv, nil, :STREAM) do |addr|
Thread.report_on_exception = false if defined? Thread.report_on_exception = ()
threads << Thread.new(addr) do
# give head start to ipv6 addresses
sleep IPV4_DELAY_SECONDS if addr.ipv4?
# raises Errno::ECONNREFUSED when ip:port is unreachable
Socket.tcp(addr.ip_address, serv, connect_timeout: CONNECTION_TIMEOUT).close
mutex.synchronize do
addrs << addr.ip_address
cond_var.signal
end
end
end
mutex.synchronize do
timeout_time = CONNECTION_TIMEOUT + Time.now.to_f
while addrs.empty? && (remaining_time = timeout_time - Time.now.to_f) > 0
cond_var.wait(mutex, remaining_time)
end
host = addrs.shift unless addrs.empty?
end
threads.each {|t| t.kill.join if t.alive? }
super(host, serv, *rest)
end
end
end
end
TCPSocket.prepend CoreExtensions::TCPSocketExt

Просмотреть файл

@ -277,7 +277,7 @@ class Gem::Dependency
requirement.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
end.map(&:to_spec)
Gem::BundlerVersionFinder.filter!(matches) if name == "bundler".freeze && !requirement.specific?
Gem::BundlerVersionFinder.filter!(matches) if filters_bundler?
if platform_only
matches.reject! do |spec|
@ -295,6 +295,10 @@ class Gem::Dependency
@requirement.specific?
end
def filters_bundler?
name == "bundler".freeze && !specific?
end
def to_specs
matches = matching_specs true

Просмотреть файл

@ -28,13 +28,14 @@ class Gem::Ext::Builder
unless make_program
make_program = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make'
end
make_program = Shellwords.split(make_program)
destdir = 'DESTDIR=%s' % ENV['DESTDIR']
['clean', '', 'install'].each do |target|
# Pass DESTDIR via command line to override what's in MAKEFLAGS
cmd = [
make_program,
*make_program,
destdir,
target,
].reject(&:empty?)

Просмотреть файл

@ -6,11 +6,16 @@
module Gem::InstallerUninstallerUtils
def regenerate_plugins_for(spec, plugins_dir)
plugins = spec.plugins
return if plugins.empty?
require 'pathname'
spec.plugins.each do |plugin|
plugin_script_path = File.join plugins_dir, "#{spec.name}_plugin#{File.extname(plugin)}"
File.open plugin_script_path, 'wb' do |file|
file.puts "require '#{plugin}'"
file.puts "require_relative '#{Pathname.new(plugin).relative_path_from(Pathname.new(plugins_dir))}'"
end
verbose plugin_script_path

Просмотреть файл

@ -66,7 +66,7 @@ class Gem::Platform
when String then
arch = arch.split '-'
if arch.length > 2 and arch.last !~ /\d/ # reassemble x86-linux-gnu
if arch.length > 2 and arch.last !~ /\d+(\.\d+)?$/ # reassemble x86-linux-{libc}
extra = arch.pop
arch.last << "-#{extra}"
end
@ -121,10 +121,6 @@ class Gem::Platform
end
end
def inspect
"%s @cpu=%p, @os=%p, @version=%p>" % [super[0..-2], *to_a]
end
def to_a
[@cpu, @os, @version]
end
@ -150,7 +146,8 @@ class Gem::Platform
##
# Does +other+ match this platform? Two platforms match if they have the
# same CPU, or either has a CPU of 'universal', they have the same OS, and
# they have the same version, or either has no version.
# they have the same version, or either has no version (except for 'linux'
# where the version is the libc name, with no version standing for 'gnu')
#
# Additionally, the platform will match if the local CPU is 'arm' and the
# other CPU starts with "arm" (for generic ARM family support).
@ -166,7 +163,10 @@ class Gem::Platform
@os == other.os and
# version
(@version.nil? or other.version.nil? or @version == other.version)
(
(@os != 'linux' and (@version.nil? or other.version.nil?)) or
@version == other.version
)
end
##

Просмотреть файл

@ -78,6 +78,7 @@ class Gem::RemoteFetcher
# fetching the gem.
def initialize(proxy=nil, dns=nil, headers={})
require 'rubygems/core_ext/tcpsocket_init' if Gem.configuration.ipv4_fallback_enabled
require 'net/http'
require 'stringio'
require 'uri'
@ -295,7 +296,7 @@ class Gem::RemoteFetcher
data = fetch_path(uri, mtime)
if data == nil # indicates the server returned 304 Not Modified
if data.nil? # indicates the server returned 304 Not Modified
return Gem.read_binary(path)
end

Просмотреть файл

@ -190,7 +190,7 @@ class Gem::Requirement
end
def hash # :nodoc:
requirements.sort.hash
requirements.map {|r| r.first == "~>" ? [r[0], r[1].to_s] : r }.sort.hash
end
def marshal_dump # :nodoc:

Просмотреть файл

@ -35,9 +35,12 @@ class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification
##
# The required_ruby_version constraint for this specification
#
# A fallback is included because when generated, some marshalled specs have it
# set to +nil+.
def required_ruby_version
spec.required_ruby_version
spec.required_ruby_version || Gem::Requirement.default
end
##

Просмотреть файл

@ -26,6 +26,13 @@ module Gem::Resolver::Molinillo
end
end
# (see Gem::Resolver::Molinillo::SpecificationProvider#dependencies_equal?)
def dependencies_equal?(dependencies, other_dependencies)
with_no_such_dependency_error_handling do
specification_provider.dependencies_equal?(dependencies, other_dependencies)
end
end
# (see Gem::Resolver::Molinillo::SpecificationProvider#name_for)
def name_for(dependency)
with_no_such_dependency_error_handling do

Просмотреть файл

@ -1,6 +1,5 @@
# frozen_string_literal: true
require 'set'
require 'tsort'
require_relative 'dependency_graph/log'

Просмотреть файл

@ -59,7 +59,7 @@ module Gem::Resolver::Molinillo
# @param [Set<Vertex>] vertices the set to add the predecessors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is a
# {#descendent?}
def _recursive_predecessors(vertices = Set.new)
def _recursive_predecessors(vertices = new_vertex_set)
incoming_edges.each do |edge|
vertex = edge.origin
next unless vertices.add?(vertex)
@ -85,7 +85,7 @@ module Gem::Resolver::Molinillo
# @param [Set<Vertex>] vertices the set to add the successors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is an
# {#ancestor?}
def _recursive_successors(vertices = Set.new)
def _recursive_successors(vertices = new_vertex_set)
outgoing_edges.each do |edge|
vertex = edge.destination
next unless vertices.add?(vertex)
@ -138,7 +138,7 @@ module Gem::Resolver::Molinillo
# @param [Vertex] other the vertex to check if there's a path to
# @param [Set<Vertex>] visited the vertices of {#graph} that have been visited
# @return [Boolean] whether there is a path to `other` from `self`
def _path_to?(other, visited = Set.new)
def _path_to?(other, visited = new_vertex_set)
return false unless visited.add?(self)
return true if equal?(other)
successors.any? { |v| v._path_to?(other, visited) }
@ -147,12 +147,18 @@ module Gem::Resolver::Molinillo
# Is there a path from `other` to `self` following edges in the
# dependency graph?
# @return true iff there is a path following edges within this {#graph}
# @return whether there is a path following edges within this {#graph}
def ancestor?(other)
other.path_to?(self)
end
alias is_reachable_from? ancestor?
def new_vertex_set
require 'set'
Set.new
end
private :new_vertex_set
end
end
end

Просмотреть файл

@ -121,7 +121,7 @@ module Gem::Resolver::Molinillo
t = ''.dup
depth = 2
tree.each do |req|
t << ' ' * depth << req.to_s
t << ' ' * depth << printable_requirement.call(req)
unless tree.last == req
if spec = conflict.activated_by_name[name_for(req)]
t << %( was resolved to #{version_for_spec.call(spec)}, which)

Просмотреть файл

@ -45,6 +45,17 @@ module Gem::Resolver::Molinillo
true
end
# Determines whether two arrays of dependencies are equal, and thus can be
# grouped.
#
# @param [Array<Object>] dependencies
# @param [Array<Object>] other_dependencies
# @return [Boolean] whether `dependencies` and `other_dependencies` should
# be considered equal.
def dependencies_equal?(dependencies, other_dependencies)
dependencies == other_dependencies
end
# Returns the name for the given `dependency`.
# @note This method should be 'pure', i.e. the return value should depend
# only on the `dependency` parameter.

Просмотреть файл

@ -329,11 +329,11 @@ module Gem::Resolver::Molinillo
# Look for past conflicts that could be unwound to affect the
# requirement tree for the current conflict
all_reqs = last_detail_for_current_unwind.all_requirements
all_reqs_size = all_reqs.size
relevant_unused_unwinds = unused_unwind_options.select do |alternative|
intersecting_requirements =
last_detail_for_current_unwind.all_requirements &
alternative.requirements_unwound_to_instead
next if intersecting_requirements.empty?
diff_reqs = all_reqs - alternative.requirements_unwound_to_instead
next if diff_reqs.size == all_reqs_size
# Find the highest index unwind whilst looping through
current_detail = alternative if alternative > current_detail
alternative
@ -344,8 +344,12 @@ module Gem::Resolver::Molinillo
state.unused_unwind_options += unwind_details.reject { |detail| detail.state_index == -1 }
# Update the requirements_unwound_to_instead on any relevant unused unwinds
relevant_unused_unwinds.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
unwind_details.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
relevant_unused_unwinds.each do |d|
(d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
end
unwind_details.each do |d|
(d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
end
current_detail
end
@ -803,7 +807,7 @@ module Gem::Resolver::Molinillo
possibilities.reverse_each do |possibility|
dependencies = dependencies_for(possibility)
if current_possibility_set && current_possibility_set.dependencies == dependencies
if current_possibility_set && dependencies_equal?(current_possibility_set.dependencies, dependencies)
current_possibility_set.possibilities.unshift(possibility)
else
possibility_sets.unshift(PossibilitySet.new(dependencies, [possibility]))

Просмотреть файл

@ -182,6 +182,7 @@ class Gem::Specification < Gem::BasicSpecification
@@default_value[k].nil?
end
@@stubs = nil
@@stubs_by_name = {}
# Sentinel object to represent "not found" stubs
@ -665,6 +666,9 @@ class Gem::Specification < Gem::BasicSpecification
#
# # Only prereleases or final releases after 2.6.0.preview2
# spec.required_ruby_version = '> 2.6.0.preview2'
#
# # This gem will work with 2.3.0 or greater, including major version 3, but lesser than 4.0.0
# spec.required_ruby_version = '>= 2.3', '< 4'
def required_ruby_version=(req)
@required_ruby_version = Gem::Requirement.create req
@ -800,10 +804,8 @@ class Gem::Specification < Gem::BasicSpecification
def self.stubs
@@stubs ||= begin
pattern = "*.gemspec"
stubs = installed_stubs(dirs, pattern) + default_stubs(pattern)
stubs = stubs.uniq {|stub| stub.full_name }
stubs = stubs_for_pattern(pattern, false)
_resort!(stubs)
@@stubs_by_name = stubs.select {|s| Gem::Platform.match_spec? s }.group_by(&:name)
stubs
end
@ -820,31 +822,40 @@ class Gem::Specification < Gem::BasicSpecification
end
end
EMPTY = [].freeze # :nodoc:
##
# Returns a Gem::StubSpecification for installed gem named +name+
# only returns stubs that match Gem.platforms
def self.stubs_for(name)
if @@stubs_by_name[name]
@@stubs_by_name[name]
if @@stubs
@@stubs_by_name[name] || []
else
pattern = "#{name}-*.gemspec"
stubs = installed_stubs(dirs, pattern).select {|s| Gem::Platform.match_spec? s } + default_stubs(pattern)
stubs = stubs.uniq {|stub| stub.full_name }.group_by(&:name)
stubs.each_value {|v| _resort!(v) }
@@stubs_by_name.merge! stubs
@@stubs_by_name[name] ||= EMPTY
@@stubs_by_name[name] ||= stubs_for_pattern("#{name}-*.gemspec").select do |s|
s.name == name
end
end
end
##
# Finds stub specifications matching a pattern from the standard locations,
# optionally filtering out specs not matching the current platform
#
def self.stubs_for_pattern(pattern, match_platform = true) # :nodoc:
installed_stubs = installed_stubs(Gem::Specification.dirs, pattern)
installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform
stubs = installed_stubs + default_stubs(pattern)
stubs = stubs.uniq {|stub| stub.full_name }
_resort!(stubs)
stubs
end
def self._resort!(specs) # :nodoc:
specs.sort! do |a, b|
names = a.name <=> b.name
next names if names.nonzero?
b.version <=> a.version
versions = b.version <=> a.version
next versions if versions.nonzero?
b.platform == Gem::Platform::RUBY ? -1 : 1
end
end
@ -1080,20 +1091,15 @@ class Gem::Specification < Gem::BasicSpecification
end
def self._latest_specs(specs, prerelease = false) # :nodoc:
result = Hash.new {|h,k| h[k] = {} }
native = {}
result = {}
specs.reverse_each do |spec|
next if spec.version.prerelease? unless prerelease
native[spec.name] = spec.version if spec.platform == Gem::Platform::RUBY
result[spec.name][spec.platform] = spec
result[spec.name] = spec
end
result.map(&:last).map(&:values).flatten.reject do |spec|
minimum = native[spec.name]
minimum && spec.version < minimum
end.sort_by{|tup| tup.name }
result.map(&:last).flatten.sort_by{|tup| tup.name }
end
##
@ -1552,7 +1558,6 @@ class Gem::Specification < Gem::BasicSpecification
def build_extensions # :nodoc:
return if default_gem?
return if extensions.empty?
return if installed_by_version < Gem::Version.new('2.2.0.preview.2')
return if File.exist? gem_build_complete_path
return if !File.writable?(base_dir)
return if !File.exist?(File.join(base_dir, 'extensions'))
@ -2123,7 +2128,6 @@ class Gem::Specification < Gem::BasicSpecification
def missing_extensions?
return false if default_gem?
return false if extensions.empty?
return false if installed_by_version < Gem::Version.new('2.2.0.preview.2')
return false if File.exist? gem_build_complete_path
true
@ -2548,7 +2552,7 @@ class Gem::Specification < Gem::BasicSpecification
begin
dependencies.each do |dep|
next unless dep.runtime?
dep.to_specs.each do |dep_spec|
dep.matching_specs(true).each do |dep_spec|
next if visited.has_key?(dep_spec)
visited[dep_spec] = true
trail.push(dep_spec)

Просмотреть файл

@ -301,7 +301,9 @@ class Gem::TestCase < Minitest::Test
def setup
@orig_env = ENV.to_hash
@tmp = Dir.mktmpdir("tmp", Dir.pwd)
@tmp = File.expand_path("tmp")
FileUtils.mkdir_p @tmp
ENV['GEM_VENDOR'] = nil
ENV['GEMRC'] = nil
@ -310,7 +312,6 @@ class Gem::TestCase < Minitest::Test
ENV['XDG_DATA_HOME'] = nil
ENV['SOURCE_DATE_EPOCH'] = nil
ENV['BUNDLER_VERSION'] = nil
ENV["TMPDIR"] = @tmp
@current_dir = Dir.pwd
@fetcher = nil
@ -321,13 +322,10 @@ class Gem::TestCase < Minitest::Test
# capture output
Gem::DefaultUserInteraction.ui = Gem::MockGemUi.new
tmpdir = File.realpath Dir.tmpdir
tmpdir.tap(&Gem::UNTAINT)
@tempdir = File.join(tmpdir, "test_rubygems_#{$$}")
@tempdir = Dir.mktmpdir("test_rubygems_", @tmp)
@tempdir.tap(&Gem::UNTAINT)
FileUtils.mkdir_p @tempdir
ENV["TMPDIR"] = @tempdir
@orig_SYSTEM_WIDE_CONFIG_FILE = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE
Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
@ -366,7 +364,9 @@ class Gem::TestCase < Minitest::Test
Dir.chdir @tempdir
ENV['HOME'] = @userhome
Gem.instance_variable_set :@config_file, nil
Gem.instance_variable_set :@user_home, nil
Gem.instance_variable_set :@config_home, nil
Gem.instance_variable_set :@data_home, nil
Gem.instance_variable_set :@gemdeps, nil
Gem.instance_variable_set :@env_requirements_by_name, nil
@ -449,7 +449,6 @@ class Gem::TestCase < Minitest::Test
Dir.chdir @current_dir
FileUtils.rm_rf @tempdir
FileUtils.rm_rf @tmp
ENV.replace(@orig_env)

Просмотреть файл

@ -138,12 +138,12 @@ RSpec.describe "bundle executable" do
it "doesn't print defaults" do
install_gemfile "", :verbose => true
expect(out).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}")
expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}")
end
it "doesn't print defaults" do
install_gemfile "", :verbose => true
expect(out).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}")
expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}")
end
end

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше