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

Commit

Permalink
Adds ruby version to Gemfile.lock.
Browse files Browse the repository at this point in the history
* Adds support for `bundle update --ruby` command to allow for updating
  ruby version in Gemfile.lock.
* Adds support for `bundle install` to allow for adding ruby version in
  Gemfile.lock.

https://www.pivotaltracker.com/story/show/106008092

Signed-off-by: JT Archie <jtarchie@gmail.com>
  • Loading branch information
David Morhovich authored and jtarchie committed Oct 27, 2015
1 parent b53dda5 commit 0736729
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 10 deletions.
2 changes: 2 additions & 0 deletions lib/bundler/cli.rb
Expand Up @@ -185,6 +185,8 @@ def install
"Update a specific source (and all gems associated with it)"
method_option "force", :type => :boolean, :banner =>
"Force downloading every gem."
method_option "ruby", :type => :boolean, :banner =>
"Update ruby specified in Gemfile.lock"
def update(*gems)
require "bundler/cli/update"
Update.new(options, gems).run
Expand Down
4 changes: 2 additions & 2 deletions lib/bundler/cli/update.rb
Expand Up @@ -12,7 +12,7 @@ def run
sources = Array(options[:source])
groups = Array(options[:group]).map(&:to_sym)

if gems.empty? && sources.empty? && groups.empty?
if gems.empty? && sources.empty? && groups.empty? && !options[:ruby]
# We're doing a full update
Bundler.definition(true)
else
Expand All @@ -33,7 +33,7 @@ def run
gems.concat(specs.map(&:name))
end

Bundler.definition(:gems => gems, :sources => sources)
Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby])
end

Bundler::Fetcher.disable_endpoint = options["full-index"]
Expand Down
35 changes: 29 additions & 6 deletions lib/bundler/definition.rb
Expand Up @@ -63,6 +63,7 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti
locked = LockfileParser.new(@lockfile_contents)
@platforms = locked.platforms
@locked_bundler_version = locked.bundler_version
@locked_ruby_version = locked.ruby_version

if unlock != true
@locked_deps = locked.dependencies
Expand Down Expand Up @@ -196,8 +197,7 @@ def resolve
last_resolve
else
# Run a resolve against the locally available gems
requested_ruby_version = ruby_version.version if ruby_version
last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, requested_ruby_version)
last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, ruby_version)
end
end
end
Expand Down Expand Up @@ -271,16 +271,34 @@ def lock(file, preserve_bundled_with = false)
end
end

# Returns the version of Bundler that is creating or has created
# Gemfile.lock. Used in #to_lock.
def lock_version
def locked_bundler_version
if @locked_bundler_version && @locked_bundler_version < Gem::Version.new(Bundler::VERSION)
new_version = Bundler::VERSION
end

new_version || @locked_bundler_version || Bundler::VERSION
end

def locked_ruby_version
if @unlock[:ruby]
if ruby_version && !@locked_ruby_version
return Bundler.ruby_version
elsif ruby_version && @locked_ruby_version
return Bundler.ruby_version
elsif !ruby_version && @locked_ruby_version
return nil
end
else
if ruby_version && !@locked_ruby_version
return Bundler.ruby_version
elsif ruby_version && @locked_ruby_version
return @locked_ruby_version
elsif !ruby_version && @locked_ruby_version
return @locked_ruby_version
end
end
end

def to_lock
out = ""

Expand All @@ -307,6 +325,11 @@ def to_lock
out << " #{p}\n"
end

if locked_ruby_version
out << "\nRUBY VERSION\n"
out << " #{locked_ruby_version}\n"
end

out << "\n"
out << "DEPENDENCIES\n"

Expand All @@ -319,7 +342,7 @@ def to_lock

# Record the version of Bundler that was used to create the lockfile
out << "\nBUNDLED WITH\n"
out << " #{lock_version}\n"
out << " #{locked_bundler_version}\n"

out
end
Expand Down
9 changes: 8 additions & 1 deletion lib/bundler/lockfile_parser.rb
Expand Up @@ -12,11 +12,12 @@

module Bundler
class LockfileParser
attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version
attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version

BUNDLED = "BUNDLED WITH"
DEPENDENCIES = "DEPENDENCIES"
PLATFORMS = "PLATFORMS"
RUBY = "RUBY VERSION"
GIT = "GIT"
GEM = "GEM"
PATH = "PATH"
Expand Down Expand Up @@ -46,6 +47,8 @@ def initialize(lockfile)
@state = :dependency
elsif line == PLATFORMS
@state = :platform
elsif line == RUBY
@state = :ruby
elsif line == BUNDLED
@state = :bundled_with
elsif line =~ /^[^\s]/
Expand Down Expand Up @@ -195,5 +198,9 @@ def parse_bundled_with(line)
@bundler_version = Gem::Version.create(line)
end
end

def parse_ruby(line)
@ruby_version = line.strip
end
end
end
2 changes: 1 addition & 1 deletion lib/bundler/resolver.rb
Expand Up @@ -194,7 +194,7 @@ def initialize(index, source_requirements, base, ruby_version)
@search_for = {}
@base_dg = Molinillo::DependencyGraph.new
@base.each {|ls| @base_dg.add_vertex(ls.name, Dependency.new(ls.name, ls.version), true) }
@ruby_version = ruby_version ? Gem::Version.create(ruby_version) : nil
@ruby_version = ruby_version
end

def start(requirements)
Expand Down
67 changes: 67 additions & 0 deletions spec/commands/install_spec.rb
Expand Up @@ -340,6 +340,73 @@
end
end

describe "Ruby version in Gemfile.lock" do
include Bundler::GemHelpers

context "and using an unsupported Ruby version" do
it "prints an error" do
install_gemfile <<-G
::RUBY_VERSION = '1.8.7'
ruby '~> 2.1'
G
expect(out).to include("Your Ruby version is 1.8.7, but your Gemfile specified ~> 2.1")
end
end

context "and using a supported Ruby version" do
before do
install_gemfile <<-G
::RUBY_VERSION = '2.1.3'
::RUBY_PATCHLEVEL = 100
ruby '~> 2.1.0'
G
end

it "writes current Ruby version to Gemfile.lock" do
lockfile_should_be <<-L
GEM
specs:
PLATFORMS
ruby
RUBY VERSION
ruby 2.1.3p100
DEPENDENCIES
BUNDLED WITH
#{Bundler::VERSION}
L
end

it "does not update Gemfile.lock with updated ruby versions" do
install_gemfile <<-G
::RUBY_VERSION = '2.2.3'
::RUBY_PATCHLEVEL = 100
ruby '~> 2.2.0'
G

lockfile_should_be <<-L
GEM
specs:
PLATFORMS
ruby
RUBY VERSION
ruby 2.1.3p100
DEPENDENCIES
BUNDLED WITH
#{Bundler::VERSION}
L

end
end
end

describe "when Bundler root contains regex chars" do
before do
root_dir = tmp("foo[]bar")
Expand Down
123 changes: 123 additions & 0 deletions spec/commands/update_spec.rb
Expand Up @@ -319,3 +319,126 @@
expect(exitstatus).to eq(22) if exitstatus
end
end

describe "bundle update --ruby" do
context 'when the Gemfile removes the ruby' do
it 'removes the Ruby from the Gemfile.lock' do
install_gemfile <<-G
::RUBY_VERSION = '2.1.3'
::RUBY_PATCHLEVEL = 100
ruby '~> 2.1.0'
G

install_gemfile <<-G
::RUBY_VERSION = '2.1.4'
::RUBY_PATCHLEVEL = 222
G


bundle "update --ruby"

lockfile_should_be <<-L
GEM
specs:
PLATFORMS
ruby
DEPENDENCIES
BUNDLED WITH
#{Bundler::VERSION}
L
end
end

context 'when the Gemfile specified an updated Ruby verison' do
it "updates the Gemfile.lock with the latest version" do
install_gemfile <<-G
::RUBY_VERSION = '2.1.3'
::RUBY_PATCHLEVEL = 100
ruby '~> 2.1.0'
G

install_gemfile <<-G
::RUBY_VERSION = '2.1.4'
::RUBY_PATCHLEVEL = 222
ruby '~> 2.1.0'
G


bundle "update --ruby"

lockfile_should_be <<-L
GEM
specs:
PLATFORMS
ruby
RUBY VERSION
ruby 2.1.4p222
DEPENDENCIES
BUNDLED WITH
#{Bundler::VERSION}
L
end
end

context 'when a different Ruby is being used than has been versioned' do
it "shows a helpful error message" do
install_gemfile <<-G
::RUBY_VERSION = '2.1.3'
::RUBY_PATCHLEVEL = 100
ruby '~> 2.1.0'
G

install_gemfile <<-G
::RUBY_VERSION = '2.2.2'
::RUBY_PATCHLEVEL = 505
ruby '~> 2.1.0'
G


bundle "update --ruby"
expect(out).to include("Your Ruby version is 2.2.2, but your Gemfile specified ~> 2.1.0")
end
end

context 'when updating Ruby version and Gemfile `ruby`' do
it "updates the Gemfile.lock with the latest version" do
install_gemfile <<-G
::RUBY_VERSION = '2.1.3'
::RUBY_PATCHLEVEL = 100
ruby '~> 2.1.0'
G

install_gemfile <<-G
::RUBY_VERSION = '1.8.3'
::RUBY_PATCHLEVEL = 55
ruby '~> 1.8.0'
G


bundle "update --ruby"

lockfile_should_be <<-L
GEM
specs:
PLATFORMS
ruby
RUBY VERSION
ruby 1.8.3p55
DEPENDENCIES
BUNDLED WITH
#{Bundler::VERSION}
L
end
end
end
27 changes: 27 additions & 0 deletions spec/lock/lockfile_spec.rb
Expand Up @@ -1124,6 +1124,33 @@
G
end

it "captures the Ruby version in the lockfile", :focus do
install_gemfile <<-G
source "file://#{gem_repo1}"
ruby '#{RUBY_VERSION}'
gem "rack", "> 0.9", "< 1.0"
G

lockfile_should_be <<-G
GEM
remote: file:#{gem_repo1}/
specs:
rack (0.9.1)
PLATFORMS
ruby
RUBY VERSION
ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}
DEPENDENCIES
rack (> 0.9, < 1.0)
BUNDLED WITH
#{Bundler::VERSION}
G
end

# Some versions of the Bundler 1.1 RC series introduced corrupted
# lockfiles. There were two major problems:
#
Expand Down

0 comments on commit 0736729

Please sign in to comment.