Skip to content
9 changes: 9 additions & 0 deletions lib/prism/lex_compat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,15 @@ def result
IgnoreStateToken.new([[lineno, column], event, value, lex_state])
when :on_embexpr_end
IgnoreStateToken.new([[lineno, column], event, value, lex_state])
when :on_words_sep
# Ripper emits one token each per line.
lines = value.lines
lines[0...-1].each do |whitespace|
tokens << Token.new([[lineno, column], event, whitespace, lex_state])
lineno += 1
column = 0
end
Token.new([[lineno, column], event, lines.last, lex_state])
when :on_regexp_end
# On regex end, Ripper scans and then sets end state, so the ripper
# lexed output is begin, when it should be end. prism sets lex state
Expand Down
7 changes: 0 additions & 7 deletions lib/prism/lex_ripper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@ def result
results << token
previous = token
end
when :on_words_sep
if previous[1] == :on_words_sep
previous[2] << token[2]
else
results << token
previous = token
end
else
results << token
previous = token
Expand Down
73 changes: 46 additions & 27 deletions lib/rubygems/bundler_version_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ def self.bundler_version
v ||= bundle_update_bundler_version
return if v == true

v ||= bundle_config_version

v ||= lockfile_version
return unless v

Expand Down Expand Up @@ -49,21 +51,7 @@ def self.lockfile_version
private_class_method :lockfile_version

def self.lockfile_contents
gemfile = ENV["BUNDLE_GEMFILE"]
gemfile = nil if gemfile&.empty?

unless gemfile
begin
Gem::Util.traverse_parents(Dir.pwd) do |directory|
next unless gemfile = Gem::GEM_DEP_FILES.find {|f| File.file?(f) }

gemfile = File.join directory, gemfile
break
end
rescue Errno::ENOENT
return
end
end
gemfile = gemfile_path

return unless gemfile

Expand All @@ -82,19 +70,24 @@ def self.lockfile_contents
private_class_method :lockfile_contents

def self.bundle_config_version
config_file = bundler_config_file
return unless config_file && File.file?(config_file)
version = nil

contents = File.read(config_file)
contents =~ /^BUNDLE_VERSION:\s*["']?([^"'\s]+)["']?\s*$/
[bundler_local_config_file, bundler_global_config_file].each do |config_file|
next unless config_file && File.file?(config_file)

$1
contents = File.read(config_file)
contents =~ /^BUNDLE_VERSION:\s*["']?([^"'\s]+)["']?\s*$/

version = $1
break if version
end

version
end
private_class_method :bundle_config_version

def self.bundler_config_file
# see Bundler::Settings#global_config_file and local_config_file
# global
def self.bundler_global_config_file
# see Bundler::Settings#global_config_file
if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty?
ENV["BUNDLE_CONFIG"]
elsif ENV["BUNDLE_USER_CONFIG"] && !ENV["BUNDLE_USER_CONFIG"].empty?
Expand All @@ -103,10 +96,36 @@ def self.bundler_config_file
ENV["BUNDLE_USER_HOME"] + "config"
elsif Gem.user_home && !Gem.user_home.empty?
Gem.user_home + ".bundle/config"
else
# local
"config"
end
end
private_class_method :bundler_config_file
private_class_method :bundler_global_config_file

def self.bundler_local_config_file
gemfile = gemfile_path
return unless gemfile

File.join(File.dirname(gemfile), ".bundle", "config")
end
private_class_method :bundler_local_config_file

def self.gemfile_path
gemfile = ENV["BUNDLE_GEMFILE"]
gemfile = nil if gemfile&.empty?

unless gemfile
begin
Gem::Util.traverse_parents(Dir.pwd) do |directory|
next unless gemfile = Gem::GEM_DEP_FILES.find {|f| File.file?(f) }

gemfile = File.join directory, gemfile
break
end
rescue Errno::ENOENT
return
end
end

gemfile
end
private_class_method :gemfile_path
end
5 changes: 3 additions & 2 deletions lib/rubygems/version.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require_relative "deprecate"

##
# The Version class processes string versions into comparable
# values. A version string should normally be a series of numbers
Expand Down Expand Up @@ -152,6 +150,9 @@
# For the last example, single-digit versions are automatically extended with
# a zero to give a sensible result.

# Workaround for directly loading Gem::Version in some cases
module Gem; end

class Gem::Version
include Comparable

Expand Down
18 changes: 18 additions & 0 deletions spec/bundler/runtime/self_management_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,24 @@
expect(out).to eq(previous_minor)
end

it "requires the right bundler version from the config and run bundle CLI without re-exec" do
unless Bundler.rubygems.provides?(">= 4.1.0.dev")
skip "This spec can only run when Gem::BundlerVersionFinder.bundler_versions reads bundler configs"
end

lockfile_bundled_with(current_version)

bundle "config set --local version #{previous_minor}"
bundle "config set --local path.system true"
bundle "install"

script = bundled_app("script.rb")
create_file(script, "p 'executed once'")

bundle "-v", env: { "RUBYOPT" => "-r#{script}" }
expect(out).to eq(%("executed once"\n9.3.0))
end

it "does not try to install when using bundle config version global" do
lockfile_bundled_with(previous_minor)

Expand Down
82 changes: 41 additions & 41 deletions spec/bundler/support/builders.rb
Original file line number Diff line number Diff line change
Expand Up @@ -695,54 +695,54 @@ def _default_files

TEST_CERT = <<~CERT
-----BEGIN CERTIFICATE-----
MIIDMjCCAhqgAwIBAgIBATANBgkqhkiG9w0BAQUFADAnMQwwCgYDVQQDDAN5b3Ux
MIIDNTCCAh2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAnMQwwCgYDVQQDDAN5b3Ux
FzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTE1MDIwODAwMTIyM1oXDTQyMDYy
NTAwMTIyM1owJzEMMAoGA1UEAwwDeW91MRcwFQYKCZImiZPyLGQBGRYHZXhhbXBs
ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANlvFdpN43c4DMS9Jo06
m0a7k3bQ3HWQ1yrYhZMi77F1F73NpBknYHIzDktQpGn6hs/4QFJT4m4zNEBF47UL
jHU5nTK5rjkS3niGYUjvh3ZEzVeo9zHUlD/UwflDo4ALl3TSo2KY/KdPS/UTdLXL
ajkQvaVJtEDgBPE3DPhlj5whp+Ik3mDHej7qpV6F502leAwYaFyOtlEG/ZGNG+nZ
L0clH0j77HpP42AylHDi+vakEM3xcjo9BeWQ6Vkboic93c9RTt6CWBWxMQP7Nol1
MOebz9XOSQclxpxWteXNfPRtMdAhmRl76SMI8ywzThNPpa4EH/yz34ftebVOgKyM
nd0CAwEAAaNpMGcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFA7D
n9qo0np23qi3aOYuAAPn/5IdMBYGA1UdEQQPMA2BC3lvdUBleGFtcGxlMBYGA1Ud
EgQPMA2BC3lvdUBleGFtcGxlMA0GCSqGSIb3DQEBBQUAA4IBAQA7Gyk62sWOUX/N
vk4tJrgKESph6Ns8+E36A7n3jt8zCep8ldzMvwTWquf9iqhsC68FilEoaDnUlWw7
d6oNuaFkv7zfrWGLlvqQJC+cu2X5EpcCksg5oRp8VNbwJysJ6JgwosxzROII8eXc
R+j1j6mDvQYqig2QOnzf480pjaqbP+tspfDFZbhKPrgM3Blrb3ZYuFpv4zkqI7aB
6fuk2DUhNO1CuwrJA84TqC+jGo73bDKaT5hrIDiaJRrN5+zcWja2uEWrj5jSbep4
oXdEdyH73hOHMBP40uds3PqnUsxEJhzjB2sCCe1geV24kw9J4m7EQXPVkUKDgKrt
LlpDmOoo
ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMkupYkg3Nd1oXM3fo0d
mVJBWNrni88lKDuIIQXwcKe6XCgiloZG708ecLTOws9+o9MkTl9Wtpf/WGXT98NK
EPUYakd2Fv1SuD1jWYlP7iDR6hB3RkWBm5ziujYftVJ4ZrPD42PLjDASvlh75Tvr
MeM7yq/qkcgNsd9dQyUvMNPks3tla9je7Dt7Auli2IN3CNXys7gIOfwJH0Bb/M6t
y7oUfpoUKAfLzwe61abztgDu1lSNgdFBM1kcxYflyh/FkX5TlAcWeAXzLrnxAXGR
UxXrxW4oPC+kZi/pDRBd7X4zQDx7bCmr1+FsS3M05i3w5E08Tt9iKRk4V8nCmE4i
k6UCAwEAAaNsMGowCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYE
FOOOFw5TNAqt/TcRRZEU3Dg/58XuMBYGA1UdEQQPMA2BC3lvdUBleGFtcGxlMBYG
A1UdEgQPMA2BC3lvdUBleGFtcGxlMA0GCSqGSIb3DQEBCwUAA4IBAQAy3xnmobxU
1SyhHvoIXTJmG0wt1DQ/Dqwjy362LpEf1UHt29wtg1Mph58eVtl93z5Vd2t4/O77
E2BHpSu9ujc6/Br4+2uA/Qk/xRyLBtZAwty6J4uFvOOg985HonN+RCUZbKSUTmtA
TZvNtIDAZFQ8Tu75K4gIBxDcz7biGi4i1VJ3F3GNCNeossr9IQwKvb+UWFq14U5R
IzUnGgMIzcjUG2kKQvddRD1CjS+egtcLvShbOfm5bs4w4rfQ2FPF+Aaf9v7fxa/c
Jrf3K+cB19eAy7O4nlPG1xurvnZd0QpqRk++werrBuKe1Pgga7YBLePfJhzwqcZv
wVOSsB870yeO
-----END CERTIFICATE-----
CERT

TEST_PKEY = <<~PKEY
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
PKEY
end
Expand Down
8 changes: 0 additions & 8 deletions test/prism/ruby/ripper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,10 @@ class RipperTest < TestCase
]

omitted_lex = [
"comments.txt",
"heredoc_percent_q_newline_delimiter.txt",
"heredoc_with_escaped_newline_at_start.txt",
"heredocs_with_fake_newlines.txt",
"indented_file_end.txt",
"seattlerb/TestRubyParserShared.txt",
"seattlerb/class_comments.txt",
"seattlerb/module_comments.txt",
"seattlerb/parse_line_block_inline_comment_leading_newlines.txt",
"seattlerb/parse_line_block_inline_multiline_comment.txt",
"spanning_heredoc_newlines.txt",
"strings.txt",
"whitequark/dedenting_heredoc.txt",
"whitequark/procarg0.txt",
]
Expand Down
25 changes: 20 additions & 5 deletions test/rubygems/test_gem_bundler_version_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def test_bundler_version_with_bundle_config
f.write(config_content)
f.flush

bvf.stub(:bundler_config_file, f.path) do
bvf.stub(:bundler_global_config_file, f.path) do
assert_nil bvf.bundler_version
end
end
Expand All @@ -81,7 +81,7 @@ def test_bundler_version_with_bundle_config_single_quoted
f.write(config_with_single_quoted_version)
f.flush

bvf.stub(:bundler_config_file, f.path) do
bvf.stub(:bundler_global_config_file, f.path) do
assert_nil bvf.bundler_version
end
end
Expand All @@ -98,18 +98,33 @@ def test_bundler_version_with_bundle_config_version
f.write(config_content)
f.flush

bvf.stub(:bundler_config_file, f.path) do
bvf.stub(:bundler_global_config_file, f.path) do
assert_equal v("1.1.1.1"), bvf.bundler_version
end
end
end

def test_bundler_version_with_bundle_config_non_existent_file
bvf.stub(:bundler_config_file, "/non/existent/path") do
bvf.stub(:bundler_global_config_file, "/non/existent/path") do
assert_nil bvf.bundler_version
end
end

def test_bundler_version_set_on_local_config
config_content = <<~CONFIG
BUNDLE_VERSION: "1.2.3"
CONFIG

Tempfile.create("bundle_config") do |f|
f.write(config_content)
f.flush

bvf.stub(:bundler_local_config_file, f.path) do
assert_equal v("1.2.3"), bvf.bundler_version
end
end
end

def test_bundler_version_with_bundle_config_without_version
config_without_version = <<~CONFIG
BUNDLE_JOBS: "8"
Expand All @@ -120,7 +135,7 @@ def test_bundler_version_with_bundle_config_without_version
f.write(config_without_version)
f.flush

bvf.stub(:bundler_config_file, f.path) do
bvf.stub(:bundler_global_config_file, f.path) do
assert_nil bvf.bundler_version
end
end
Expand Down
Loading