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)
......
......@@ -76,10 +76,14 @@ module Pod
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
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
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]
end
it 'includes pod target when declared in the pod target definition but has a test dependency on itself' 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 => [], :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 == [pod_target]
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 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 => [], :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
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 not within target definition' 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 => [])
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