diff options
author | Nick LaMuro <nicklamuro@gmail.com> | 2017-06-26 17:19:04 -0500 |
---|---|---|
committer | Nick LaMuro <nicklamuro@gmail.com> | 2017-06-29 11:32:32 -0500 |
commit | 3db89cafa715527ff0066efb38fdeec1f07119f1 (patch) | |
tree | 7d1f3c269d73e7e206a5a6c186365c3353ccd6d0 | |
parent | a14b5c02da80dc74bdafc660f592c5c4d0c8740d (diff) | |
download | bundler-3db89cafa715527ff0066efb38fdeec1f07119f1.tar.gz |
Compare sources using source's root
When doing the following:
expand(other.original_path)
inside a Bundler::Source::Path instance, the `@root_path` from the
instance that is having eql? called on it, the other instance's
root_path. This, in obscure cases, can cause a bug when you are doing an
nested eval_gemfile or other calls when comparing the lockfile's locked
path sources to the Bundler.definition's path sources.
Creating the expanded_original_path method allows a public interface to
be made available (and doesn't mess with any exiting functionality) that
allows comparing the source path of one Source::Path's expand_path to
another, where each uses their own root_path to resolve their full path,
instead of sharing the base one and causing edge case bugs
-rw-r--r-- | lib/bundler/source/path.rb | 6 | ||||
-rw-r--r-- | spec/bundler/source/path_spec.rb | 31 | ||||
-rw-r--r-- | spec/install/gemfile/eval_gemfile_spec.rb | 7 |
3 files changed, 43 insertions, 1 deletions
diff --git a/lib/bundler/source/path.rb b/lib/bundler/source/path.rb index 99808d2ef2..b13f971858 100644 --- a/lib/bundler/source/path.rb +++ b/lib/bundler/source/path.rb @@ -65,7 +65,7 @@ module Bundler def eql?(other) return unless other.class == self.class - expand(@original_path) == expand(other.original_path) && + expanded_original_path == other.expanded_original_path && version == other.version end @@ -119,6 +119,10 @@ module Bundler instance_of?(Path) end + def expanded_original_path + @expanded_original_path ||= expand(original_path) + end + private def expanded_path diff --git a/spec/bundler/source/path_spec.rb b/spec/bundler/source/path_spec.rb new file mode 100644 index 0000000000..1d13e03ec1 --- /dev/null +++ b/spec/bundler/source/path_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +RSpec.describe Bundler::Source::Path do + before do + allow(Bundler).to receive(:root) { Pathname.new("root") } + end + + describe "#eql?" do + subject { described_class.new("path" => "gems/a") } + + context "with two equivalent relative paths from different roots" do + let(:a_gem_opts) { { "path" => "../gems/a", "root_path" => Bundler.root.join("nested") } } + let(:a_gem) { described_class.new a_gem_opts } + + it "returns true" do + expect(subject).to eq a_gem + end + end + + context "with the same (but not equivalent) relative path from different roots" do + subject { described_class.new("path" => "gems/a") } + + let(:a_gem_opts) { { "path" => "gems/a", "root_path" => Bundler.root.join("nested") } } + let(:a_gem) { described_class.new a_gem_opts } + + it "returns false" do + expect(subject).to_not eq a_gem + end + end + end +end diff --git a/spec/install/gemfile/eval_gemfile_spec.rb b/spec/install/gemfile/eval_gemfile_spec.rb index f3f9cb6444..0588bea3da 100644 --- a/spec/install/gemfile/eval_gemfile_spec.rb +++ b/spec/install/gemfile/eval_gemfile_spec.rb @@ -41,6 +41,13 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do bundle! :install expect(the_bundle).to include_gem("a 1.0") end + + # Make sure that we are properly comparing path based gems between the + # parsed lockfile and the evaluated gemfile. + it "bundles with --deployment" do + bundle! :install + bundle! "install --deployment" + end end context "Gemfile uses gemspec paths after eval-ing a Gemfile" do |