Commit f8ecc02e authored by Marius Rackwitz's avatar Marius Rackwitz

[Analyzer] Introduce PodVariant to combine specs and platform

parent 52b3fe9c
...@@ -13,6 +13,7 @@ module Pod ...@@ -13,6 +13,7 @@ module Pod
autoload :SandboxAnalyzer, 'cocoapods/installer/analyzer/sandbox_analyzer' autoload :SandboxAnalyzer, 'cocoapods/installer/analyzer/sandbox_analyzer'
autoload :SpecsState, 'cocoapods/installer/analyzer/specs_state' autoload :SpecsState, 'cocoapods/installer/analyzer/specs_state'
autoload :LockingDependencyAnalyzer, 'cocoapods/installer/analyzer/locking_dependency_analyzer' autoload :LockingDependencyAnalyzer, 'cocoapods/installer/analyzer/locking_dependency_analyzer'
autoload :PodVariant, 'cocoapods/installer/analyzer/pod_variant'
autoload :TargetInspectionResult, 'cocoapods/installer/analyzer/target_inspection_result' autoload :TargetInspectionResult, 'cocoapods/installer/analyzer/target_inspection_result'
autoload :TargetInspector, 'cocoapods/installer/analyzer/target_inspector' autoload :TargetInspector, 'cocoapods/installer/analyzer/target_inspector'
...@@ -287,29 +288,25 @@ module Pod ...@@ -287,29 +288,25 @@ module Pod
# #
def generate_pod_targets(specs_by_target) def generate_pod_targets(specs_by_target)
if installation_options.deduplicate_targets? if installation_options.deduplicate_targets?
all_specs = specs_by_target.flat_map do |target_definition, dependent_specs| distinct_targets = specs_by_target.each_with_object({}) do |dependency, hash|
dependent_specs.group_by(&:root).map do |root_spec, specs| target_definition, dependent_specs = *dependency
[root_spec, specs, target_definition] dependent_specs.group_by(&:root).each do |root_spec, specs|
end pod_variant = PodVariant.new(specs, target_definition.platform)
end
distinct_targets = all_specs.each_with_object({}) do |dependency, hash|
root_spec, specs, target_definition = *dependency
hash[root_spec] ||= {} hash[root_spec] ||= {}
(hash[root_spec][[specs, target_definition.platform]] ||= []) << target_definition (hash[root_spec][pod_variant] ||= []) << target_definition
end
end end
pod_targets = distinct_targets.flat_map do |_, targets_by_distinctors| pod_targets = distinct_targets.flat_map do |_, target_definitions_by_variant|
if targets_by_distinctors.count > 1 if target_definitions_by_variant.count > 1
# There are different sets of subspecs or the spec is used across different platforms # There are different sets of subspecs or the spec is used across different platforms
suffixes = scope_suffix_for_distinctor(targets_by_distinctors.keys) suffixes = scope_suffixes_for_variants(target_definitions_by_variant.keys)
targets_by_distinctors.flat_map do |distinctor, target_definitions| target_definitions_by_variant.flat_map do |variant, target_definitions|
specs, = *distinctor generate_pod_target(target_definitions, variant.specs, :scope_suffix => suffixes[variant])
generate_pod_target(target_definitions, specs, :scope_suffix => suffixes[distinctor])
end end
else else
(specs, _), target_definitions = targets_by_distinctors.first variant, target_definitions = *target_definitions_by_variant.first
generate_pod_target(target_definitions, specs) generate_pod_target(target_definitions, variant.specs)
end end
end end
else else
...@@ -328,13 +325,13 @@ module Pod ...@@ -328,13 +325,13 @@ module Pod
# Describes what makes pod targets configurations distinct among other. # Describes what makes pod targets configurations distinct among other.
# #
# @param [(Array<Specification>, Platform) => TargetDefinition] distinctors # @param [Array<PodVariant>] variants
# #
# @return [(Array<Specification>, Platform) => String] # @return [Hash<PodVariant, String>]
# #
def scope_suffix_for_distinctor(distinctors) def scope_suffixes_for_variants(variants)
all_spec_variants = distinctors.map { |k| k[0] } all_spec_variants = variants.map(&:specs)
all_platform_variants = distinctors.map { |k| k[1] } all_platform_variants = variants.map(&:platform)
all_platform_name_variants = all_platform_variants.map(&:name) all_platform_name_variants = all_platform_variants.map(&:name)
if all_platform_name_variants.uniq.count == all_platform_name_variants.count if all_platform_name_variants.uniq.count == all_platform_name_variants.count
...@@ -346,27 +343,25 @@ module Pod ...@@ -346,27 +343,25 @@ module Pod
end end
if all_platform_variants.uniq.count == all_platform_variants.count if all_platform_variants.uniq.count == all_platform_variants.count
result = distinctors.map { |d| [d, platform_name_proc.call(d[1])] } result = variants.map { |v| [v, platform_name_proc.call(v.platform)] }
else else
common_specs = all_spec_variants.reduce(all_spec_variants.first, &:&) common_specs = all_spec_variants.reduce(all_spec_variants.first, &:&)
result = distinctors.map do |distinctor| result = variants.map do |variant|
specs, = *distinctor subspecs = variant.specs - common_specs
specs -= common_specs subspec_names = subspecs.map { |spec| spec.name.split('/')[1..-1].join('_') }
subspec_names = specs.map { |spec| spec.name.split('/')[1..-1].join('_') }
# => Subspecs names without common subspecs # => Subspecs names without common subspecs
[distinctor, subspec_names.empty? ? nil : subspec_names.join('-')] [variant, subspec_names.empty? ? nil : subspec_names.join('-')]
end end
if all_spec_variants.count > all_spec_variants.uniq.count if all_spec_variants.count > all_spec_variants.uniq.count
result.map! do |distinctor, suffix| result.map! do |variant, suffix|
_, platform = *distinctor platform_name = platform_name_proc.call(variant.platform)
platform_name = platform_name_proc.call(platform)
# => Platform name (+ SDK version) + subspecs names without common subspecs # => Platform name (+ SDK version) + subspecs names without common subspecs
[distinctor, [platform_name, suffix].compact.join('-')] [variant, [platform_name, suffix].compact.join('-')]
end end
end end
end end
Hash[result.map { |d, name| [d, name && name.tr('/', '_')] }] Hash[result.map { |v, name| [v, name && name.tr('/', '_')] }]
end end
# Finds the names of the Pods upon which the given target _transitively_ # Finds the names of the Pods upon which the given target _transitively_
......
module Pod
class Installer
class Analyzer
# Bundles the information needed to setup a {PodTarget}.
class PodVariant
# @return [Array<Specification>] the spec and subspecs for the target
#
attr_accessor :specs
# @return [Platform] the platform
#
attr_accessor :platform
# @return [Specification] the root specification
#
def root_spec
specs.first.root
end
# @param [Array<String>] specs @see #specs
# @param [Platform] platform @see #platform
#
def initialize(specs, platform)
self.specs = specs
self.platform = platform
end
# @return [Bool] whether the {PodVariant} is equal to another taking all
# all their attributes into account
#
def ==(other)
self.class == other.class &&
specs == other.specs &&
platform == other.platform
end
alias_method :eql?, :==
# Hashes the instance by all its attributes.
#
# This adds support to make instances usable as Hash keys.
#
# @!visibility private
def hash
[specs, platform].hash
end
end
end
end
end
...@@ -130,46 +130,48 @@ module Pod ...@@ -130,46 +130,48 @@ module Pod
#--------------------------------------# #--------------------------------------#
describe '#scope_suffix_for_distinctor' do describe '#scope_suffixes_for_variants' do
before do before do
@analyzer = Pod::Installer::Analyzer.new(config.sandbox, stub('Podfile'), nil) @analyzer = Pod::Installer::Analyzer.new(config.sandbox, stub('Podfile'), nil)
@root_spec = stub(:name => 'Spec') @root_spec = stub(:name => 'Spec')
end end
PodVariant = Pod::Installer::Analyzer::PodVariant.freeze
it 'returns scopes by platform names if they qualify' do it 'returns scopes by platform names if they qualify' do
specs = [ variants = [
[[@root_spec], Platform.ios], PodVariant.new([@root_spec], Platform.ios),
[[@root_spec], Platform.osx], PodVariant.new([@root_spec], Platform.osx),
] ]
@analyzer.send(:scope_suffix_for_distinctor, specs).values.should == %w(iOS OSX) @analyzer.send(:scope_suffixes_for_variants, variants).values.should == %w(iOS OSX)
end end
it 'returns scopes by versioned platform names if they qualify' do it 'returns scopes by versioned platform names if they qualify' do
specs = [ variants = [
[[@root_spec], Platform.ios], PodVariant.new([@root_spec], Platform.ios),
[[@root_spec], Platform.new(:ios, '7.0')], PodVariant.new([@root_spec], Platform.new(:ios, '7.0')),
] ]
@analyzer.send(:scope_suffix_for_distinctor, specs).values.should == ['iOS', 'iOS7.0'] @analyzer.send(:scope_suffixes_for_variants, variants).values.should == ['iOS', 'iOS7.0']
end end
it 'returns scopes by subspec names if they qualify' do it 'returns scopes by subspec names if they qualify' do
shared_subspec = stub(:name => 'Spec/Shared') shared_subspec = stub(:name => 'Spec/Shared')
specs = [ variants = [
[[@root_spec, shared_subspec], Platform.ios], PodVariant.new([@root_spec, shared_subspec], Platform.ios),
[[@root_spec, shared_subspec, stub(:name => 'Spec/Foo')], Platform.ios], PodVariant.new([@root_spec, shared_subspec, stub(:name => 'Spec/Foo')], Platform.ios),
[[@root_spec, shared_subspec, stub(:name => 'Spec/Bar')], Platform.ios], PodVariant.new([@root_spec, shared_subspec, stub(:name => 'Spec/Bar')], Platform.ios),
] ]
@analyzer.send(:scope_suffix_for_distinctor, specs).values.should == [nil, 'Foo', 'Bar'] @analyzer.send(:scope_suffixes_for_variants, variants).values.should == [nil, 'Foo', 'Bar']
end end
it 'returns scopes by platform names and subspec names if they qualify' do it 'returns scopes by platform names and subspec names if they qualify' do
specs = [ variants = [
[[@root_spec], Platform.ios], PodVariant.new([@root_spec], Platform.ios),
[[@root_spec, stub(:name => 'Spec/Foo')], Platform.ios], PodVariant.new([@root_spec, stub(:name => 'Spec/Foo')], Platform.ios),
[[@root_spec], Platform.osx], PodVariant.new([@root_spec], Platform.osx),
[[@root_spec, stub(:name => 'Spec/Bar')], Platform.osx], PodVariant.new([@root_spec, stub(:name => 'Spec/Bar')], Platform.osx),
] ]
@analyzer.send(:scope_suffix_for_distinctor, specs).values.should == [ @analyzer.send(:scope_suffixes_for_variants, variants).values.should == [
'iOS', 'iOS',
'iOS-Foo', 'iOS-Foo',
'OSX', 'OSX',
...@@ -179,12 +181,12 @@ module Pod ...@@ -179,12 +181,12 @@ module Pod
it 'returns scopes by versioned platform names and subspec names if they qualify' do it 'returns scopes by versioned platform names and subspec names if they qualify' do
specs = [ specs = [
[[@root_spec], Platform.new(:ios, '7.0')], PodVariant.new([@root_spec], Platform.new(:ios, '7.0')),
[[@root_spec, stub(:name => 'Spec/Foo')], Platform.ios], PodVariant.new([@root_spec, stub(:name => 'Spec/Foo')], Platform.ios),
[[@root_spec], Platform.osx], PodVariant.new([@root_spec], Platform.osx),
[[@root_spec, stub(:name => 'Spec/Bar')], Platform.osx], PodVariant.new([@root_spec, stub(:name => 'Spec/Bar')], Platform.osx),
] ]
@analyzer.send(:scope_suffix_for_distinctor, specs).values.should == [ @analyzer.send(:scope_suffixes_for_variants, specs).values.should == [
'iOS7.0', 'iOS7.0',
'iOS-Foo', 'iOS-Foo',
'OSX', 'OSX',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment