Commit 38391fc7 authored by Dimitris Koutsogiorgas's avatar Dimitris Koutsogiorgas Committed by GitHub

Merge pull request #7014 from dnkoutso/filter_test_only_pod_targets

Use the resolver to identify which pod targets are test only
parents 821f2080 99084c7d
......@@ -34,6 +34,11 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
[Dimitris Koutsogiorgas](https://github.com/dnkoutso)
[#7019](https://github.com/CocoaPods/CocoaPods/pull/7019)
* Use the resolver to identify which pod targets are test only
[Dimitris Koutsogiorgas](https://github.com/dnkoutso)
[Justin Martin](https://github.com/justinseanmartin)
[#7014](https://github.com/CocoaPods/CocoaPods/pull/7014)
* Perform code signing on xctest bundles in the Pods project generated by a test spec
[Justin Martin](https://github.com/justinseanmartin)
[#7013](https://github.com/CocoaPods/CocoaPods/pull/7013)
......
......@@ -75,11 +75,15 @@ module Pod
store_existing_checkout_options
fetch_external_sources if allow_fetches
@locked_dependencies = generate_version_locking_dependencies
@result.specs_by_target = validate_platforms(resolve_dependencies)
@result.specifications = generate_specifications
@result.targets = generate_targets
@locked_dependencies = generate_version_locking_dependencies
resolver_specs_by_target = resolve_dependencies
validate_platforms(resolver_specs_by_target)
@result.specifications = generate_specifications(resolver_specs_by_target)
@result.targets = generate_targets(resolver_specs_by_target)
@result.sandbox_state = generate_sandbox_state
@result.specs_by_target = resolver_specs_by_target.each_with_object({}) do |rspecs_by_target, hash|
hash[rspecs_by_target[0]] = rspecs_by_target[1].map(&:spec)
end
@result
end
......@@ -365,13 +369,17 @@ module Pod
# Creates the models that represent the targets generated by CocoaPods.
#
# @return [Array<AggregateTarget>]
# @param [Hash{Podfile::TargetDefinition => Array<ResolvedSpecification>}] resolver_specs_by_target
# mapping of targets to resolved specs (containing information about test usage)
# aggregate targets
#
# @return [Array<AggregateTarget>] the list of aggregate targets generated.
#
def generate_targets
specs_by_target = result.specs_by_target.reject { |td, _| td.abstract? }
pod_targets = generate_pod_targets(specs_by_target)
aggregate_targets = specs_by_target.keys.map do |target_definition|
generate_target(target_definition, pod_targets)
def generate_targets(resolver_specs_by_target)
resolver_specs_by_target = resolver_specs_by_target.reject { |td, _| td.abstract? }
pod_targets = generate_pod_targets(resolver_specs_by_target)
aggregate_targets = resolver_specs_by_target.keys.map do |target_definition|
generate_target(target_definition, pod_targets, resolver_specs_by_target)
end
if installation_options.integrate_targets?
# Copy embedded target pods that cannot have their pods embedded as frameworks to
......@@ -406,9 +414,12 @@ module Pod
# @param [Array<PodTarget>] pod_targets
# the pod targets, which were generated.
#
# @param [Hash{Podfile::TargetDefinition => Array<ResolvedSpecification>}] resolver_specs_by_target
# the resolved specifications grouped by target.
#
# @return [AggregateTarget]
#
def generate_target(target_definition, pod_targets)
def generate_target(target_definition, pod_targets, resolver_specs_by_target)
target = AggregateTarget.new(target_definition, sandbox)
target.host_requires_frameworks |= target_definition.uses_frameworks?
......@@ -429,7 +440,7 @@ module Pod
end
end
target.pod_targets = filter_pod_targets_for_target_definition(pod_targets, target_definition)
target.pod_targets = filter_pod_targets_for_target_definition(target_definition, pod_targets, resolver_specs_by_target)
target
end
......@@ -437,61 +448,40 @@ module Pod
# Returns a filtered list of pod targets that should or should not be part of the target definition. Pod targets
# used by tests only are filtered.
#
# @param [Array<PodTarget>] pod_targets
# the array of pod targets to check against
#
# @param [TargetDefinition] target_definition
# the target definition to use as the base for filtering
#
# @return [Array<PodTarget>] the filtered list of pod targets.
#
def filter_pod_targets_for_target_definition(pod_targets, target_definition)
pod_targets.select do |pod_target|
pod_target.target_definitions.include?(target_definition) && !pod_target_test_only?(pod_target, pod_targets)
end
end
# Returns true if a pod target is only used by other pod targets as a test dependency and therefore should
# not be included as part of the aggregate target.
#
# @param [PodTarget] pod_target
# the pod target being queried
#
# @param [Array<PodTarget>] pod_targets
# the array of pod targets to check against
#
# @return [Boolean] if the pod target is only referenced from test dependencies.
# @param [Hash{Podfile::TargetDefinition => Array<ResolvedSpecification>}] resolver_specs_by_target
# the resolved specifications grouped by target.
#
def pod_target_test_only?(pod_target, pod_targets)
name = pod_target.name
key = @test_pod_target_key.new(name, pod_targets)
if @test_pod_target_analyzer_cache.key?(key)
return @test_pod_target_analyzer_cache[key]
end
source = pod_targets.any? do |pt|
pt.dependent_targets.map(&:name).include?(name)
end
test = pod_targets.any? do |pt|
pt.test_dependent_targets.reject { |dpt| dpt.name == pt.name }.map(&:name).include?(name)
# @return [Array<PodTarget>] the filtered list of pod targets.
#
def filter_pod_targets_for_target_definition(target_definition, pod_targets, resolver_specs_by_target)
pod_targets.select do |pod_target|
included_in_target_definition = pod_target.target_definitions.include?(target_definition)
used_by_tests_only = resolver_specs_by_target[target_definition].select { |resolver_spec| pod_target.specs.include?(resolver_spec.spec) }.all?(&:used_by_tests_only?)
included_in_target_definition && !used_by_tests_only
end
@test_pod_target_analyzer_cache[key] = !source && test
end
# Setup the pod targets for an aggregate target. Deduplicates resulting
# targets by grouping by platform and subspec by their root
# to create a {PodTarget} for each spec.
#
# @param [Hash{Podfile::TargetDefinition => Array<Specification>}] specs_by_target
# @param [Hash{Podfile::TargetDefinition => Array<ResolvedSpecification>}] resolver_specs_by_target
# the resolved specifications grouped by target.
#
# @return [Array<PodTarget>]
#
def generate_pod_targets(specs_by_target)
def generate_pod_targets(resolver_specs_by_target)
if installation_options.deduplicate_targets?
distinct_targets = specs_by_target.each_with_object({}) do |dependency, hash|
distinct_targets = resolver_specs_by_target.each_with_object({}) do |dependency, hash|
target_definition, dependent_specs = *dependency
dependent_specs.group_by(&:root).each do |root_spec, specs|
pod_variant = PodVariant.new(specs, target_definition.platform, target_definition.uses_frameworks?)
dependent_specs.group_by(&:root).each do |root_spec, resolver_specs|
pod_variant = PodVariant.new(resolver_specs.map(&:spec), target_definition.platform, target_definition.uses_frameworks?)
hash[root_spec] ||= {}
(hash[root_spec][pod_variant] ||= []) << target_definition
end
......@@ -504,30 +494,30 @@ module Pod
end
end
all_specs = specs_by_target.values.flatten.uniq
all_resolver_specs = resolver_specs_by_target.values.flatten.map(&:spec).uniq
pod_targets_by_name = pod_targets.group_by(&:pod_name).each_with_object({}) do |(name, values), hash|
# Sort the target by the number of activated subspecs, so that
# we prefer a minimal target as transitive dependency.
hash[name] = values.sort_by { |pt| pt.specs.count }
end
pod_targets.each do |target|
dependencies = transitive_dependencies_for_specs(target.specs.reject(&:test_specification?), target.platform, all_specs).group_by(&:root)
test_dependencies = transitive_dependencies_for_specs(target.specs.select(&:test_specification?), target.platform, all_specs).group_by(&:root)
dependencies = transitive_dependencies_for_specs(target.specs.reject(&:test_specification?), target.platform, all_resolver_specs).group_by(&:root)
test_dependencies = transitive_dependencies_for_specs(target.specs.select(&:test_specification?), target.platform, all_resolver_specs).group_by(&:root)
test_dependencies.delete_if { |k| dependencies.key? k }
target.dependent_targets = filter_dependencies(dependencies, pod_targets_by_name, target)
target.test_dependent_targets = filter_dependencies(test_dependencies, pod_targets_by_name, target)
end
else
dedupe_cache = {}
specs_by_target.flat_map do |target_definition, specs|
resolver_specs_by_target.flat_map do |target_definition, specs|
grouped_specs = specs.group_by(&:root).values.uniq
pod_targets = grouped_specs.flat_map do |pod_specs|
generate_pod_target([target_definition], pod_specs).scoped(dedupe_cache)
generate_pod_target([target_definition], pod_specs.map(&:spec)).scoped(dedupe_cache)
end
pod_targets.each do |target|
dependencies = transitive_dependencies_for_specs(target.specs, target.platform, specs).group_by(&:root)
test_dependencies = transitive_dependencies_for_specs(target.specs.select(&:test_specification?), target.platform, all_specs).group_by(&:root)
dependencies = transitive_dependencies_for_specs(target.specs.reject(&:test_specification?), target.platform, specs.map(&:spec)).group_by(&:root)
test_dependencies = transitive_dependencies_for_specs(target.specs.select(&:test_specification?), target.platform, specs.map(&:spec)).group_by(&:root)
test_dependencies.delete_if { |k| dependencies.key? k }
target.dependent_targets = pod_targets.reject { |t| dependencies[t.root_spec].nil? }
target.test_dependent_targets = pod_targets.reject { |t| test_dependencies[t.root_spec].nil? }
......@@ -764,27 +754,27 @@ module Pod
"- #{dependencies.map(&:to_s).join("\n- ")}"
end
specs_by_target = nil
resolver_specs_by_target = nil
UI.section "Resolving dependencies of #{UI.path(podfile.defined_in_file) || 'Podfile'}" do
resolver = Resolver.new(sandbox, podfile, locked_dependencies, sources)
resolver.specs_updated = specs_updated?
specs_by_target = resolver.resolve
specs_by_target.values.flatten(1).each(&:validate_cocoapods_version)
resolver_specs_by_target = resolver.resolve
resolver_specs_by_target.values.flatten(1).map(&:spec).each(&:validate_cocoapods_version)
end
specs_by_target
resolver_specs_by_target
end
# Warns for any specification that is incompatible with its target.
#
# @param [Hash{TargetDefinition => Array<Spec>}] specs_by_target
# @param [Hash{TargetDefinition => Array<Spec>}] resolver_specs_by_target
# the specifications grouped by target.
#
# @return [Hash{TargetDefinition => Array<Spec>}] the specifications
# grouped by target.
#
def validate_platforms(specs_by_target)
specs_by_target.each do |target, specs|
specs.each do |spec|
def validate_platforms(resolver_specs_by_target)
resolver_specs_by_target.each do |target, specs|
specs.map(&:spec).each do |spec|
next unless target_platform = target.platform
unless spec.available_platforms.any? { |p| target_platform.supports?(p) }
UI.warn "The platform of the target `#{target.name}` " \
......@@ -795,12 +785,12 @@ module Pod
end
end
# Returns the list of all the resolved the resolved specifications.
# Returns the list of all the resolved specifications.
#
# @return [Array<Specification>] the list of the specifications.
#
def generate_specifications
result.specs_by_target.values.flatten.uniq
def generate_specifications(resolver_specs_by_target)
resolver_specs_by_target.values.flatten.map(&:spec).uniq
end
# Computes the state of the sandbox respect to the resolved
......
......@@ -12,6 +12,39 @@ module Pod
# by target for a given Podfile.
#
class Resolver
# A small container that wraps a resolved specification for a given target definition. Additional metadata
# is included here such as if the specification is only used by tests.
#
class ResolverSpecification
# @return [Specification] the specification that was resolved
#
attr_reader :spec
# @return [Bool] whether this resolved specification is only used by tests.
#
attr_reader :used_by_tests_only
alias used_by_tests_only? used_by_tests_only
def initialize(spec, used_by_tests_only)
@spec = spec
@used_by_tests_only = used_by_tests_only
end
def name
spec.name
end
def root
spec.root
end
def ==(other)
self.class == other &&
spec == other.spec &&
used_by_tests_only == other.test_only
end
end
include Pod::Installer::InstallationOptions::Mixin
delegate_installation_options { podfile }
......@@ -64,8 +97,8 @@ module Pod
# Identifies the specifications that should be installed.
#
# @return [Hash{TargetDefinition => Array<Specification>}] specs_by_target
# the specifications that need to be installed grouped by target
# @return [Hash{TargetDefinition => Array<ResolverSpecification>}] resolver_specs_by_target
# the resolved specifications that need to be installed grouped by target
# definition.
#
def resolve
......@@ -75,28 +108,28 @@ module Pod
end
end
@activated = Molinillo::Resolver.new(self, self).resolve(dependencies, locked_dependencies)
specs_by_target
resolver_specs_by_target
rescue Molinillo::ResolverError => e
handle_resolver_error(e)
end
# @return [Hash{Podfile::TargetDefinition => Array<Specification>}]
# @return [Hash{Podfile::TargetDefinition => Array<ResolverSpecification>}]
# returns the resolved specifications grouped by target.
#
# @note The returned specifications can be subspecs.
#
def specs_by_target
@specs_by_target ||= {}.tap do |specs_by_target|
def resolver_specs_by_target
@resolver_specs_by_target ||= {}.tap do |resolver_specs_by_target|
podfile.target_definition_list.each do |target|
dependencies = {}
specs = target.dependencies.map(&:name).flat_map do |name|
node = @activated.vertex_named(name)
valid_dependencies_for_target_from_node(target, dependencies, node) << node
(valid_dependencies_for_target_from_node(target, dependencies, node) << node).map { |s| [s, node.payload.test_specification?] }
end
specs_by_target[target] = specs.
map(&:payload).
uniq.
resolver_specs_by_target[target] = specs.
group_by(&:first).
map { |vertex, spec_test_only_tuples| ResolverSpecification.new(vertex.payload, spec_test_only_tuples.map { |tuple| tuple[1] }.all?) }.
sort_by(&:name)
end
end
......@@ -517,7 +550,6 @@ module Pod
dependency_nodes + dependency_nodes.flat_map do |item|
node_result = valid_dependencies_for_target_from_node(target, dependencies, item)
node_result
end
end
......
......@@ -672,84 +672,30 @@ module Pod
#-------------------------------------------------------------------------#
it 'handles test only pod targets' do
pod_target_one = stub(:name => 'Pod1', :dependent_targets => [], :test_dependent_targets => [])
pod_target_two = stub(:name => 'Pod2', :dependent_targets => [], :test_dependent_targets => [])
pod_target_three = stub(:name => 'Pod3', :dependent_targets => [pod_target_one, pod_target_two], :test_dependent_targets => [])
pod_target_four = stub(:name => 'Pod4', :dependent_targets => [], :test_dependent_targets => [pod_target_three])
all_pod_targets = [pod_target_one, pod_target_two, pod_target_three, pod_target_four]
@analyzer.send(:pod_target_test_only?, pod_target_one, all_pod_targets).should.be.false
@analyzer.send(:pod_target_test_only?, pod_target_two, all_pod_targets).should.be.false
@analyzer.send(:pod_target_test_only?, pod_target_three, all_pod_targets).should.be.true
@analyzer.send(:pod_target_test_only?, pod_target_four, all_pod_targets).should.be.false
end
it 'handles test only pod targets that depend on themselves as tests' do
pod_target_one = stub(:name => 'Pod1', :dependent_targets => [])
pod_target_one.stubs(:test_dependent_targets => [pod_target_one])
all_pod_targets = [pod_target_one]
@analyzer.send(:pod_target_test_only?, pod_target_one, all_pod_targets).should.be.false
end
it 'handles test only pod targets that depend on themselves as tests but are also dependent as sources' do
pod_target_one = stub(:name => 'Pod1', :dependent_targets => [])
pod_target_one.stubs(:test_dependent_targets => [pod_target_one])
pod_target_two = stub(:name => 'Pod2', :dependent_targets => [pod_target_one], :test_dependent_targets => [])
all_pod_targets = [pod_target_one, pod_target_two]
@analyzer.send(:pod_target_test_only?, pod_target_one, all_pod_targets).should.be.false
end
it 'includes pod target when declared in the target definition and is not test only' do
it 'does include pod target if any spec is not used by tests only and is part of target definition' do
spec1 = Resolver::ResolverSpecification.new(stub, false)
spec2 = Resolver::ResolverSpecification.new(stub, true)
target_definition = stub
pod_target = stub(:name => 'Pod1', :dependent_targets => [], :test_dependent_targets => [], :target_definitions => [target_definition])
all_pod_targets = [pod_target]
@analyzer.stubs(:pod_target_test_only?).with(pod_target, all_pod_targets).returns(false)
@analyzer.send(:filter_pod_targets_for_target_definition, all_pod_targets, target_definition).should == [pod_target]
pod_target = stub(:name => 'Pod1', :target_definitions => [target_definition], :specs => [spec1.spec, spec2.spec])
resolver_specs_by_target = { target_definition => [spec1, spec2] }
@analyzer.send(:filter_pod_targets_for_target_definition, target_definition, [pod_target], resolver_specs_by_target).should == [pod_target]
end
it 'includes pod target when declared in the pod target definition but has a test dependency on itself' do
it 'does not include pod target if its used by tests only' do
spec1 = Resolver::ResolverSpecification.new(stub, true)
spec2 = Resolver::ResolverSpecification.new(stub, true)
target_definition = stub
pod_target = stub(:name => 'Pod1', :dependent_targets => [], :target_definitions => [target_definition])
pod_target.stubs(:test_dependent_targets => [pod_target])
all_pod_targets = [pod_target]
@analyzer.send(:filter_pod_targets_for_target_definition, all_pod_targets, target_definition).should == [pod_target]
pod_target = stub(:name => 'Pod1', :target_definitions => [target_definition], :specs => [spec1.spec, spec2.spec])
resolver_specs_by_target = { target_definition => [spec1, spec2] }
@analyzer.send(:filter_pod_targets_for_target_definition, target_definition, [pod_target], resolver_specs_by_target).should.be.empty
end
it 'does not include pod target if declared within pod target definition and is a test only target' do
it 'does not include pod target if its not part of the target definition' do
spec = Resolver::ResolverSpecification.new(stub, false)
target_definition = stub
pod_target = stub(:name => 'Pod1', :dependent_targets => [], :test_dependent_targets => [], :target_definitions => [target_definition])
all_pod_targets = [pod_target]
@analyzer.stubs(:pod_target_test_only?).with(pod_target, all_pod_targets).returns(true)
@analyzer.send(:filter_pod_targets_for_target_definition, all_pod_targets, target_definition).should.be.empty
end
it 'does not include pod target if not within target definition' do
target_definition = stub
pod_target = stub(:name => 'Pod1', :dependent_targets => [], :test_dependent_targets => [], :target_definitions => [])
all_pod_targets = [pod_target]
@analyzer.send(:filter_pod_targets_for_target_definition, all_pod_targets, target_definition).should.be.empty
end
it 'handles complicated scenario of pod target dependencies' do
target_definition_one = stub
target_definition_two = stub
pod_target_one = stub(:name => 'Pod1', :dependent_targets => [], :test_dependent_targets => [], :target_definitions => [target_definition_one, target_definition_two])
pod_target_two = stub(:name => 'Pod2', :dependent_targets => [], :test_dependent_targets => [], :target_definitions => [target_definition_one])
pod_target_three = stub(:name => 'Pod3', :dependent_targets => [], :target_definitions => [target_definition_two])
pod_target_three.stubs(:test_dependent_targets => [pod_target_three])
pod_target_four = stub(:name => 'Pod4', :dependent_targets => [pod_target_one], :test_dependent_targets => [], :target_definitions => [target_definition_one])
pod_target_five = stub(:name => 'Pod5', :dependent_targets => [pod_target_one], :test_dependent_targets => [pod_target_three], :target_definitions => [target_definition_two])
all_pod_targets = [pod_target_one, pod_target_two, pod_target_three, pod_target_four, pod_target_five]
@analyzer.send(:filter_pod_targets_for_target_definition, all_pod_targets, target_definition_one).should == [
pod_target_one,
pod_target_two,
pod_target_four,
]
@analyzer.send(:filter_pod_targets_for_target_definition, all_pod_targets, target_definition_two).should == [
pod_target_one,
pod_target_five,
]
pod_target = stub(:name => 'Pod1', :target_definitions => [], :specs => [spec.spec])
resolver_specs_by_target = { target_definition => [spec] }
@analyzer.send(:filter_pod_targets_for_target_definition, target_definition, [pod_target], resolver_specs_by_target).should.be.empty
end
describe 'extension targets' do
......
......@@ -52,7 +52,7 @@ module Pod
it 'resolves the specification of the podfile' do
target_definition = @podfile.target_definitions['Pods']
specs = @resolver.resolve[target_definition]
specs.map(&:to_s).should == [
specs.map(&:spec).map(&:to_s).should == [
'A2DynamicDelegate (2.0.2)',
'BlocksKit (1.5.2)',
'libffi (3.0.13)',
......@@ -62,8 +62,8 @@ module Pod
it 'returns the resolved specifications grouped by target definition' do
@resolver.resolve
target_definition = @podfile.target_definitions['Pods']
specs = @resolver.specs_by_target[target_definition]
specs.map(&:to_s).should == [
specs = @resolver.resolver_specs_by_target[target_definition]
specs.map(&:spec).map(&:to_s).should == [
'A2DynamicDelegate (2.0.2)',
'BlocksKit (1.5.2)',
'libffi (3.0.13)',
......@@ -80,8 +80,8 @@ module Pod
end
resolver = Resolver.new(config.sandbox, podfile, empty_graph, config.sources_manager.all)
resolver.resolve
specs = resolver.specs_by_target.values.flatten
specs.map(&:to_s).should == ['Reachability (3.0.0)']
specs = resolver.resolver_specs_by_target.values.flatten
specs.map(&:spec).map(&:to_s).should == ['Reachability (3.0.0)']
end
it 'resolves an empty podfile' do
......@@ -89,7 +89,7 @@ module Pod
platform :ios
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should == []
end
end
......@@ -113,7 +113,7 @@ module Pod
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should == ['AFNetworking (0.9.1)', 'AFQuickLookView (0.1.0)']
end
......@@ -125,7 +125,7 @@ module Pod
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should == ['AFNetworking (1.2.1)', 'RestKit (0.20.1)',
'RestKit/Core (0.20.1)', 'RestKit/CoreData (0.20.1)',
'RestKit/Network (0.20.1)', 'RestKit/ObjectMapping (0.20.1)',
......@@ -141,7 +141,7 @@ module Pod
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should == ['AFAmazonS3Client (1.0.1)', 'AFNetworking (1.3.4)',
'AFOAuth2Client (1.0.0)', 'CargoBay (1.0.0)']
end
......@@ -155,7 +155,7 @@ module Pod
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:root).map(&:to_s).uniq.sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:root).map(&:to_s).uniq.sort
specs.should == ['AFNetworking (2.0.1)', 'InstagramKit (3.7)']
end
......@@ -186,7 +186,7 @@ module Pod
pod 'AFNetworking' # the most recent version requires 10.8
end
@resolver.stubs(:podfile).returns(@podfile)
@resolver.resolve.values.flatten.map(&:to_s).sort.should == [
@resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort.should == [
'AFNetworking (1.3.4)',
]
end
......@@ -210,7 +210,7 @@ module Pod
end
@resolver.stubs(:podfile).returns(@podfile)
@resolver.send(:cached_sets)['lib'] = stub(:all_specifications => [spec])
@resolver.resolve.values.flatten.map(&:to_s).sort.should == [
@resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort.should == [
'AFNetworking (1.3.4)', 'lib (1.0)', 'lib/Calendar (1.0)', 'lib/Classes (1.0)', 'lib/RequestManager (1.0)'
]
end
......@@ -287,7 +287,7 @@ module Pod
pod 'RestKit', '0.20.0-rc1'
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
resolver.resolve.values.flatten.map(&:to_s).sort.should == [
resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort.should == [
'AFNetworking (1.1.0)',
'RestKit (0.20.0-rc1)',
'RestKit/Core (0.20.0-rc1)',
......@@ -322,6 +322,86 @@ module Pod
)
end
it 'handles test only dependencies correctly' do
@podfile = Podfile.new do
platform :ios
pod 'MainSpec', :git => 'GIT-URL', :testspecs => ['Tests']
end
spec = Spec.new do |s|
s.name = 'MainSpec'
s.version = '1.2.3'
s.platform = :ios
s.test_spec 'Tests' do |tss|
tss.source_files = 'some/file'
end
end
config.sandbox.expects(:specification).with('MainSpec').returns(spec)
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
resolved_specs = resolver.resolve.values.flatten
spec_names = resolved_specs.map(&:name).sort
spec_names.should == %w(
MainSpec MainSpec/Tests
)
resolved_specs.find { |rs| rs.name == 'MainSpec' }.used_by_tests_only?.should.be.false
resolved_specs.find { |rs| rs.name == 'MainSpec/Tests' }.used_by_tests_only?.should.be.true
end
it 'handles test only transitive dependencies' do
@podfile = Podfile.new do
platform :ios
pod 'MainSpec', :git => 'GIT-URL', :testspecs => ['Tests']
end
spec = Spec.new do |s|
s.name = 'MainSpec'
s.version = '1.2.3'
s.platform = :ios
s.test_spec 'Tests' do |tss|
tss.source_files = 'some/file'
tss.dependency 'Expecta'
end
end
config.sandbox.expects(:specification).with('MainSpec').returns(spec)
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
resolved_specs = resolver.resolve.values.flatten
spec_names = resolved_specs.map(&:name).sort
spec_names.should == %w(
Expecta MainSpec MainSpec/Tests
)
resolved_specs.find { |rs| rs.name == 'Expecta' }.used_by_tests_only?.should.be.true
resolved_specs.find { |rs| rs.name == 'MainSpec' }.used_by_tests_only?.should.be.false
resolved_specs.find { |rs| rs.name == 'MainSpec/Tests' }.used_by_tests_only?.should.be.true
end
it 'handles test only dependencies when they are also required by sources' do
@podfile = Podfile.new do
platform :ios
pod 'MainSpec', :git => 'GIT-URL', :testspecs => ['Tests']
end
spec = Spec.new do |s|
s.name = 'MainSpec'
s.version = '1.2.3'
s.platform = :ios
s.dependency 'Expecta'
s.test_spec 'Tests' do |tss|
tss.source_files = 'some/file'
tss.dependency 'Expecta'
end
end
config.sandbox.expects(:specification).with('MainSpec').returns(spec)
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
resolved_specs = resolver.resolve.values.flatten
spec_names = resolved_specs.map(&:name).sort
spec_names.should == %w(
Expecta MainSpec MainSpec/Tests
)
resolved_specs.find { |rs| rs.name == 'Expecta' }.used_by_tests_only?.should.be.false
resolved_specs.find { |rs| rs.name == 'MainSpec' }.used_by_tests_only?.should.be.false
resolved_specs.find { |rs| rs.name == 'MainSpec/Tests' }.used_by_tests_only?.should.be.true
end
it 'allows pre-release spec versions when a requirement has an ' \
'external source' do
@podfile = Podfile.new do
......@@ -335,7 +415,7 @@ module Pod
end
config.sandbox.expects(:specification).with('MainSpec').returns(spec)
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should == [
'MainSpec (1.2.3-pre)',
]
......@@ -461,12 +541,12 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
pod 'JSONKit', '<= 1.5pre'
end
resolver = Resolver.new(config.sandbox, podfile, empty_graph, config.sources_manager.all)
version = resolver.resolve.values.flatten.first.version
version = resolver.resolve.values.flatten.first.spec.version
version.to_s.should == '1.5pre'
locked_deps = dependency_graph_from_array([Dependency.new('JSONKit', '= 1.4')])
resolver = Resolver.new(config.sandbox, podfile, locked_deps, config.sources_manager.all)
version = resolver.resolve.values.flatten.first.version
version = resolver.resolve.values.flatten.first.spec.version
version.to_s.should == '1.4'
end
......@@ -499,7 +579,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
platform :osx, '10.10'
pod(*requirement)
end
resolve.values.flatten.map(&:to_s).should.not.include ios_subspec
resolve.values.flatten.map(&:spec).map(&:to_s).should.not.include ios_subspec
end
it 'includes those for the requested platform' do
......@@ -507,7 +587,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
platform :ios, '7'
pod(*requirement)
end
resolve.values.flatten.map(&:to_s).should.include ios_subspec
resolve.values.flatten.map(&:spec).map(&:to_s).should.include ios_subspec
end
it 'includes those in the target for the requested platform only' do
......@@ -524,8 +604,8 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
resolved = resolve
ios_target = resolved.keys.find { |td| td.label == 'Pods-iOS' }
osx_target = resolved.keys.find { |td| td.label == 'Pods-OSX' }
resolved[ios_target].map(&:to_s).should.include ios_subspec
resolved[osx_target].map(&:to_s).should.not.include ios_subspec
resolved[ios_target].map(&:spec).map(&:to_s).should.include ios_subspec
resolved[osx_target].map(&:spec).map(&:to_s).should.not.include ios_subspec
end
it 'includes dependencies in the target for the requested platform only' do
......@@ -544,10 +624,10 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
resolved = resolve
ios_target = resolved.keys.find { |td| td.label == 'Pods-iOS' }
osx_target = resolved.keys.find { |td| td.label == 'Pods-OSX' }
resolved[ios_target].map(&:to_s).should.include ios_dependency
resolved[osx_target].map(&:to_s).should.not.include ios_dependency
resolved[ios_target].map(&:to_s).should.not.include osx_dependency
resolved[osx_target].map(&:to_s).should.include osx_dependency
resolved[ios_target].map(&:spec).map(&:to_s).should.include ios_dependency
resolved[osx_target].map(&:spec).map(&:to_s).should.not.include ios_dependency
resolved[ios_target].map(&:spec).map(&:to_s).should.not.include osx_dependency
resolved[osx_target].map(&:spec).map(&:to_s).should.include osx_dependency
end
end
end
......@@ -563,15 +643,15 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
file = fixture('spec-repos/test_repo/JSONKit/999.999.999/JSONKit.podspec')
sources = config.sources_manager.sources(%w(master test_repo))
resolver = Resolver.new(config.sandbox, podfile, empty_graph, sources)
spec = resolver.resolve.values.flatten.first
spec = resolver.resolve.values.flatten.first.spec
spec.version.to_s.should == '999.999.999'
spec.defined_in_file.should == file
sources = config.sources_manager.sources(%w(test_repo master))
resolver = Resolver.new(config.sandbox, podfile, empty_graph, sources)
spec = resolver.resolve.values.flatten.first
spec = resolver.resolve.values.flatten.first.spec
spec.version.to_s.should == '999.999.999'
resolver.resolve.values.flatten.first.defined_in_file.should == file
resolver.resolve.values.flatten.first.spec.defined_in_file.should == file
end
it 'warns and chooses the first source when multiple sources contain ' \
......@@ -582,15 +662,15 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
end
sources = config.sources_manager.sources(%w(master test_repo))
resolver = Resolver.new(config.sandbox, podfile, empty_graph, sources)
spec = resolver.resolve.values.flatten.first
spec = resolver.resolve.values.flatten.first.spec
spec.version.to_s.should == '1.4'
spec.defined_in_file.should == fixture('spec-repos/master/Specs/1/3/f/JSONKit/1.4/JSONKit.podspec.json')
sources = config.sources_manager.sources(%w(test_repo master))
resolver = Resolver.new(config.sandbox, podfile, empty_graph, sources)
spec = resolver.resolve.values.flatten.first
spec = resolver.resolve.values.flatten.first.spec
spec.version.to_s.should == '1.4'
resolver.resolve.values.flatten.first.defined_in_file.should == fixture('spec-repos/test_repo/JSONKit/1.4/JSONKit.podspec')
resolver.resolve.values.flatten.first.spec.defined_in_file.should == fixture('spec-repos/test_repo/JSONKit/1.4/JSONKit.podspec')
UI.warnings.should.match /multiple specifications/
end
......@@ -637,7 +717,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
sources = config.sources_manager.sources(%w(test_repo))
sources.map(&:url).should.not.include(master_repo_url)
resolver = Resolver.new(config.sandbox, podfile, empty_graph, sources)
spec = resolver.resolve.values.flatten.first
spec = resolver.resolve.values.flatten.first.spec
spec.version.to_s.should == '1.5pre'
spec.defined_in_file.should == fixture('spec-repos/master/Specs/1/3/f/JSONKit/1.5pre/JSONKit.podspec.json')
end
......@@ -678,7 +758,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
resolver = Resolver.new(config.sandbox, podfile, empty_graph, sources)
resolver.resolve
specs = resolver.resolve.values.flatten
specs = resolver.resolve.values.flatten.map(&:spec)
specs.map(&:name).should ==
%w(AFNetworking AFNetworking/NSURLConnection AFNetworking/NSURLSession AFNetworking/Reachability) +
......@@ -708,7 +788,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should == ['AFNetworking (1.0RC3)']
end
......@@ -719,7 +799,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should != ['AFNetworking (1.0RC3)']
specs.should == ['AFNetworking (1.3.4)']
end
......@@ -731,7 +811,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should != ['AFNetworking (1.0RC3)']
specs.should == ['AFNetworking (1.0)']
end
......@@ -743,7 +823,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should != ['AFNetworking (1.0RC3)']
specs.should == ['AFNetworking (0.10.1)']
end
......@@ -755,7 +835,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should != ['AFNetworking (1.0RC3)']
specs.should == ['AFNetworking (1.0)']
end
......@@ -767,7 +847,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should != ['AFNetworking (1.0RC3)']
specs.should == ['AFNetworking (1.2.1)']
end
......@@ -779,7 +859,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should != ['AFNetworking (1.0RC3)']
specs.should == ['AFNetworking (1.2.1)']
end
......@@ -791,7 +871,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should != ['AFNetworking (1.0RC3)']
specs.should == ['AFNetworking (1.2.1)']
end
......@@ -826,7 +906,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
pod 'PrereleaseMonkey', '1.0-beta1'
end
resolver = Resolver.new(config.sandbox, podfile, empty_graph, config.sources_manager.all)
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs = resolver.resolve.values.flatten.map(&:spec).map(&:to_s).sort
specs.should == ['PrereleaseMonkey (1.0-beta1)']
end
end
......
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