summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick LaMuro <nicklamuro@gmail.com>2017-06-26 17:19:04 -0500
committerNick LaMuro <nicklamuro@gmail.com>2017-06-29 11:32:32 -0500
commit3db89cafa715527ff0066efb38fdeec1f07119f1 (patch)
tree7d1f3c269d73e7e206a5a6c186365c3353ccd6d0
parenta14b5c02da80dc74bdafc660f592c5c4d0c8740d (diff)
downloadbundler-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.rb6
-rw-r--r--spec/bundler/source/path_spec.rb31
-rw-r--r--spec/install/gemfile/eval_gemfile_spec.rb7
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