summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHomu <homu@barosl.com>2016-08-26 01:20:26 +0900
committerHomu <homu@barosl.com>2016-08-26 01:20:26 +0900
commitc71f43fbcb9ee25bc4466137cc29545cda1375e2 (patch)
tree123d017caf490fc82b3f8549d3f83246f3ec245c
parent8513ed1481dde5b47eead96dd0a1cfe3d77c4c84 (diff)
parent0ac668d261fc6c0adec89d7befa21e8de880b0f9 (diff)
downloadbundler-c71f43fbcb9ee25bc4466137cc29545cda1375e2.tar.gz
Auto merge of #4836 - bundler:seg-resolve-for-specific-platforms, r=indirect
Resolve for specific platforms Closes #4295. This will require adding a bunch of tests, as well as figuring out how to put this new behavior behind a feature flag (thus fixing all of the existing tests).
-rw-r--r--lib/bundler.rb2
-rw-r--r--lib/bundler/cli/binstubs.rb2
-rw-r--r--lib/bundler/cli/cache.rb2
-rw-r--r--lib/bundler/cli/check.rb2
-rw-r--r--lib/bundler/cli/install.rb2
-rw-r--r--lib/bundler/cli/outdated.rb2
-rw-r--r--lib/bundler/cli/platform.rb2
-rw-r--r--lib/bundler/cli/show.rb2
-rw-r--r--lib/bundler/cli/update.rb2
-rw-r--r--lib/bundler/definition.rb39
-rw-r--r--lib/bundler/dependency.rb2
-rw-r--r--lib/bundler/gem_helpers.rb68
-rw-r--r--lib/bundler/inline.rb2
-rw-r--r--lib/bundler/lazy_specification.rb17
-rw-r--r--lib/bundler/lockfile_parser.rb2
-rw-r--r--lib/bundler/match_platform.rb3
-rw-r--r--lib/bundler/plugin.rb4
-rw-r--r--lib/bundler/resolver.rb37
-rw-r--r--lib/bundler/runtime.rb3
-rw-r--r--lib/bundler/source.rb1
-rw-r--r--lib/bundler/spec_set.rb41
-rw-r--r--spec/bundler/source_spec.rb2
-rw-r--r--spec/install/gemfile/specific_platform_spec.rb95
-rw-r--r--spec/resolver/platform_spec.rb2
-rw-r--r--spec/support/builders.rb5
-rw-r--r--spec/support/platforms.rb4
-rw-r--r--spec/support/the_bundle.rb5
27 files changed, 290 insertions, 60 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 18b9e75253..8806ae01ef 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -91,7 +91,7 @@ module Bundler
# Return if all groups are already loaded
return @setup if defined?(@setup) && @setup
- definition.validate_ruby!
+ definition.validate_runtime!
SharedHelpers.print_major_deprecations!
diff --git a/lib/bundler/cli/binstubs.rb b/lib/bundler/cli/binstubs.rb
index f7a27b01bb..95103b7dd8 100644
--- a/lib/bundler/cli/binstubs.rb
+++ b/lib/bundler/cli/binstubs.rb
@@ -10,7 +10,7 @@ module Bundler
end
def run
- Bundler.definition.validate_ruby!
+ Bundler.definition.validate_runtime!
Bundler.settings[:bin] = options["path"] if options["path"]
Bundler.settings[:bin] = nil if options["path"] && options["path"].empty?
installer = Installer.new(Bundler.root, Bundler.definition)
diff --git a/lib/bundler/cli/cache.rb b/lib/bundler/cli/cache.rb
index c8c63e926c..5ba105a31d 100644
--- a/lib/bundler/cli/cache.rb
+++ b/lib/bundler/cli/cache.rb
@@ -7,7 +7,7 @@ module Bundler
end
def run
- Bundler.definition.validate_ruby!
+ Bundler.definition.validate_runtime!
Bundler.definition.resolve_with_cache!
setup_cache_all
Bundler.settings[:cache_all_platforms] = options["all-platforms"] if options.key?("all-platforms")
diff --git a/lib/bundler/cli/check.rb b/lib/bundler/cli/check.rb
index 738d40b622..3f504ff621 100644
--- a/lib/bundler/cli/check.rb
+++ b/lib/bundler/cli/check.rb
@@ -15,7 +15,7 @@ module Bundler
begin
definition = Bundler.definition
- definition.validate_ruby!
+ definition.validate_runtime!
not_installed = definition.missing_specs
rescue GemNotFound, VersionConflict
Bundler.ui.error "Bundler can't satisfy your Gemfile's dependencies."
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index 9802ea8036..f1632c9ee2 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -66,7 +66,7 @@ module Bundler
Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.feature_flag.plugins?
definition = Bundler.definition
- definition.validate_ruby!
+ definition.validate_runtime!
installer = Installer.install(Bundler.root, definition, options)
Bundler.load.cache if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.settings[:frozen]
diff --git a/lib/bundler/cli/outdated.rb b/lib/bundler/cli/outdated.rb
index 09b2d71453..de71075522 100644
--- a/lib/bundler/cli/outdated.rb
+++ b/lib/bundler/cli/outdated.rb
@@ -18,7 +18,7 @@ module Bundler
Bundler::CLI::Common.select_spec(gem_name)
end
- Bundler.definition.validate_ruby!
+ Bundler.definition.validate_runtime!
current_specs = Bundler.ui.silence { Bundler.load.specs }
current_dependencies = {}
Bundler.ui.silence { Bundler.load.dependencies.each {|dep| current_dependencies[dep.name] = dep } }
diff --git a/lib/bundler/cli/platform.rb b/lib/bundler/cli/platform.rb
index b5f906bfd9..9fdab0a53c 100644
--- a/lib/bundler/cli/platform.rb
+++ b/lib/bundler/cli/platform.rb
@@ -29,7 +29,7 @@ module Bundler
output << "Your Gemfile specifies a Ruby version requirement:\n* #{ruby_version}"
begin
- Bundler.definition.validate_ruby!
+ Bundler.definition.validate_runtime!
output << "Your current platform satisfies the Ruby version requirement."
rescue RubyVersionMismatch => e
output << e.message
diff --git a/lib/bundler/cli/show.rb b/lib/bundler/cli/show.rb
index d67b086dd1..77e845a603 100644
--- a/lib/bundler/cli/show.rb
+++ b/lib/bundler/cli/show.rb
@@ -13,7 +13,7 @@ module Bundler
def run
Bundler.ui.silence do
- Bundler.definition.validate_ruby!
+ Bundler.definition.validate_runtime!
Bundler.load.lock
end
diff --git a/lib/bundler/cli/update.rb b/lib/bundler/cli/update.rb
index ea2a4b8d8f..5aac47bd09 100644
--- a/lib/bundler/cli/update.rb
+++ b/lib/bundler/cli/update.rb
@@ -57,7 +57,7 @@ module Bundler
# rubygems plugins sometimes hook into the gem install process
Gem.load_env_plugins if Gem.respond_to?(:load_env_plugins)
- Bundler.definition.validate_ruby!
+ Bundler.definition.validate_runtime!
Installer.install Bundler.root, Bundler.definition, opts
Bundler.load.cache if Bundler.app_cache.exist?
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index dc3b4690d7..0cb6e7e399 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -70,7 +70,8 @@ module Bundler
if lockfile && File.exist?(lockfile)
@lockfile_contents = Bundler.read_file(lockfile)
@locked_gems = LockfileParser.new(@lockfile_contents)
- @platforms = @locked_gems.platforms
+ @locked_platforms = @locked_gems.platforms
+ @platforms = @locked_platforms.dup
@locked_bundler_version = @locked_gems.bundler_version
@locked_ruby_version = @locked_gems.ruby_version
@@ -91,6 +92,7 @@ module Bundler
@locked_deps = []
@locked_specs = SpecSet.new([])
@locked_sources = []
+ @locked_platforms = []
end
@unlock[:gems] ||= []
@@ -102,8 +104,7 @@ module Bundler
@gem_version_promoter = create_gem_version_promoter
- current_platform = Bundler.rubygems.platforms.map {|p| generic(p) }.compact.last
- add_platform(current_platform)
+ add_current_platform unless Bundler.settings[:frozen]
@path_changes = converge_paths
eager_unlock = expand_dependencies(@unlock[:gems])
@@ -414,6 +415,11 @@ module Bundler
deleted = []
changed = []
+ new_platforms = @platforms - @locked_platforms
+ deleted_platforms = @locked_platforms - @platforms
+ added.concat new_platforms.map {|p| "* platform: #{p}" }
+ deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
+
gemfile_sources = sources.lock_sources
new_sources = gemfile_sources - @locked_sources
@@ -462,6 +468,11 @@ module Bundler
raise ProductionError, msg if added.any? || deleted.any? || changed.any?
end
+ def validate_runtime!
+ validate_ruby!
+ validate_platforms!
+ end
+
def validate_ruby!
return unless ruby_version
@@ -487,6 +498,22 @@ module Bundler
end
end
+ # TODO: refactor this so that `match_platform` can be called with two platforms
+ DummyPlatform = Struct.new(:platform)
+ class DummyPlatform; include MatchPlatform; end
+ def validate_platforms!
+ return if @platforms.any? do |bundle_platform|
+ bundle_platform = DummyPlatform.new(bundle_platform)
+ Bundler.rubygems.platforms.any? do |local_platform|
+ bundle_platform.match_platform(local_platform)
+ end
+ end
+
+ raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
+ "but your local platforms are #{Bundler.rubygems.platforms.map(&:to_s)}, and " \
+ "there's no compatible match between those two lists."
+ end
+
def add_platform(platform)
@new_platform ||= !@platforms.include?(platform)
@platforms |= [platform]
@@ -497,6 +524,12 @@ module Bundler
raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
end
+ def add_current_platform
+ current_platform = Bundler.rubygems.platforms.last
+ add_platform(current_platform) if Bundler.settings[:specific_platform]
+ add_platform(generic(current_platform))
+ end
+
attr_reader :sources
private :sources
diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb
index 1b1808b40a..66162d741a 100644
--- a/lib/bundler/dependency.rb
+++ b/lib/bundler/dependency.rb
@@ -52,7 +52,7 @@ module Bundler
:x64_mingw_20 => Gem::Platform::X64_MINGW,
:x64_mingw_21 => Gem::Platform::X64_MINGW,
:x64_mingw_22 => Gem::Platform::X64_MINGW,
- :x64_mingw_23 => Gem::Platform::X64_MINGW
+ :x64_mingw_23 => Gem::Platform::X64_MINGW,
}.freeze
REVERSE_PLATFORM_MAP = {}.tap do |reverse_platform_map|
diff --git a/lib/bundler/gem_helpers.rb b/lib/bundler/gem_helpers.rb
index 5c824ffefc..6d926ce83f 100644
--- a/lib/bundler/gem_helpers.rb
+++ b/lib/bundler/gem_helpers.rb
@@ -28,5 +28,73 @@ module Bundler
generic(Gem::Platform.local)
end
module_function :generic_local_platform
+
+ def platform_specificity_match(spec_platform, user_platform)
+ spec_platform = Gem::Platform.new(spec_platform)
+ return PlatformMatch::EXACT_MATCH if spec_platform == user_platform
+ return PlatformMatch::WORST_MATCH if spec_platform.nil? || spec_platform == Gem::Platform::RUBY || user_platform == Gem::Platform::RUBY
+
+ PlatformMatch.new(
+ PlatformMatch.os_match(spec_platform, user_platform),
+ PlatformMatch.cpu_match(spec_platform, user_platform),
+ PlatformMatch.platform_version_match(spec_platform, user_platform)
+ )
+ end
+ module_function :platform_specificity_match
+
+ def select_best_platform_match(specs, platform)
+ specs.select {|spec| spec.match_platform(platform) }.
+ min_by {|spec| platform_specificity_match(spec.platform, platform) }
+ end
+ module_function :select_best_platform_match
+
+ PlatformMatch = Struct.new(:os_match, :cpu_match, :platform_version_match)
+ class PlatformMatch
+ def <=>(other)
+ return nil unless other.is_a?(PlatformMatch)
+
+ m = os_match <=> other.os_match
+ return m unless m.zero?
+
+ m = cpu_match <=> other.cpu_match
+ return m unless m.zero?
+
+ m = platform_version_match <=> other.platform_version_match
+ m
+ end
+
+ EXACT_MATCH = new(-1, -1, -1).freeze
+ WORST_MATCH = new(1_000_000, 1_000_000, 1_000_000).freeze
+
+ def self.os_match(spec_platform, user_platform)
+ if spec_platform.os == user_platform.os
+ 0
+ else
+ 1
+ end
+ end
+
+ def self.cpu_match(spec_platform, user_platform)
+ if spec_platform.cpu == user_platform.cpu
+ 0
+ elsif spec_platform.cpu == "arm" && user_platform.cpu.to_s.start_with?("arm")
+ 0
+ elsif spec_platform.cpu.nil? || spec_platform.cpu == "universal"
+ 1
+ else
+ 2
+ end
+ end
+
+ def self.platform_version_match(spec_platform, user_platform)
+ if spec_platform.version == user_platform.version
+ 0
+ elsif spec_platform.version.nil?
+ 1
+ else
+ 2
+ end
+ end
+ end
end
end
diff --git a/lib/bundler/inline.rb b/lib/bundler/inline.rb
index af542f1e44..dec3be3e98 100644
--- a/lib/bundler/inline.rb
+++ b/lib/bundler/inline.rb
@@ -47,7 +47,7 @@ def gemfile(install = false, options = {}, &gemfile)
definition = builder.to_definition(nil, true)
def definition.lock(*); end
- definition.validate_ruby!
+ definition.validate_runtime!
missing_specs = proc do
begin
diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb
index 36ff5c59ed..0b667f7dbe 100644
--- a/lib/bundler/lazy_specification.rb
+++ b/lib/bundler/lazy_specification.rb
@@ -6,6 +6,20 @@ require "bundler/match_platform"
module Bundler
class LazySpecification
Identifier = Struct.new(:name, :version, :source, :platform, :dependencies)
+ class Identifier
+ include Comparable
+ def <=>(other)
+ return unless other.is_a?(Identifier)
+ [name, version, platform_string] <=> [other.name, other.version, other.platform_string]
+ end
+
+ protected
+
+ def platform_string
+ platform_string = platform.to_s
+ platform_string == Index::RUBY ? Index::NULL : platform_string
+ end
+ end
include MatchPlatform
@@ -55,7 +69,8 @@ module Bundler
end
def __materialize__
- @specification = source.specs.search(Gem::Dependency.new(name, version)).last
+ search_object = Bundler.settings[:specific_platform] ? self : Dependency.new(name, version)
+ @specification = source.specs.search(search_object).last
end
def respond_to?(*args)
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index 063a1887fa..51148ab614 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -92,7 +92,7 @@ module Bundler
end
end
@sources << @rubygems_aggregate
- @specs = @specs.values
+ @specs = @specs.values.sort_by(&:identifier)
warn_for_outdated_bundler_version
rescue ArgumentError => e
Bundler.ui.debug(e)
diff --git a/lib/bundler/match_platform.rb b/lib/bundler/match_platform.rb
index fed418b593..0a4e4c7e3a 100644
--- a/lib/bundler/match_platform.rb
+++ b/lib/bundler/match_platform.rb
@@ -8,7 +8,8 @@ module Bundler
def match_platform(p)
Gem::Platform::RUBY == platform ||
platform.nil? || p == platform ||
- generic(Gem::Platform.new(platform)) === p
+ generic(Gem::Platform.new(platform)) === p ||
+ Gem::Platform.new(platform) === p
end
end
end
diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb
index 015be99af8..8fb4119323 100644
--- a/lib/bundler/plugin.rb
+++ b/lib/bundler/plugin.rb
@@ -62,7 +62,9 @@ module Bundler
save_plugins plugins, installed_specs, builder.inferred_plugins
rescue => e
- Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}"
+ unless e.is_a?(GemfileError)
+ Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}"
+ end
raise
end
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 3ab4ae6f38..b8016b37a9 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -66,44 +66,33 @@ module Bundler
end
end
- ALL = Bundler::Dependency::PLATFORM_MAP.values.uniq.freeze
-
class SpecGroup < Array
include GemHelpers
- attr_reader :activated, :required_by
+ attr_reader :activated
def initialize(a)
super
@required_by = []
@activated_platforms = []
@dependencies = nil
- @specs = {}
-
- ALL.each do |p|
- @specs[p] = reverse.find {|s| s.match_platform(p) }
+ @specs = Hash.new do |specs, platform|
+ specs[platform] = select_best_platform_match(self, platform)
end
end
def initialize_copy(o)
super
- @required_by = o.required_by.dup
@activated_platforms = o.activated.dup
end
def to_specs
- specs = {}
-
- @activated_platforms.each do |p|
+ @activated_platforms.map do |p|
next unless s = @specs[p]
- platform = generic(Gem::Platform.new(s.platform))
- next if specs[platform]
-
- lazy_spec = LazySpecification.new(name, version, platform, source)
+ lazy_spec = LazySpecification.new(name, version, s.platform, source)
lazy_spec.dependencies.replace s.dependencies
- specs[platform] = lazy_spec
- end
- specs.values
+ lazy_spec
+ end.compact
end
def activate_platform!(platform)
@@ -148,17 +137,15 @@ module Bundler
private
def __dependencies
- @dependencies ||= begin
- dependencies = {}
- ALL.each do |p|
- next unless spec = @specs[p]
- dependencies[p] = []
+ @dependencies = Hash.new do |dependencies, platform|
+ dependencies[platform] = []
+ if spec = @specs[platform]
spec.dependencies.each do |dep|
next if dep.type == :development
- dependencies[p] << DepProxy.new(dep, p)
+ dependencies[platform] << DepProxy.new(dep, platform)
end
end
- dependencies
+ dependencies[platform]
end
end
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index fda499cf5a..45f445aec1 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -140,7 +140,8 @@ module Bundler
Bundler.ui.info "Updating files in #{Bundler.settings.app_cache_path}"
- specs.each do |spec|
+ specs_to_cache = Bundler.settings[:cache_all_platforms] ? @definition.resolve.materialized_for_all_platforms : specs
+ specs_to_cache.each do |spec|
next if spec.name == "bundler"
next if spec.source.is_a?(Source::Gemspec)
spec.source.send(:fetch_gem, spec) if Bundler.settings[:cache_all_platforms] && spec.source.respond_to?(:fetch_gem, true)
diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb
index afa7d91838..b6f3a4311d 100644
--- a/lib/bundler/source.rb
+++ b/lib/bundler/source.rb
@@ -14,6 +14,7 @@ module Bundler
def version_message(spec)
message = "#{spec.name} #{spec.version}"
+ message += " (#{spec.platform})" if spec.platform != Gem::Platform::RUBY
if Bundler.locked_gems
locked_spec = Bundler.locked_gems.specs.find {|s| s.name == spec.name }
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index f2ccac4742..fe31b17f0e 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -24,17 +24,9 @@ module Bundler
dep = deps.shift
next if handled[dep] || skip.include?(dep.name)
- spec = lookup[dep.name].find do |s|
- if match_current_platform
- Gem::Platform.match(s.platform)
- else
- s.match_platform(dep.__platform)
- end
- end
-
handled[dep] = true
- if spec
+ if spec = spec_for_dependency(dep, match_current_platform)
specs << spec
spec.dependencies.each do |d|
@@ -99,6 +91,20 @@ module Bundler
SpecSet.new(materialized.compact)
end
+ # Materialize for all the specs in the spec set, regardless of what platform they're for
+ # This is in contrast to how for does platform filtering (and specifically different from how `materialize` calls `for` only for the current platform)
+ # @return [Array<Gem::Specification>]
+ def materialized_for_all_platforms
+ names = @specs.map(&:name).uniq
+ @specs.map do |s|
+ next s unless s.is_a?(LazySpecification)
+ s.source.dependency_names = names if s.source.respond_to?(:dependency_names=)
+ spec = s.__materialize__
+ raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec
+ spec
+ end
+ end
+
def merge(set)
arr = sorted.dup
set.each do |s|
@@ -133,10 +139,7 @@ module Bundler
def lookup
@lookup ||= begin
lookup = Hash.new {|h, k| h[k] = [] }
- specs = @specs.sort_by do |s|
- s.platform.to_s == "ruby" ? "\0" : s.platform.to_s
- end
- specs.reverse_each do |s|
+ Index.sort_specs(@specs).reverse_each do |s|
lookup[s.name] << s
end
lookup
@@ -147,6 +150,18 @@ module Bundler
@specs.each {|s| yield s }
end
+ def spec_for_dependency(dep, match_current_platform)
+ if match_current_platform
+ Bundler.rubygems.platforms.reverse_each do |pl|
+ match = GemHelpers.select_best_platform_match(lookup[dep.name], pl)
+ return match if match
+ end
+ nil
+ else
+ GemHelpers.select_best_platform_match(lookup[dep.name], dep.__platform)
+ end
+ end
+
def tsort_each_child(s)
s.dependencies.sort_by(&:name).each do |d|
next if d.type == :development
diff --git a/spec/bundler/source_spec.rb b/spec/bundler/source_spec.rb
index 25abd90c96..4e99411a17 100644
--- a/spec/bundler/source_spec.rb
+++ b/spec/bundler/source_spec.rb
@@ -22,7 +22,7 @@ describe Bundler::Source do
end
describe "#version_message" do
- let(:spec) { double(:spec, :name => "nokogiri", :version => ">= 1.6") }
+ let(:spec) { double(:spec, :name => "nokogiri", :version => ">= 1.6", :platform => rb) }
shared_examples_for "the lockfile specs are not relevant" do
it "should return a string with the spec name and version" do
diff --git a/spec/install/gemfile/specific_platform_spec.rb b/spec/install/gemfile/specific_platform_spec.rb
new file mode 100644
index 0000000000..3e12f94c86
--- /dev/null
+++ b/spec/install/gemfile/specific_platform_spec.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+describe "bundle install with specific_platform enabled" do
+ before do
+ bundle "config specific_platform true"
+
+ build_repo2 do
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1")
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86_64-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-mingw32" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x64-mingw32" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "universal-darwin" }
+
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86_64-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x64-mingw32" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-mingw32" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5")
+
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "universal-darwin" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86_64-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-mingw32" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x64-mingw32" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.4")
+
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.3")
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86_64-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-mingw32" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x64-mingw32" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "universal-darwin" }
+
+ build_gem("google-protobuf", "3.0.0.alpha.4.0")
+ build_gem("google-protobuf", "3.0.0.alpha.3.1.pre")
+ build_gem("google-protobuf", "3.0.0.alpha.3")
+ build_gem("google-protobuf", "3.0.0.alpha.2.0")
+ build_gem("google-protobuf", "3.0.0.alpha.1.1")
+ build_gem("google-protobuf", "3.0.0.alpha.1.0")
+ end
+ end
+
+ let(:google_protobuf) { <<-G }
+ source "file:#{gem_repo2}"
+ gem "google-protobuf"
+ G
+
+ context "when on a darwin machine" do
+ before { simulate_platform "x86_64-darwin-15" }
+
+ it "locks to both the specific darwin platform and ruby" do
+ install_gemfile!(google_protobuf)
+ expect(the_bundle.locked_gems.platforms).to eq([pl("ruby"), pl("x86_64-darwin-15")])
+ expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w(
+ google-protobuf-3.0.0.alpha.5.0.5.1
+ google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
+ ))
+ end
+
+ it "caches both the universal-darwin and ruby gems when --all-platforms is passed" do
+ gemfile(google_protobuf)
+ bundle! "package --all-platforms"
+ expect([cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1"), cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")]).
+ to all(exist)
+ end
+
+ context "when adding a platform via lock --add_platform" do
+ it "adds the foreign platform" do
+ install_gemfile!(google_protobuf)
+ bundle! "lock --add-platform=#{x64_mingw}"
+
+ expect(the_bundle.locked_gems.platforms).to eq([rb, x64_mingw, pl("x86_64-darwin-15")])
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w(
+ google-protobuf-3.0.0.alpha.5.0.5.1
+ google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
+ google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw32
+ ))
+ end
+
+ it "falls back on plain ruby when that version doesnt have a platform-specific gem" do
+ install_gemfile!(google_protobuf)
+ bundle! "lock --add-platform=#{java}"
+
+ expect(the_bundle.locked_gems.platforms).to eq([java, rb, pl("x86_64-darwin-15")])
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w(
+ google-protobuf-3.0.0.alpha.5.0.5.1
+ google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
+ ))
+ end
+ end
+ end
+end
diff --git a/spec/resolver/platform_spec.rb b/spec/resolver/platform_spec.rb
index d5f217684c..fa91eab9c2 100644
--- a/spec/resolver/platform_spec.rb
+++ b/spec/resolver/platform_spec.rb
@@ -50,7 +50,7 @@ describe "Resolving platform craziness" do
# mingw is _not_ hardcoded to add CPU x86 in rubygems
platforms "x86-mingw32"
dep "thin"
- should_resolve_as %w(thin-1.2.7-x86-mingw32)
+ should_resolve_as %w(thin-1.2.7-mingw32)
end
it "finds x64-mingw gems" do
diff --git a/spec/support/builders.rb b/spec/support/builders.rb
index 337234f14a..7436779d15 100644
--- a/spec/support/builders.rb
+++ b/spec/support/builders.rb
@@ -610,7 +610,10 @@ module Spec
end
def _default_files
- @_default_files ||= { "lib/#{name}.rb" => "#{Builders.constantize(name)} = '#{version}'" }
+ @_default_files ||= begin
+ platform_string = " #{@spec.platform}" unless @spec.platform == Gem::Platform::RUBY
+ { "lib/#{name}.rb" => "#{Builders.constantize(name)} = '#{version}#{platform_string}'" }
+ end
end
def _default_path
diff --git a/spec/support/platforms.rb b/spec/support/platforms.rb
index b1dedb05fa..a2a3afba00 100644
--- a/spec/support/platforms.rb
+++ b/spec/support/platforms.rb
@@ -11,6 +11,10 @@ module Spec
Gem::Platform.new("x86-darwin-10")
end
+ def x64_mac
+ Gem::Platform.new("x86_64-darwin-15")
+ end
+
def java
Gem::Platform.new([nil, "java", nil])
end
diff --git a/spec/support/the_bundle.rb b/spec/support/the_bundle.rb
index 86df9cd9c7..742d393425 100644
--- a/spec/support/the_bundle.rb
+++ b/spec/support/the_bundle.rb
@@ -27,5 +27,10 @@ module Spec
def lockfile
bundle_dir.join("Gemfile.lock")
end
+
+ def locked_gems
+ raise "Cannot read lockfile if it doesn't exist" unless locked?
+ Bundler::LockfileParser.new(lockfile.read)
+ end
end
end