summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Giddins <segiddins@segiddins.me>2017-05-18 23:34:10 -0500
committerSamuel Giddins <segiddins@segiddins.me>2017-07-02 15:05:46 +0200
commit7a4998966a016383d1848ef0508c2db0bb520725 (patch)
tree93077f74b3d113471d30df5bf10ecfd7875f55f7
parent5e8243ba4845bd87238eb9dfb8ca765683f9229f (diff)
downloadbundler-seg-dsl-force-version.tar.gz
[DSL] Allow forcing a particular version of a gemseg-dsl-force-version
Even if it conflicts
-rw-r--r--lib/bundler/dependency.rb5
-rw-r--r--lib/bundler/dsl.rb6
-rw-r--r--lib/bundler/resolver.rb9
-rw-r--r--lib/bundler/rubygems_ext.rb4
-rw-r--r--spec/install/gemfile/force_spec.rb51
5 files changed, 73 insertions, 2 deletions
diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb
index d2bac66cdb..1c37769e0a 100644
--- a/lib/bundler/dependency.rb
+++ b/lib/bundler/dependency.rb
@@ -88,6 +88,7 @@ module Bundler
@should_include = options.fetch("should_include", true)
@autorequire = Array(options["require"] || []) if options.key?("require")
+ @force_version = options.fetch("force_version", false)
end
def gem_platforms(valid_platforms)
@@ -106,6 +107,10 @@ module Bundler
@should_include && current_env? && current_platform?
end
+ def force_version?
+ @force_version
+ end
+
def current_env?
return true unless @env
if @env.is_a?(Hash)
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index c368c533fe..ef5aff09e4 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -15,7 +15,7 @@ module Bundler
VALID_PLATFORMS = Bundler::Dependency::PLATFORM_MAP.keys.freeze
VALID_KEYS = %w[group groups git path glob name branch ref tag require submodules
- platform platforms type source install_if].freeze
+ platform platforms type source install_if force_version].freeze
attr_reader :gemspecs
attr_accessor :dependencies
@@ -376,6 +376,10 @@ repo_name ||= user_name
opts["source"] = @sources.add_rubygems_source("remotes" => source)
end
+ if opts.key?("force_version") && (r = Gem::Requirement.new(version)) && !r.exact?
+ raise GemfileError, "Cannot use force_version for inexact version requirement `#{r}`"
+ end
+
git_name = (git_names & opts.keys).last
if @git_sources[git_name]
opts["git"] = @git_sources[git_name].call(opts[git_name])
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 8bdeae275f..1fa343e6f0 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -354,7 +354,7 @@ module Bundler
end
def requirement_satisfied_by?(requirement, activated, spec)
- return false unless requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
+ return false unless requirement.matches_spec?(spec) || allows_conflicts?(requirement, activated, spec)
spec.activate_platform!(requirement.__platform) if !@platforms || @platforms.include?(requirement.__platform)
true
end
@@ -456,5 +456,12 @@ module Bundler
end
version_platform_strs.join(", ")
end
+
+ def allows_conflicts?(requirement, activated, spec)
+ return true if spec.source.is_a?(Source::Gemspec)
+ return false if requirement.force_version?
+ return true if activated.vertex_named(spec.name).requirements.any?(&:force_version?)
+ false
+ end
end
end
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index 0d282a8fcc..a35d3fb599 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -166,6 +166,10 @@ module Gem
requirement.satisfied_by?(spec.version)
end unless allocate.respond_to?(:matches_spec?)
+
+ def force_version?
+ false
+ end
end
class Requirement
diff --git a/spec/install/gemfile/force_spec.rb b/spec/install/gemfile/force_spec.rb
new file mode 100644
index 0000000000..2fff97fa5a
--- /dev/null
+++ b/spec/install/gemfile/force_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+RSpec.describe "bundle install with a gemfile that forces a gem version" do
+ context "with a simple conflict" do
+ it "works" do
+ install_gemfile! <<-G
+ source "file:#{gem_repo1}"
+ gem "rack_middleware"
+ gem "rack", "1.0.0", :force_version => true
+ G
+
+ expect(the_bundle).to include_gems("rack 1.0.0", "rack_middleware 1.0")
+ end
+
+ it "raises when forcing to an inexact version" do
+ install_gemfile <<-G
+ gem "rack", "> 1.0.0", :force_version => true
+ G
+ expect(out).to include("Cannot use force_version for inexact version requirement `> 1.0.0`.")
+ end
+
+ it "raises when forcing without specifying a version" do
+ install_gemfile <<-G
+ gem "rack", :force_version => true
+ G
+ expect(out).to include("Cannot use force_version for inexact version requirement `>= 0`.")
+ end
+
+ it "works when there's no conflict" do
+ install_gemfile! <<-G
+ source "file:#{gem_repo1}"
+ gem "rack", "1.0.0", :force_version => true
+ G
+
+ expect(the_bundle).to include_gems("rack 1.0.0")
+ end
+ end
+
+ context "with a complex conflict" do
+ it "works" do
+ install_gemfile! <<-G
+ source "file:#{gem_repo1}"
+ gem "rails", "2.3.2"
+ gem "activesupport", "2.3.5", :force_version => true
+ G
+
+ expect(the_bundle).to include_gems("rails 2.3.2", "activesupport 2.3.5", "actionpack 2.3.2", "activerecord 2.3.2", "actionmailer 2.3.2", "activeresource 2.3.2")
+ end
+ end
+end