diff options
author | Homu <homu@barosl.com> | 2016-04-20 09:06:06 +0900 |
---|---|---|
committer | Samuel Giddins <segiddins@segiddins.me> | 2016-04-19 19:08:39 -0500 |
commit | a552c140929a8365c123bd9cfa6f5df6d3048d7e (patch) | |
tree | e6a3a59dc3414445519632a5b000c8cc5f2708f0 | |
parent | 009ac70f7499bf5df535220344348c8f4ac35163 (diff) | |
download | bundler-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.rb | 2 | ||||
-rw-r--r-- | lib/bundler/definition.rb | 22 | ||||
-rw-r--r-- | lib/bundler/environment.rb | 2 | ||||
-rw-r--r-- | lib/bundler/lockfile_parser.rb | 29 | ||||
-rw-r--r-- | lib/bundler/runtime.rb | 2 | ||||
-rw-r--r-- | spec/bundler/lockfile_parser_spec.rb | 94 | ||||
-rw-r--r-- | spec/runtime/setup_spec.rb | 62 | ||||
-rw-r--r-- | spec/support/helpers.rb | 7 |
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" |