diff options
author | Samuel Giddins <segiddins@segiddins.me> | 2017-05-18 23:34:10 -0500 |
---|---|---|
committer | Samuel Giddins <segiddins@segiddins.me> | 2017-07-02 15:05:46 +0200 |
commit | 7a4998966a016383d1848ef0508c2db0bb520725 (patch) | |
tree | 93077f74b3d113471d30df5bf10ecfd7875f55f7 | |
parent | 5e8243ba4845bd87238eb9dfb8ca765683f9229f (diff) | |
download | bundler-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.rb | 5 | ||||
-rw-r--r-- | lib/bundler/dsl.rb | 6 | ||||
-rw-r--r-- | lib/bundler/resolver.rb | 9 | ||||
-rw-r--r-- | lib/bundler/rubygems_ext.rb | 4 | ||||
-rw-r--r-- | spec/install/gemfile/force_spec.rb | 51 |
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 |