diff options
author | Hiroshi SHIBATA <[email protected]> | 2021-07-07 14:07:29 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2021-07-07 15:31:52 +0900 |
commit | c082c6eb7c786a432bea23cf78839f64585cb630 () | |
tree | e3c608264fe03645e905fe7284d713cff87b87dd | |
parent | 6e2240a2f954c84ed12357382c9c065ae4b91e11 (diff) |
Sync RubyGems and Bundler with upstream
Notes: Merged: https://.com/ruby/ruby/pull/4634
52 files changed, 477 insertions, 466 deletions
@@ -37,7 +37,7 @@ module Bundler environment_preserver = EnvironmentPreserver.from_env ORIGINAL_ENV = environment_preserver.restore environment_preserver.replace_with_backup - SUDO_MUTEX = Mutex.new autoload :Definition, File.expand_path("bundler/definition", __dir__) autoload :Dependency, File.expand_path("bundler/dependency", __dir__) @@ -100,8 +100,11 @@ module Bundler files_not_readable_or_writable = [] files_not_rw_and_owned_by_different_user = [] files_not_owned_by_current_user_but_still_rw = [] Find.find(Bundler.bundle_path.to_s).each do |f| - if !File.writable?(f) || !File.readable?(f) if File.stat(f).uid != Process.uid files_not_rw_and_owned_by_different_user << f else @@ -113,6 +116,13 @@ module Bundler end ok = true if files_not_owned_by_current_user_but_still_rw.any? Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \ "user, but are still readable/writable. These files are:\n - #{files_not_owned_by_current_user_but_still_rw.join("\n - ")}" @@ -104,7 +104,7 @@ module Bundler private def warn_if_root - return if Bundler.settings[:silence_root_warning] || Bundler::WINDOWS || !Process.uid.zero? Bundler.ui.warn "Don't run Bundler as root. Bundler can ask for sudo " \ "if it is needed, and installing your bundle as root will break this " \ "application for all non-root users on this machine.", :wrap => true @@ -5,7 +5,7 @@ require "set" module Bundler class CompactIndexClient - DEBUG_MUTEX = Mutex.new def self.debug return unless ENV["DEBUG_COMPACT_INDEX"] DEBUG_MUTEX.synchronize { warn("[#{self}] #{yield}") } @@ -25,7 +25,7 @@ module Bundler @endpoints = Set.new @info_checksums_by_name = {} @parsed_checksums = false - @mutex = Mutex.new end def execution_mode=(block) @@ -65,19 +65,19 @@ module Bundler end def mswin? - Bundler::WINDOWS end def mswin64? - Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin64" && Bundler.local_platform.cpu == "x64" end def mingw? - Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu != "x64" end def x64_mingw? - Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu == "x64" end (KNOWN_MINOR_VERSIONS + KNOWN_MAJOR_VERSIONS).each do |version| @@ -61,10 +61,8 @@ module Bundler @unlocking_bundler = false @unlocking = unlock else - unlock = unlock.dup @unlocking_bundler = unlock.delete(:bundler) - unlock.delete_if {|_k, v| Array(v).empty? } - @unlocking = !unlock.empty? end @dependencies = dependencies @@ -111,8 +109,8 @@ module Bundler @locked_platforms = [] end - @locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) } - @multisource_allowed = @locked_gem_sources.any?(&:multiple_remotes?) && Bundler.frozen_bundle? if @multisource_allowed unless sources.aggregate_global_source? @@ -121,7 +119,7 @@ module Bundler Bundler::SharedHelpers.major_deprecation 2, msg end - @sources.merged_gem_lockfile_sections! end @unlock[:sources] ||= [] @@ -506,9 +504,6 @@ module Bundler attr_reader :sources private :sources - attr_reader :locked_gem_sources - private :locked_gem_sources - def nothing_changed? !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform end @@ -636,35 +631,11 @@ module Bundler end end - def converge_rubygems_sources - return false unless multisource_allowed? - - 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 - locked_gem_sources.each do |locked_gem_source| - # Merge the remotes from the Gemfile into the Gemfile.lock - changes |= locked_gem_source.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes]) - end - - changes - end - def converge_sources - changes = false - - changes |= converge_rubygems_sources - # Replace the sources from the Gemfile with the sources from the Gemfile.lock, # if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent # source in the Gemfile.lock, use the one from the Gemfile. - changes |= sources.replace_sources!(@locked_sources) sources.all_sources.each do |source| # If the source is unlockable and the current command allows an unlock of @@ -913,14 +884,13 @@ module Bundler end def additional_base_requirements_for_resolve - return [] unless @locked_gems dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) } @locked_gems.specs.reduce({}) do |requirements, locked_spec| name = locked_spec.name dependency = dependencies_by_name[name] - next requirements unless dependency 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.get_proxy(dep, locked_spec.platform) requirements @@ -24,9 +24,6 @@ module Bundler def initialize @source = nil @sources = SourceList.new - - @global_rubygems_sources = [] - @git_sources = {} @dependencies = [] @groups = [] @@ -48,7 +45,6 @@ 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"} " \ @@ -168,7 +164,7 @@ module Bundler elsif block_given? with_source(@sources.add_rubygems_source("remotes" => source), &blk) else - @global_rubygems_sources << source end end @@ -222,6 +218,7 @@ module Bundler end def to_definition(lockfile, unlock) Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles) end @@ -453,12 +450,7 @@ repo_name ||= user_name 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.bundler_3_mode? msg = "This Gemfile contains multiple primary sources. " \ @@ -135,7 +135,7 @@ module Bundler next end - mode = Bundler::WINDOWS ? "wb:UTF-8" : "w" require "erb" content = if RUBY_VERSION >= "2.6" ERB.new(template, :trim_mode => "-").result(binding) @@ -144,7 +144,7 @@ module Bundler end File.write(binstub_path, content, :mode => mode, :perm => 0o777 & ~File.umask) - if Bundler::WINDOWS || options[:all_platforms] prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n" File.write("#{binstub_path}.cmd", prefix + content, :mode => mode) end @@ -182,7 +182,7 @@ module Bundler executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path) executable_path = executable_path - mode = Bundler::WINDOWS ? "wb:UTF-8" : "w" require "erb" content = if RUBY_VERSION >= "2.6" ERB.new(template, :trim_mode => "-").result(binding) @@ -191,7 +191,7 @@ module Bundler end File.write("#{bin_path}/#{executable}", content, :mode => mode, :perm => 0o755) - if Bundler::WINDOWS || options[:all_platforms] prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n" File.write("#{bin_path}/#{executable}.cmd", prefix + content, :mode => mode) end @@ -1,16 +1,5 @@ # frozen_string_literal: true -#-- -# Some versions of the Bundler 1.1 RC series introduced corrupted -# lockfiles. There were two major problems: -# -# * multiple copies of the same GIT section appeared in the lockfile -# * when this happened, those sections got multiple copies of gems -# in those sections. -# -# As a result, Bundler 1.1 contains code that fixes the earlier -# corruption. We will remove this fix-up code in Bundler 1.2. - module Bundler class LockfileParser attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version @@ -124,12 +113,7 @@ module Bundler @sources << @current_source when GIT @current_source = TYPES[@type].from_lock(@opts) - # Strip out duplicate GIT sections - if @sources.include?(@current_source) - @current_source = @sources.find {|s| s == @current_source } - else - @sources << @current_source - end when GEM @opts["remotes"] = Array(@opts.delete("remote")).reverse @current_source = TYPES[@type].from_lock(@opts) @@ -212,9 +196,7 @@ module Bundler @current_spec = LazySpecification.new(name, version, platform) @current_spec.source = @current_source - # Avoid introducing multiple copies of the same spec (caused by - # duplicate GIT sections) - @specs[@current_spec.identifier] ||= @current_spec elsif spaces.size == 6 version = version.split(",").map(&:strip) if version dep = Gem::Dependency.new(name, version) @@ -77,7 +77,7 @@ module Bundler source_list = SourceList.new source_list.add_git_source(git_source_options) if git_source_options - source_list.global_rubygems_source = rubygems_source if rubygems_source deps = names.map {|name| Dependency.new name, version } @@ -134,6 +134,8 @@ module Gem class Requirement module OrderIndependentComparison def ==(other) if _requirements_sorted? && other._requirements_sorted? super else @@ -252,19 +252,6 @@ module Bundler other_remotes.map(&method(:remove_auth)) == @remotes.map(&method(:remove_auth)) end - def replace_remotes(other_remotes, allow_equivalent = false) - return false if other_remotes == @remotes - - equivalent = allow_equivalent && equivalent_remotes?(other_remotes) - - @remotes = [] - other_remotes.reverse_each do |r| - add_remote r.to_s - end - - !equivalent - end - def spec_names if @allow_remote && dependency_api_available? remote_specs.spec_names @@ -28,8 +28,9 @@ module Bundler @merged_gem_lockfile_sections end - def merged_gem_lockfile_sections! @merged_gem_lockfile_sections = true end def aggregate_global_source? @@ -53,18 +54,17 @@ module Bundler end def add_rubygems_source(options = {}) - add_source_to_list Source::Rubygems.new(options), @rubygems_sources end def add_plugin_source(source, options = {}) add_source_to_list Plugin.source(source).new(options), @plugin_sources end - def global_rubygems_source=(uri) - @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri, "allow_local" => true) - end - - def add_rubygems_remote(uri) global_rubygems_source.add_remote(uri) global_rubygems_source end @@ -109,27 +109,26 @@ module Bundler if merged_gem_lockfile_sections? [combine_rubygems_sources] else - rubygems_sources.sort_by(&:to_s).uniq end end # Returns true if there are changes def replace_sources!(replacement_sources) - return true if replacement_sources.empty? - [path_sources, git_sources, plugin_sources].each do |source_list| - source_list.map! do |source| - replacement_sources.find {|s| s == source } || source - end - end - replacement_rubygems = merged_gem_lockfile_sections? && - replacement_sources.detect {|s| s.is_a?(Source::Rubygems) } - @global_rubygems_source = replacement_rubygems if replacement_rubygems - return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources) - false end def local_only! @@ -146,6 +145,24 @@ module Bundler private def rubygems_aggregate_class Source::Rubygems end @@ -27,7 +27,7 @@ class Bundler::ConnectionPool # @!visibility private def initialize - @mutex = Mutex.new @last_time = Time.now.to_f end @@ -39,8 +39,8 @@ class Bundler::ConnectionPool::TimedStack @created = 0 @que = [] @max = size - @mutex = Mutex.new - @resource = ConditionVariable.new @shutdown_block = nil end @@ -21,8 +21,8 @@ module Bundler # @param func [Proc] job to run in inside the worker pool def initialize(size, name, func) @name = name - @request_queue = Queue.new - @response_queue = Queue.new @func = func @size = size @threads = nil @@ -178,7 +178,7 @@ module Gem @configuration = nil @gemdeps = nil @loaded_specs = {} - LOADED_SPECS_MUTEX = Mutex.new @path_to_default_spec_map = {} @platforms = [] @ruby = nil @@ -11,10 +11,10 @@ module CoreExtensions 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 = () @@ -1,23 +1,70 @@ # frozen_string_literal: true ## -# Provides a single method +deprecate+ to be used to declare when -# something is going away. # # class Legacy -# def self.klass_method # # ... # end # -# def instance_method # # ... # end # # extend Gem::Deprecate -# deprecate :instance_method, "X.z", 2011, 4 # # class << self # extend Gem::Deprecate -# deprecate :klass_method, :none, 2011, 4 # end # end @@ -52,6 +52,13 @@ module Gem::GemcutterUtilities end ## # The host to connect to either from the RUBYGEMS_HOST environment variable # or from the user's configuration @@ -126,7 +133,7 @@ module Gem::GemcutterUtilities response = rubygems_api_request(:put, "api/v1/api_key", sign_in_host, scope: scope) do |request| request.basic_auth email, password - request["OTP"] = options[:otp] if options[:otp] request.body = URI.encode_www_form({:api_key => api_key }.merge(update_scope_params)) end @@ -159,7 +166,7 @@ module Gem::GemcutterUtilities response = rubygems_api_request(:post, "api/v1/api_key", sign_in_host, scope: scope) do |request| request.basic_auth email, password - request["OTP"] = options[:otp] if options[:otp] request.body = URI.encode_www_form({ name: key_name }.merge(scope_params)) end @@ -224,7 +231,7 @@ module Gem::GemcutterUtilities request_method = Net::HTTP.const_get method.to_s.capitalize Gem::RemoteFetcher.fetcher.request(uri, request_method) do |req| - req["OTP"] = options[:otp] if options[:otp] block.call(req) end end @@ -68,7 +68,7 @@ class Gem::Installer @path_warning = false - @install_lock = Mutex.new class << self ## @@ -4,7 +4,7 @@ require 'rubygems/request' require 'rubygems/request/connection_pools' require 'rubygems/s3_uri_signer' require 'rubygems/uri_formatter' -require 'rubygems/uri_parsing' require 'rubygems/user_interaction' require 'resolv' @@ -14,15 +14,12 @@ require 'resolv' class Gem::RemoteFetcher include Gem::UserInteraction - include Gem::UriParsing ## # A FetchError exception wraps up the various possible IO and HTTP failures # that could happen while downloading from the internet. class FetchError < Gem::Exception - include Gem::UriParsing - ## # The URI which was being accessed when the exception happened. @@ -31,7 +28,7 @@ class Gem::RemoteFetcher def initialize(message, uri) super message - uri = parse_uri(uri) @original_uri = uri.dup @@ -88,7 +85,7 @@ class Gem::RemoteFetcher @proxy = proxy @pools = {} - @pool_lock = Mutex.new @cert_files = Gem::Request.get_cert_files @headers = headers @@ -133,7 +130,7 @@ class Gem::RemoteFetcher require "fileutils" FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir - source_uri = parse_uri(source_uri) scheme = source_uri.scheme @@ -228,7 +225,7 @@ class Gem::RemoteFetcher unless location = response['Location'] raise FetchError.new("redirecting but no redirect location was given", uri) end - location = parse_uri location if https?(uri) && !https?(location) raise FetchError.new("redirecting to non-https resource: #{location}", uri) @@ -246,7 +243,7 @@ class Gem::RemoteFetcher # Downloads +uri+ and returns it as a String. def fetch_path(uri, mtime = nil, head = false) - uri = parse_uri uri unless uri.scheme raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}" @@ -11,7 +11,7 @@ class Gem::Request::ConnectionPools # :nodoc: @proxy_uri = proxy_uri @cert_files = cert_files @pools = {} - @pool_mutex = Mutex.new end def pool_for(uri) @@ -12,7 +12,7 @@ class Gem::Request::HTTPPool # :nodoc: @http_args = http_args @cert_files = cert_files @proxy_uri = proxy_uri - @queue = SizedQueue.new 1 @queue << nil end @@ -151,7 +151,7 @@ class Gem::RequestSet @prerelease = options[:prerelease] requests = [] - download_queue = Queue.new # Create a thread-safe list of gems to download sorted_requests.each do |req| @@ -105,7 +105,7 @@ class Gem::Specification < Gem::BasicSpecification # rubocop:disable Style/MutableConstant LOAD_CACHE = {} # :nodoc: # rubocop:enable Style/MutableConstant - LOAD_CACHE_MUTEX = Mutex.new private_constant :LOAD_CACHE if defined? private_constant @@ -5,10 +5,18 @@ # class Gem::UriParser ## # Parses the #uri, raising if it's invalid def parse!(uri) raise URI::InvalidURIError unless uri # Always escape URI's to deal with potential spaces and such @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -require "rubygems/uri_parser" - -module Gem::UriParsing - - def parse_uri(source_uri) - return source_uri unless source_uri.is_a?(String) - - uri_parser.parse(source_uri) - end - - private :parse_uri - - def uri_parser - require "uri" - - Gem::UriParser.new - end - - private :uri_parser - -end @@ -543,7 +543,7 @@ class Gem::StreamUI # A progress reporter that behaves nicely with threaded downloading. class ThreadedDownloadReporter - MUTEX = Mutex.new ## # The current file name being displayed @@ -2,16 +2,6 @@ require "bundler/cli" -using Module.new { - # Some `man` (e.g., on macOS) always highlights the output even to - # non-tty. - refine Spec::Helpers do - def out - super.gsub(/.[\b]/, "") - end - end -} if RUBY_VERSION >= "2.4" - RSpec.describe "bundle executable" do it "returns non-zero exit status when passed unrecognized options" do bundle "--invalid_argument", :raise_on_error => false @@ -42,49 +32,57 @@ RSpec.describe "bundle executable" do it "aliases e to exec" do bundle "e --help" - expect(out).to include("bundle-exec") end it "aliases ex to exec" do bundle "ex --help" - expect(out).to include("bundle-exec") end it "aliases exe to exec" do bundle "exe --help" - expect(out).to include("bundle-exec") end it "aliases c to check" do bundle "c --help" - expect(out).to include("bundle-check") end it "aliases i to install" do bundle "i --help" - expect(out).to include("bundle-install") end it "aliases ls to list" do bundle "ls --help" - expect(out).to include("bundle-list") end it "aliases package to cache" do bundle "package --help" - expect(out).to include("bundle-cache") end it "aliases pack to cache" do bundle "pack --help" - expect(out).to include("bundle-cache") end end @@ -204,7 +204,7 @@ RSpec.describe Bundler::Definition do context "eager unlock" do let(:source_list) do Bundler::SourceList.new.tap do |source_list| - source_list.global_rubygems_source = file_uri_for(gem_repo4) end end @@ -115,15 +115,15 @@ RSpec.describe Bundler::SourceList do end end - describe "#add_rubygems_remote", :bundler => "< 3" do - let!(:returned_source) { source_list.add_rubygems_remote("https://rubygems.org/") } it "returns the aggregate rubygems source" do expect(returned_source).to be_instance_of(Bundler::Source::Rubygems) end it "adds the provided remote to the beginning of the aggregate source" do - source_list.add_rubygems_remote("https://othersource.org") expect(returned_source.remotes).to eq [ Bundler::URI("https://othersource.org/"), Bundler::URI("https://rubygems.org/"), @@ -212,22 +212,22 @@ RSpec.describe Bundler::SourceList do describe "#path_sources" do it "returns an empty array when no path sources have been added" do - source_list.add_rubygems_remote("https://rubygems.org") source_list.add_git_source("uri" => "git://host/path.git") expect(source_list.path_sources).to be_empty end it "returns path sources in the reverse order that they were added" do source_list.add_git_source("uri" => "git://third-git.org/path.git") - source_list.add_rubygems_remote("https://fifth-rubygems.org") source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_remote("https://fourth-rubygems.org") source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_remote("https://third-rubygems.org") source_list.add_git_source("uri" => "git://second-git.org/path.git") - source_list.add_rubygems_remote("https://second-rubygems.org") source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_remote("https://first-rubygems.org") source_list.add_git_source("uri" => "git://first-git.org/path.git") expect(source_list.path_sources).to eq [ @@ -240,7 +240,7 @@ RSpec.describe Bundler::SourceList do describe "#git_sources" do it "returns an empty array when no git sources have been added" do - source_list.add_rubygems_remote("https://rubygems.org") source_list.add_path_source("path" => "/path/to/gem") expect(source_list.git_sources).to be_empty @@ -248,15 +248,15 @@ RSpec.describe Bundler::SourceList do it "returns git sources in the reverse order that they were added" do source_list.add_git_source("uri" => "git://third-git.org/path.git") - source_list.add_rubygems_remote("https://fifth-rubygems.org") source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_remote("https://fourth-rubygems.org") source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_remote("https://third-rubygems.org") source_list.add_git_source("uri" => "git://second-git.org/path.git") - source_list.add_rubygems_remote("https://second-rubygems.org") source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_remote("https://first-rubygems.org") source_list.add_git_source("uri" => "git://first-git.org/path.git") expect(source_list.git_sources).to eq [ @@ -269,7 +269,7 @@ RSpec.describe Bundler::SourceList do describe "#plugin_sources" do it "returns an empty array when no plugin sources have been added" do - source_list.add_rubygems_remote("https://rubygems.org") source_list.add_path_source("path" => "/path/to/gem") expect(source_list.plugin_sources).to be_empty @@ -279,13 +279,13 @@ RSpec.describe Bundler::SourceList do source_list.add_plugin_source("new_source", "uri" => "https://third-git.org/path.git") source_list.add_git_source("https://new-git.org") source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_remote("https://fourth-rubygems.org") source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_remote("https://third-rubygems.org") source_list.add_plugin_source("new_source", "uri" => "git://second-git.org/path.git") - source_list.add_rubygems_remote("https://second-rubygems.org") source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_remote("https://first-rubygems.org") source_list.add_plugin_source("new_source", "uri" => "git://first-git.org/path.git") expect(source_list.plugin_sources).to eq [ @@ -339,7 +339,7 @@ RSpec.describe Bundler::SourceList do describe "#get" do context "when it includes an equal source" do let(:rubygems_source) { Bundler::Source::Rubygems.new("remotes" => ["https://rubygems.org"]) } - before { @equal_source = source_list.add_rubygems_remote("https://rubygems.org") } it "returns the equal source" do expect(source_list.get(rubygems_source)).to be @equal_source @@ -32,6 +32,8 @@ RSpec.describe "bundle doctor" do unwritable_file = double("file") allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [unwritable_file] } allow(File).to receive(:stat).with(unwritable_file) { stat } allow(stat).to receive(:uid) { Process.uid } allow(File).to receive(:writable?).with(unwritable_file) { true } @@ -47,7 +49,6 @@ RSpec.describe "bundle doctor" do doctor = Bundler::CLI::Doctor.new({}) expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"] expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"] - allow(File).to receive(:exist?).and_call_original allow(File).to receive(:exist?).with("/usr/lib/libSystem.dylib").and_return(true) expect { doctor.run }.not_to(raise_error, @stdout.string) expect(@stdout.string).to be_empty @@ -57,7 +58,6 @@ RSpec.describe "bundle doctor" do doctor = Bundler::CLI::Doctor.new({}) expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"] expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"] - allow(File).to receive(:exist?).and_call_original allow(File).to receive(:exist?).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(false) expect { doctor.run }.to raise_error(Bundler::ProductionError, strip_whitespace(<<-E).strip), @stdout.string The following gems are missing OS dependencies: @@ -67,12 +67,32 @@ RSpec.describe "bundle doctor" do end end context "when home contains files that are not readable/writable" do before(:each) do @stat = double("stat") @unwritable_file = double("file") allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@unwritable_file] } allow(File).to receive(:stat).with(@unwritable_file) { @stat } end @@ -241,6 +241,94 @@ RSpec.describe "bundle update" do expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1") end it "should still downgrade if forced by the Gemfile" do build_repo4 do build_gem "a" @@ -26,6 +26,38 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do end end context "eval-ed Gemfile has relative-path gems" do before do build_lib("a", :path => bundled_app("gems/a")) @@ -1355,4 +1355,74 @@ RSpec.describe "bundle install with gems on multiple sources" do expect(the_bundle).not_to be_locked end end end @@ -399,7 +399,7 @@ The checksum of /versions does not match the checksum provided by the server! So api_request_limit = low_api_request_limit_for(gem_repo2) - install_gemfile <<-G, :artifice => "compact_index_extra_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) source "#{source_uri}" source "#{source_uri}/extra" do gem "back_deps" @@ -421,7 +421,7 @@ The checksum of /versions does not match the checksum provided by the server! So api_request_limit = low_api_request_limit_for(gem_repo4) - install_gemfile <<-G, :artifice => "compact_index_extra_api_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) source "#{source_uri}" source "#{source_uri}/extra" do gem "back_deps" @@ -371,7 +371,7 @@ RSpec.describe "gemcutter's dependency API" do api_request_limit = low_api_request_limit_for(gem_repo2) - install_gemfile <<-G, :artifice => "endpoint_extra_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) source "#{source_uri}" source "#{source_uri}/extra" gem "back_deps" @@ -392,7 +392,7 @@ RSpec.describe "gemcutter's dependency API" do api_request_limit = low_api_request_limit_for(gem_repo2) - install_gemfile <<-G, :artifice => "endpoint_extra_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) source "#{source_uri}" source "#{source_uri}/extra" do gem "back_deps" @@ -181,8 +181,11 @@ RSpec.describe "global gem caching" do bundle :install, :artifice => "compact_index_no_gem", :dir => bundled_app2 # activesupport is installed and both are in the global cache - expect(the_bundle).not_to include_gems "rack 1.0.0", :dir => bundled_app2 - expect(the_bundle).to include_gems "activesupport 2.3.5", :dir => bundled_app2 expect(source_global_cache("rack-1.0.0.gem")).to exist expect(source_global_cache("activesupport-2.3.5.gem")).to exist end @@ -1178,83 +1178,6 @@ RSpec.describe "the lockfile format" do G end - # Some versions of the Bundler 1.1 RC series introduced corrupted - # lockfiles. There were two major problems: - # - # * multiple copies of the same GIT section appeared in the lockfile - # * when this happened, those sections got multiple copies of gems - # in those sections. - it "fixes corrupted lockfiles" do - build_git "omg", :path => lib_path("omg") - revision = revision_for(lib_path("omg")) - - gemfile <<-G - source "#{file_uri_for(gem_repo2)}/" - gem "omg", :git => "#{lib_path("omg")}", :branch => 'master' - G - - bundle "config set --local path vendor" - bundle :install - expect(the_bundle).to include_gems "omg 1.0" - - # Create a Gemfile.lock that has duplicate GIT sections - lockfile <<-L - GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master - specs: - omg (1.0) - - GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master - specs: - omg (1.0) - - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - omg! - - BUNDLED WITH - #{Bundler::VERSION} - L - - FileUtils.rm_rf(bundled_app("vendor")) - bundle "install" - expect(the_bundle).to include_gems "omg 1.0" - - # Confirm that duplicate specs do not appear - lockfile_should_be(<<-L) - GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master - specs: - omg (1.0) - - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - omg! - - BUNDLED WITH - #{Bundler::VERSION} - L - end - it "raises a helpful error message when the lockfile is missing deps" do lockfile <<-L GEM @@ -1326,7 +1249,10 @@ RSpec.describe "the lockfile format" do expect { bundle "update", :all => true }.to change { File.mtime(bundled_app_lock) } expect(File.read(bundled_app_lock)).to match("\r\n") - expect(the_bundle).to include_gems "rack 1.2" end end @@ -211,133 +211,6 @@ RSpec.describe "real world edgecases", :realworld => true do expect(err).to be_empty end - it "checks out git repos when the lockfile is corrupted" do - gemfile <<-G - source "https://rubygems.org" - git_source(:) {|repo| "https://.com/\#{repo}.git" } - - gem 'activerecord', : => 'carlhuda/rails-bundler-test', :branch => 'master' - gem 'activesupport', : => 'carlhuda/rails-bundler-test', :branch => 'master' - gem 'actionpack', : => 'carlhuda/rails-bundler-test', :branch => 'master' - G - - lockfile <<-L - GIT - remote: https://.com/carlhuda/rails-bundler-test.git - revision: 369e28a87419565f1940815219ea9200474589d4 - branch: master - specs: - actionpack (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - erubis (~> 2.7.0) - journey (~> 1.0.1) - rack (~> 1.4.0) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.1.2) - activemodel (3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - activerecord (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activesupport (3.2.2) - i18n (~> 0.6) - multi_json (~> 1.0) - - GIT - remote: https://.com/carlhuda/rails-bundler-test.git - revision: 369e28a87419565f1940815219ea9200474589d4 - branch: master - specs: - actionpack (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - erubis (~> 2.7.0) - journey (~> 1.0.1) - rack (~> 1.4.0) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.1.2) - activemodel (3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - activerecord (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activesupport (3.2.2) - i18n (~> 0.6) - multi_json (~> 1.0) - - GIT - remote: https://.com/carlhuda/rails-bundler-test.git - revision: 369e28a87419565f1940815219ea9200474589d4 - branch: master - specs: - actionpack (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - erubis (~> 2.7.0) - journey (~> 1.0.1) - rack (~> 1.4.0) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.1.2) - activemodel (3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - activerecord (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activesupport (3.2.2) - i18n (~> 0.6) - multi_json (~> 1.0) - - GEM - remote: https://rubygems.org/ - specs: - arel (3.0.2) - builder (3.0.0) - erubis (2.7.0) - hike (1.2.1) - i18n (0.6.0) - journey (1.0.3) - multi_json (1.1.0) - rack (1.4.1) - rack-cache (1.2) - rack (>= 0.4) - rack-test (0.6.1) - rack (>= 1.0) - sprockets (2.1.2) - hike (~> 1.2) - rack (~> 1.0) - tilt (~> 1.1, != 1.3.0) - tilt (1.3.3) - tzinfo (0.3.32) - - PLATFORMS - ruby - - DEPENDENCIES - actionpack! - activerecord! - activesupport! - L - - bundle :lock - expect(err).to be_empty - end - it "outputs a helpful error message when gems have invalid gemspecs" do install_gemfile <<-G, :standalone => true, :raise_on_error => false source 'https://rubygems.org' @@ -349,7 +222,7 @@ RSpec.describe "real world edgecases", :realworld => true do end it "doesn't hang on big gemfile" do - skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" gemfile <<~G # frozen_string_literal: true @@ -461,7 +334,7 @@ RSpec.describe "real world edgecases", :realworld => true do end it "doesn't hang on tricky gemfile" do - skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" gemfile <<~G source 'https://rubygems.org' @@ -487,7 +360,7 @@ RSpec.describe "real world edgecases", :realworld => true do end it "doesn't hang on nix gemfile" do - skip "Only for ruby 3.0.1" if RUBY_VERSION != "3.0.1" gemfile <<~G source "https://rubygems.org" do @@ -4,17 +4,19 @@ require "spec_helper" RSpec.describe "bundle install with complex dependencies", :realworld => true do it "resolves quickly" do - start_time = Time.now - - install_gemfile <<-G source 'https://rubygems.org' gem "actionmailer" gem "mongoid", ">= 0.10.2" G duration = Time.now - start_time - expect(duration.to_f).to be < 120 # seconds end end @@ -13,7 +13,7 @@ require "bundler" require "rspec/core" require "rspec/expectations" require "rspec/mocks" -require "diff/lcs" require_relative "support/builders" require_relative "support/build_metadata" @@ -0,0 +1,16 @@ @@ -7,7 +7,7 @@ Artifice.deactivate class CompactIndexRateLimited < CompactIndexAPI class RequestCounter def self.queue - @queue ||= Queue.new end def self.size @@ -8,7 +8,7 @@ require "artifice" require "sinatra/base" ALL_REQUESTS = [] # rubocop:disable Style/MutableConstant -ALL_REQUESTS_MUTEX = Mutex.new at_exit do if expected = ENV["BUNDLER_SPEC_ALL_REQUESTS"] @@ -35,28 +35,3 @@ module Gem end end end - -if ENV["BUNDLER_SPEC_WINDOWS"] == "true" - require_relative "path" - require "bundler/constants" - - module Bundler - remove_const :WINDOWS if defined?(WINDOWS) - WINDOWS = true - end -end - -if ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"] - require_relative "path" - require "bundler/source" - require "bundler/source/rubygems" - - module Bundler - class Source - class Rubygems < Source - remove_const :API_REQUEST_LIMIT - API_REQUEST_LIMIT = ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"].to_i - end - end - end -end @@ -457,15 +457,11 @@ module Spec end def simulate_windows(platform = mswin) - old = ENV["BUNDLER_SPEC_WINDOWS"] - ENV["BUNDLER_SPEC_WINDOWS"] = "true" simulate_platform platform do simulate_bundler_version_when_missing_prerelease_default_gem_activation do yield end end - ensure - ENV["BUNDLER_SPEC_WINDOWS"] = old end def simulate_bundler_version_when_missing_prerelease_default_gem_activation @@ -118,14 +118,14 @@ module Spec opts[:raise_on_error] = false @errors = names.map do |full_name| name, version, platform = full_name.split(/\s+/) - require_path = name == "bundler" ? "#{lib_dir}/bundler" : name.tr("-", "/") version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name) source_const = "#{Spec::Builders.constantize(name)}_SOURCE" ruby <<~R, opts - require '#{lib_dir}/bundler' Bundler.setup(#{groups}) - require '#{require_path}.rb' actual_version, actual_platform = #{version_const}.split(/\s+/, 2) unless Gem::Version.new(actual_version) == Gem::Version.new('#{version}') puts actual_version @@ -170,7 +170,7 @@ module Spec name, version = name.split(/\s+/, 2) ruby <<-R, opts begin - require '#{lib_dir}/bundler' Bundler.setup(#{groups}) rescue Bundler::GemNotFound, Bundler::GitError exit 0 @@ -71,6 +71,10 @@ module Spec @spec_dir ||= source_root.join(ruby_core? ? "spec/bundler" : "spec") end def man_dir @man_dir ||= lib_dir.join("bundler/man") end @@ -1595,7 +1595,7 @@ class Object metaclass.send :undef_method, name metaclass.send :alias_method, name, new_name metaclass.send :undef_method, new_name - end end require_relative 'utilities' @@ -14,6 +14,7 @@ class TestGemGemcutterUtilities < Gem::TestCase Gem.configuration.disable_default_gem_server = nil ENV['RUBYGEMS_HOST'] = nil Gem.configuration.rubygems_api_key = nil @cmd = Gem::Command.new '', 'summary' @@ -22,6 +23,7 @@ class TestGemGemcutterUtilities < Gem::TestCase def teardown ENV['RUBYGEMS_HOST'] = nil Gem.configuration.rubygems_api_key = nil credential_teardown @@ -186,6 +188,16 @@ class TestGemGemcutterUtilities < Gem::TestCase assert_match %r{Access Denied.}, @sign_in_ui.output end def test_sign_in_with_correct_otp_code api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903' response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." |