Skip to content
This repository has been archived by the owner on Apr 14, 2021. It is now read-only.

Commit

Permalink
Auto merge of #4603 - bundler:seg-allow-unlocking-when-removing-ruby,…
Browse files Browse the repository at this point in the history
… r=indirect

[Definition] Allow unlocking when removing the ruby version requirement

Closes #4595. Closes #4627.

\c @RochesterinNYC
  • Loading branch information
homu committed Jun 10, 2016
2 parents 4b57850 + 4f8a41a commit 6ebda98
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 8 deletions.
8 changes: 8 additions & 0 deletions lib/bundler/definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti

@unlock[:gems] ||= []
@unlock[:sources] ||= []
@unlock[:ruby] ||= if @ruby_version && @locked_ruby_version
unless locked_ruby_version_object = RubyVersion.from_string(@locked_ruby_version)
raise LockfileError, "Failed to create a `RubyVersion` object from " \
"`#{@locked_ruby_version}` found in #{lockfile} -- try running `bundle update --ruby`."
end
@ruby_version.diff(locked_ruby_version_object)
end
@unlocking ||= @unlock[:ruby] || (!@locked_ruby_version ^ !@ruby_version)

current_platform = Bundler.rubygems.platforms.map {|p| generic(p) }.compact.last
add_platform(current_platform)
Expand Down
24 changes: 21 additions & 3 deletions lib/bundler/ruby_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ def to_s(versions = self.versions)
output
end

# @private
PATTERN = /
ruby\s
([\d.]+) # ruby version
(?:p(\d+))? # optional patchlevel
(?:\s\((\S+)\s(.+)\))? # optional engine info
/xo

# Returns a RubyVersion from the given string.
# @param [String] the version string to match.
# @return [RubyVersion,Nil] The version if the string is a valid RubyVersion
# description, and nil otherwise.
def self.from_string(string)
new($1, $2, $3, $4) if string =~ PATTERN
end

def single_version_string
to_s(gem_version)
end
Expand All @@ -64,7 +80,7 @@ def host
# 2. ruby_version
# 3. engine_version
def diff(other)
raise ArgumentError, "Can only diff with a RubyVersion" unless other.is_a?(RubyVersion)
raise ArgumentError, "Can only diff with a RubyVersion, not a #{other.class}" unless other.is_a?(RubyVersion)
if engine != other.engine && @input_engine
[:engine, engine, other.engine]
elsif versions.empty? || !matches?(versions, other.gem_version)
Expand All @@ -87,17 +103,19 @@ def self.system
# not defined in ruby 1.8.7
"ruby"
end
# :sob: mocking RUBY_VERSION breaks stuff on 1.8.7
ruby_version = ENV.fetch("BUNDLER_SPEC_RUBY_VERSION") { RUBY_VERSION }.dup
ruby_engine_version = case ruby_engine
when "ruby"
RUBY_VERSION.dup
ruby_version
when "rbx"
Rubinius::VERSION.dup
when "jruby"
JRUBY_VERSION.dup
else
raise BundlerError, "RUBY_ENGINE value #{RUBY_ENGINE} is not recognized"
end
@ruby_version ||= RubyVersion.new(RUBY_VERSION.dup, RUBY_PATCHLEVEL.to_s, ruby_engine, ruby_engine_version)
@ruby_version ||= RubyVersion.new(ruby_version, RUBY_PATCHLEVEL.to_s, ruby_engine, ruby_engine_version)
end

def to_gem_version_with_patchlevel
Expand Down
34 changes: 34 additions & 0 deletions spec/bundler/ruby_version_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,40 @@
end
end
end

describe ".from_string" do
shared_examples_for "returning" do
it "returns the original RubyVersion" do
expect(described_class.from_string(subject.to_s)).to eq(subject)
end
end

include_examples "returning"

context "no patchlevel" do
let(:patchlevel) { nil }

include_examples "returning"
end

context "engine is ruby" do
let(:engine) { "ruby" }
let(:engine_version) { version }

include_examples "returning"
end

context "with multiple requirements" do
let(:engine_version) { ["> 9", "< 11"] }
let(:version) { ["> 8", "< 10"] }
let(:patchlevel) { nil }

it "returns nil" do
expect(described_class.from_string(subject.to_s)).to be_nil
end
end
end

describe "#to_s" do
it "should return info string with the ruby version, patchlevel, engine, and engine version" do
expect(subject.to_s).to eq("ruby 2.0.0p645 (jruby 2.0.1)")
Expand Down
4 changes: 2 additions & 2 deletions spec/commands/install_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@
L
end

it "does not update Gemfile.lock with updated ruby versions" do
it "updates Gemfile.lock with updated incompatible ruby version" do
install_gemfile <<-G, :expect_err => true
::RUBY_VERSION = '2.2.3'
::RUBY_PATCHLEVEL = 100
Expand All @@ -408,7 +408,7 @@
DEPENDENCIES
RUBY VERSION
ruby 2.1.3p100
ruby 2.2.3p100
BUNDLED WITH
#{Bundler::VERSION}
Expand Down
64 changes: 64 additions & 0 deletions spec/install/gemfile/ruby_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
require "spec_helper"

describe "ruby requirement" do
def locked_ruby_version
Bundler::RubyVersion.from_string(Bundler::LockfileParser.new(lockfile).ruby_version)
end

# As discovered by https://github.com/bundler/bundler/issues/4147, there is
# no test coverage to ensure that adding a gem is possible with a ruby
# requirement. This test verifies the fix, committed in bfbad5c5.
Expand All @@ -22,4 +26,64 @@
expect(exitstatus).to eq(0) if exitstatus
should_be_installed "rack-obama 1.0"
end

it "allows removing the ruby version requirement" do
install_gemfile <<-G
source "file://#{gem_repo1}"
ruby "~> #{RUBY_VERSION}"
gem "rack"
G

expect(lockfile).to include("RUBY VERSION")

install_gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
G

should_be_installed "rack 1.0.0"
expect(lockfile).not_to include("RUBY VERSION")
end

it "allows changing the ruby version requirement to something compatible" do
install_gemfile <<-G
source "file://#{gem_repo1}"
ruby ">= 1.0.0"
gem "rack"
G

expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)

simulate_ruby_version "5100"

install_gemfile <<-G
source "file://#{gem_repo1}"
ruby ">= 1.0.1"
gem "rack"
G

should_be_installed "rack 1.0.0"
expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
end

it "allows changing the ruby version requirement to something incompatible" do
install_gemfile <<-G
source "file://#{gem_repo1}"
ruby ">= 1.0.0"
gem "rack"
G

expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)

simulate_ruby_version "5100"

install_gemfile <<-G
source "file://#{gem_repo1}"
ruby ">= 5000.0"
gem "rack"
G

should_be_installed "rack 1.0.0"
expect(locked_ruby_version.versions).to eq(["5100"])
end
end
4 changes: 2 additions & 2 deletions spec/other/platform_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ def should_be_patchlevel_fixnum

bundle :check
expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("The Gemfile's dependencies are satisfied")
expect(out).to eq("Resolving dependencies...\nThe Gemfile's dependencies are satisfied")
end

it "checks fine with any engine" do
Expand All @@ -395,7 +395,7 @@ def should_be_patchlevel_fixnum

bundle :check
expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("The Gemfile's dependencies are satisfied")
expect(out).to eq("Resolving dependencies...\nThe Gemfile's dependencies are satisfied")
end
end

Expand Down
2 changes: 1 addition & 1 deletion spec/runtime/setup_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,7 @@ def lock_with(ruby_version = nil)
L

if ruby_version
lock += "\n RUBY VERSION\n #{ruby_version}\n"
lock += "\n RUBY VERSION\n ruby #{ruby_version}\n"
end

lock += <<-L
Expand Down
9 changes: 9 additions & 0 deletions spec/support/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,15 @@ def simulate_platform(platform)
ENV["BUNDLER_SPEC_PLATFORM"] = old if block_given?
end

def simulate_ruby_version(version)
return if version == RUBY_VERSION
old = ENV["BUNDLER_SPEC_RUBY_VERSION"]
ENV["BUNDLER_SPEC_RUBY_VERSION"] = version
yield if block_given?
ensure
ENV["BUNDLER_SPEC_RUBY_VERSION"] = old if block_given?
end

def simulate_ruby_engine(engine, version = "1.6.0")
return if engine == local_ruby_engine

Expand Down

0 comments on commit 6ebda98

Please sign in to comment.