summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Giddins <segiddins@segiddins.me>2016-08-03 18:43:24 -0500
committerSamuel Giddins <segiddins@segiddins.me>2016-08-25 11:16:40 -0500
commita7163e32c3045b25c7bf2b90329971f3788da358 (patch)
tree806d10f9ec7df71df758f13c611fb0a269684157
parent8513ed1481dde5b47eead96dd0a1cfe3d77c4c84 (diff)
downloadbundler-a7163e32c3045b25c7bf2b90329971f3788da358.tar.gz
Resolve for specific platforms
-rw-r--r--lib/bundler/definition.rb14
-rw-r--r--lib/bundler/dependency.rb2
-rw-r--r--lib/bundler/gem_helpers.rb33
-rw-r--r--lib/bundler/lazy_specification.rb2
-rw-r--r--lib/bundler/resolver.rb35
-rw-r--r--lib/bundler/runtime.rb3
-rw-r--r--lib/bundler/source.rb1
-rw-r--r--lib/bundler/spec_set.rb14
-rw-r--r--spec/resolver/platform_spec.rb2
9 files changed, 76 insertions, 30 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index dc3b4690d7..705576c5fc 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,9 @@ module Bundler
@gem_version_promoter = create_gem_version_promoter
- current_platform = Bundler.rubygems.platforms.map {|p| generic(p) }.compact.last
- add_platform(current_platform)
+ current_platform = Bundler.rubygems.platforms.last
+ add_platform(current_platform) if Bundler.settings[:specific_platform]
+ add_platform(generic(current_platform))
@path_changes = converge_paths
eager_unlock = expand_dependencies(@unlock[:gems])
@@ -414,6 +417,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
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..03c1f33fe2 100644
--- a/lib/bundler/gem_helpers.rb
+++ b/lib/bundler/gem_helpers.rb
@@ -28,5 +28,38 @@ 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 [-1, -1, -1] if spec_platform == user_platform
+ return [5, 5, 5] if spec_platform.nil? || spec_platform == Gem::Platform::RUBY || user_platform == Gem::Platform::RUBY
+
+ [
+ if spec_platform.os == user_platform.os
+ 0
+ else
+ 1
+ end,
+
+ 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,
+
+ if spec_platform.version == user_platform.version
+ 0
+ elsif spec_platform.version.nil?
+ 1
+ else
+ 2
+ end,
+ ]
+ end
+ module_function :platform_specificity_match
end
end
diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb
index 36ff5c59ed..0c7b4f2c3d 100644
--- a/lib/bundler/lazy_specification.rb
+++ b/lib/bundler/lazy_specification.rb
@@ -55,7 +55,7 @@ module Bundler
end
def __materialize__
- @specification = source.specs.search(Gem::Dependency.new(name, version)).last
+ @specification = source.specs.search(self).last
end
def respond_to?(*args)
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 3ab4ae6f38..62a9215f66 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -66,8 +66,6 @@ module Bundler
end
end
- ALL = Bundler::Dependency::PLATFORM_MAP.values.uniq.freeze
-
class SpecGroup < Array
include GemHelpers
@@ -78,10 +76,9 @@ module Bundler
@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 {|spec| spec.match_platform(platform) }.
+ min_by {|spec| platform_specificity_match(spec.platform, platform) }
end
end
@@ -92,18 +89,12 @@ module Bundler
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 +139,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..e18d8ba1cb 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 Bundler.ui.debug? && 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..48699abfe4 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -99,6 +99,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|
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