summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHomu <homu@barosl.com>2016-04-20 09:06:06 +0900
committerSamuel Giddins <segiddins@segiddins.me>2016-04-19 19:08:39 -0500
commita552c140929a8365c123bd9cfa6f5df6d3048d7e (patch)
treee6a3a59dc3414445519632a5b000c8cc5f2708f0
parent009ac70f7499bf5df535220344348c8f4ac35163 (diff)
downloadbundler-a552c140929a8365c123bd9cfa6f5df6d3048d7e.tar.gz
Auto merge of #4449 - bundler:seg-generically-preserve-new-attributes, r=indirect
Generically preserve new attributes in lockfile WIP, this needs tests @indirect
-rw-r--r--lib/bundler/cli/check.rb2
-rw-r--r--lib/bundler/definition.rb22
-rw-r--r--lib/bundler/environment.rb2
-rw-r--r--lib/bundler/lockfile_parser.rb29
-rw-r--r--lib/bundler/runtime.rb2
-rw-r--r--spec/bundler/lockfile_parser_spec.rb94
-rw-r--r--spec/runtime/setup_spec.rb62
-rw-r--r--spec/support/helpers.rb7
8 files changed, 208 insertions, 12 deletions
diff --git a/lib/bundler/cli/check.rb b/lib/bundler/cli/check.rb
index f6a1022306..738d40b622 100644
--- a/lib/bundler/cli/check.rb
+++ b/lib/bundler/cli/check.rb
@@ -32,7 +32,7 @@ module Bundler
Bundler.ui.error "This bundle has been frozen, but there is no #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} present"
exit 1
else
- Bundler.load.lock(:preserve_bundled_with => true) unless options[:"dry-run"]
+ Bundler.load.lock(:preserve_unknown_sections => true) unless options[:"dry-run"]
Bundler.ui.info "The Gemfile's dependencies are satisfied"
end
end
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 944b8089c1..4a8eb08abe 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -241,7 +241,7 @@ module Bundler
dependencies.map(&:groups).flatten.uniq
end
- def lock(file, preserve_bundled_with = false)
+ def lock(file, preserve_unknown_sections = false)
contents = to_lock
# Convert to \r\n if the existing lock has them
@@ -258,8 +258,8 @@ module Bundler
end
end
- preserve_bundled_with ||= !updating_major && (Bundler.settings[:frozen] || !@unlocking)
- return if lockfiles_equal?(@lockfile_contents, contents, preserve_bundled_with)
+ preserve_unknown_sections ||= !updating_major && (Bundler.settings[:frozen] || !@unlocking)
+ return if lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
if Bundler.settings[:frozen]
Bundler.ui.error "Cannot write a changed lockfile while frozen."
@@ -672,13 +672,17 @@ module Bundler
groups - Bundler.settings.without - @optional_groups + Bundler.settings.with
end
- def lockfiles_equal?(current, proposed, preserve_bundled_with)
- if preserve_bundled_with
- pattern = /\n\n#{LockfileParser::BUNDLED}\n\s+#{Gem::Version::VERSION_PATTERN}\n/
- current.sub(pattern, "\n") == proposed.sub(pattern, "\n")
- else
- current == proposed
+ def lockfiles_equal?(current, proposed, preserve_unknown_sections)
+ if preserve_unknown_sections
+ sections_to_ignore = LockfileParser.sections_to_ignore(@locked_bundler_version)
+ sections_to_ignore += LockfileParser.unknown_sections_in_lockfile(current)
+ sections_to_ignore += LockfileParser::ENVIRONMENT_VERSION_SECTIONS
+ pattern = /#{Regexp.union(sections_to_ignore)}\n(\s{2,}.*\n)+/
+ whitespace_cleanup = /\n{2,}/
+ current = current.gsub(pattern, "\n").gsub(whitespace_cleanup, "\n\n").strip
+ proposed = proposed.gsub(pattern, "\n").gsub(whitespace_cleanup, "\n\n").strip
end
+ current == proposed
end
end
end
diff --git a/lib/bundler/environment.rb b/lib/bundler/environment.rb
index 4e072602e6..b12a146a77 100644
--- a/lib/bundler/environment.rb
+++ b/lib/bundler/environment.rb
@@ -32,7 +32,7 @@ module Bundler
end
def lock(opts = {})
- @definition.lock(Bundler.default_lockfile, opts[:preserve_bundled_with])
+ @definition.lock(Bundler.default_lockfile, opts[:preserve_unknown_sections])
end
def update(*gems)
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index 94e88dbd0c..e0c6dd1c38 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -26,6 +26,35 @@ module Bundler
OPTIONS = /^ ([a-z]+): (.*)$/i
SOURCE = [GIT, GEM, PATH].freeze
+ SECTIONS_BY_VERSION_INTRODUCED = {
+ Gem::Version.create("1.0") => [DEPENDENCIES, PLATFORMS, GIT, GEM, PATH].freeze,
+ Gem::Version.create("1.10") => [BUNDLED].freeze,
+ Gem::Version.create("1.12") => [RUBY].freeze,
+ }.freeze
+
+ KNOWN_SECTIONS = SECTIONS_BY_VERSION_INTRODUCED.values.flatten.freeze
+
+ ENVIRONMENT_VERSION_SECTIONS = [BUNDLED, RUBY].freeze
+
+ def self.sections_in_lockfile(lockfile_contents)
+ lockfile_contents.scan(/^\w[\w ]*$/).uniq
+ end
+
+ def self.unknown_sections_in_lockfile(lockfile_contents)
+ sections_in_lockfile(lockfile_contents) - KNOWN_SECTIONS
+ end
+
+ def self.sections_to_ignore(base_version = nil)
+ base_version &&= base_version.release
+ base_version ||= Gem::Version.create("1.0")
+ attributes = []
+ SECTIONS_BY_VERSION_INTRODUCED.each do |version, introduced|
+ next if version <= base_version
+ attributes += introduced
+ end
+ attributes
+ end
+
def initialize(lockfile)
@platforms = []
@sources = []
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index d4a7837072..9d53e7528a 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -52,7 +52,7 @@ module Bundler
setup_manpath
- lock(:preserve_bundled_with => true)
+ lock(:preserve_unknown_sections => true)
self
end
diff --git a/spec/bundler/lockfile_parser_spec.rb b/spec/bundler/lockfile_parser_spec.rb
new file mode 100644
index 0000000000..d9bb32b4de
--- /dev/null
+++ b/spec/bundler/lockfile_parser_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+require "spec_helper"
+require "bundler/lockfile_parser"
+
+describe Bundler::LockfileParser do
+ let(:lockfile_contents) { strip_whitespace(<<-L) }
+ GIT
+ remote: https://github.com/alloy/peiji-san.git
+ revision: eca485d8dc95f12aaec1a434b49d295c7e91844b
+ specs:
+ peiji-san (1.2.0)
+
+ GEM
+ remote: https://rubygems.org/
+ specs:
+ rake (10.3.2)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ peiji-san!
+ rake
+
+ RUBY VERSION
+ ruby 2.1.3p242
+
+ BUNDLED WITH
+ 1.12.0.rc.2
+ L
+
+ describe ".sections_in_lockfile" do
+ it "returns the attributes" do
+ attributes = described_class.sections_in_lockfile(lockfile_contents)
+ expect(attributes).to contain_exactly(
+ "BUNDLED WITH", "DEPENDENCIES", "GEM", "GIT", "PLATFORMS", "RUBY VERSION"
+ )
+ end
+ end
+
+ describe ".unknown_sections_in_lockfile" do
+ let(:lockfile_contents) { strip_whitespace(<<-L) }
+ UNKNOWN ATTR
+
+ UNKNOWN ATTR 2
+ random contents
+ L
+
+ it "returns the unknown attributes" do
+ attributes = described_class.unknown_sections_in_lockfile(lockfile_contents)
+ expect(attributes).to contain_exactly("UNKNOWN ATTR", "UNKNOWN ATTR 2")
+ end
+ end
+
+ describe ".sections_to_ignore" do
+ subject { described_class.sections_to_ignore(base_version) }
+
+ context "with a nil base version" do
+ let(:base_version) { nil }
+
+ it "returns the same as > 1.0" do
+ expect(subject).to contain_exactly(
+ described_class::BUNDLED, described_class::RUBY
+ )
+ end
+ end
+
+ context "with a prerelease base version" do
+ let(:base_version) { Gem::Version.create("1.11.0.rc.1") }
+
+ it "returns the same as for the release version" do
+ expect(subject).to contain_exactly(
+ described_class::RUBY
+ )
+ end
+ end
+
+ context "with a current version" do
+ let(:base_version) { Gem::Version.create(Bundler::VERSION) }
+
+ it "returns an empty array" do
+ expect(subject).to eq([])
+ end
+ end
+
+ context "with a future version" do
+ let(:base_version) { Gem::Version.create("5.5.5") }
+
+ it "returns an empty array" do
+ expect(subject).to eq([])
+ end
+ end
+ end
+end
diff --git a/spec/runtime/setup_spec.rb b/spec/runtime/setup_spec.rb
index d6c60dcf24..1b2b442fdd 100644
--- a/spec/runtime/setup_spec.rb
+++ b/spec/runtime/setup_spec.rb
@@ -983,6 +983,68 @@ describe "Bundler.setup" do
end
end
+ describe "when RUBY VERSION" do
+ let(:ruby_version) { nil }
+
+ def lock_with(ruby_version = nil)
+ lock = <<-L
+ GEM
+ remote: file:#{gem_repo1}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{generic_local_platform}
+
+ DEPENDENCIES
+ rack
+ L
+
+ if ruby_version
+ lock += "\n RUBY VERSION\n #{ruby_version}\n"
+ end
+
+ lock += <<-L
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lock
+ end
+
+ before do
+ install_gemfile <<-G
+ ruby ">= 0"
+ source "file:#{gem_repo1}"
+ gem "rack"
+ G
+ lockfile lock_with(ruby_version)
+ end
+
+ context "is not present" do
+ it "does not change the lock" do
+ expect { ruby! "require 'bundler/setup'" }.not_to change { lockfile }
+ end
+ end
+
+ context "is newer" do
+ let(:ruby_version) { "5.5.5" }
+ it "does not change the lock or warn" do
+ expect { ruby! "require 'bundler/setup'" }.not_to change { lockfile }
+ expect(out).to eq("")
+ expect(err).to eq("")
+ end
+ end
+
+ context "is older" do
+ let(:ruby_version) { "1.0.0" }
+ it "does not change the lock" do
+ expect { ruby! "require 'bundler/setup'" }.not_to change { lockfile }
+ end
+ end
+ end
+
describe "when Psych is not in the Gemfile", :ruby => "~> 2.2" do
it "does not load Psych" do
gemfile ""
diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb
index 60c1c6f42f..5a5d07300b 100644
--- a/spec/support/helpers.rb
+++ b/spec/support/helpers.rb
@@ -217,6 +217,13 @@ module Spec
bundle :install, opts
end
+ def lock_gemfile(*args)
+ gemfile(*args)
+ opts = args.last.is_a?(Hash) ? args.last : {}
+ opts[:retry] ||= 0
+ bundle :lock, opts
+ end
+
def install_gems(*gems)
gems.each do |g|
path = "#{gem_repo1}/gems/#{g}.gem"