Commit b09aaebd authored by Eloy Duran's avatar Eloy Duran

Contain the cached sets in the Resolver itself.

parent 2e872f0f
...@@ -17,6 +17,11 @@ module Pod ...@@ -17,6 +17,11 @@ module Pod
config.project_root + 'Podfile.lock' config.project_root + 'Podfile.lock'
end end
def dependency_specifications
# Resolve *all* dependencies first.
@dependency_specifications ||= @resolver.resolve
end
def project def project
return @project if @project return @project if @project
@project = Pod::Project.for_platform(@podfile.platform) @project = Pod::Project.for_platform(@podfile.platform)
...@@ -126,28 +131,28 @@ module Pod ...@@ -126,28 +131,28 @@ module Pod
end end
end end
def dependent_specifications_for_each_target_definition def dependency_specifications_for_each_target_definition
@dependent_specifications_for_each_target_definition ||= @resolver.resolve @dependency_specifications_for_each_target_definition ||= @resolver.resolve
end end
def dependent_specifications def dependency_specifications
dependent_specifications_for_each_target_definition.values.flatten dependency_specifications_for_each_target_definition.values.flatten
end end
def activated_specifications def activated_specifications
dependent_specifications.reject do |spec| dependency_specifications.reject do |spec|
# Don't activate specs which are only wrappers of subspecs, or share # Don't activate specs which are only wrappers of subspecs, or share
# source with another pod but aren't activated themselves. # source with another pod but aren't activated themselves.
spec.wrapper? || @resolver.context.sets[spec.name].only_part_of_other_pod? spec.wrapper? || @resolver.cached_sets[spec.name].only_part_of_other_pod?
end end
end end
def activated_specifications_for_target(target_definition) def activated_specifications_for_target(target_definition)
dependent_specifications_for_each_target_definition[target_definition] dependency_specifications_for_each_target_definition[target_definition]
end end
def download_only_specifications def download_only_specifications
dependent_specifications - activated_specifications dependency_specifications - activated_specifications
end end
end end
end end
...@@ -9,6 +9,10 @@ module Pod ...@@ -9,6 +9,10 @@ module Pod
@podfile, @project, @target_definition = podfile, project, target_definition @podfile, @project, @target_definition = podfile, project, target_definition
end end
def dependency_specifications
@dependency_specifications ||= @resolver.resolve(@definition.dependencies)
end
def xcconfig def xcconfig
@xcconfig ||= Xcodeproj::Config.new({ @xcconfig ||= Xcodeproj::Config.new({
# In a workspace this is where the static library headers should be found. # In a workspace this is where the static library headers should be found.
......
module Pod module Pod
class Resolver class Resolver
# A Resolver::Context caches specification sets and is used by the resolver
# to ensure that extra dependencies on a set are added to the same instance.
#
# In addition, the context is later on used by Specification to lookup other
# specs, like the on they are a part of.
class Context
attr_reader :sources, :sets, :sandbox
def initialize(sandbox)
@sandbox = sandbox
@sets = {}
@sources = Source::Aggregate.new
end
def find_dependency_set(dependency)
@sets[dependency.name] ||= begin
if dependency.specification
Specification::Set::External.new(dependency.specification)
elsif external_source = dependency.external_source
specification = external_source.specification_from_sandbox(@sandbox)
Specification::Set::External.new(specification)
else
@sources.search(dependency)
end
end
end
end
attr_reader :podfile, :sandbox attr_reader :podfile, :sandbox
attr_accessor :context attr_accessor :cached_sets, :cached_sources
def initialize(podfile, sandbox) def initialize(podfile, sandbox)
@podfile = podfile @podfile = podfile
@sandbox = sandbox @sandbox = sandbox
@context = Context.new(@sandbox) @cached_sets = {}
@cached_sources = Source::Aggregate.new
end end
def resolve def resolve
...@@ -47,11 +20,11 @@ module Pod ...@@ -47,11 +20,11 @@ module Pod
result result
end end
# Specification doesn't need to know more about a context, so we assign # Specification doesn't need to know more about the context, so we assign
# the other specification, of which this pod is a part, to the spec. # the other specification, of which this pod is a part, to the spec.
@specs.values.sort_by(&:name).each do |spec| @specs.values.sort_by(&:name).each do |spec|
if spec.part_of_other_pod? if spec.part_of_other_pod?
spec.part_of_specification = @context.sets[spec.part_of.name].specification spec.part_of_specification = @cached_sets[spec.part_of.name].specification
end end
end end
...@@ -60,12 +33,24 @@ module Pod ...@@ -60,12 +33,24 @@ module Pod
private private
# this can be called with anything that has dependencies def find_cached_set(dependency)
# e.g. a Specification or a Podfile. @cached_sets[dependency.name] ||= begin
def find_dependency_sets(specification, dependencies = nil) if dependency.specification
(dependencies || specification.dependencies).each do |dependency| Specification::Set::External.new(dependency.specification)
set = @context.find_dependency_set(dependency) elsif external_source = dependency.external_source
set.required_by(specification) specification = external_source.specification_from_sandbox(@sandbox)
Specification::Set::External.new(specification)
else
@cached_sources.search(dependency)
end
end
end
def find_dependency_sets(dependent_specification, dependencies)
dependencies.each do |dependency|
set = find_cached_set(dependency)
set.required_by(dependent_specification)
# Ensure we don't resolve the same spec twice
unless @loaded_specs.include?(dependency.name) unless @loaded_specs.include?(dependency.name)
# Get a reference to the spec that’s actually being loaded. # Get a reference to the spec that’s actually being loaded.
# If it’s a subspec dependency, e.g. 'RestKit/Network', then # If it’s a subspec dependency, e.g. 'RestKit/Network', then
...@@ -81,7 +66,7 @@ module Pod ...@@ -81,7 +66,7 @@ module Pod
@specs[spec.name] = spec @specs[spec.name] = spec
# And recursively load the dependencies of the spec. # And recursively load the dependencies of the spec.
find_dependency_sets(spec) find_dependency_sets(spec, spec.dependencies)
end end
end end
end end
......
...@@ -298,12 +298,9 @@ else ...@@ -298,12 +298,9 @@ else
project = Xcodeproj::Project.new(config.project_pods_root + 'Pods.xcodeproj') project = Xcodeproj::Project.new(config.project_pods_root + 'Pods.xcodeproj')
project.targets.each do |target| project.targets.each do |target|
#target.source_build_phase phase = target.build_phases.find { |phase| phase.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase) }
phase = target.buildPhases.find { |phase| phase.is_a?(Xcodeproj::Project::PBXSourcesBuildPhase) }
files = phase.files.map(&:file).map(&:name) files = phase.files.map(&:file).map(&:name)
p target.productName case target.product_name
p files
case target.productName
when 'Pods' when 'Pods'
files.should.include "ASIHTTPRequest.m" files.should.include "ASIHTTPRequest.m"
files.should.not.include "SSZipArchive.m" files.should.not.include "SSZipArchive.m"
......
require File.expand_path('../../spec_helper', __FILE__) require File.expand_path('../../spec_helper', __FILE__)
class StubbedSet < Pod::Specification::Set
attr_accessor :stub_platform
def specification
spec = super
spec.platform = @stub_platform
spec
end
end
class StubbedContext < Pod::Resolver::Context
attr_accessor :stub_platform
def find_dependency_set(dependency)
set = StubbedSet.new(super.pod_dir)
set.stub_platform = @stub_platform
set
end
end
describe "Pod::Resolver" do describe "Pod::Resolver" do
before do before do
Pod::Spec::Set.reset! Pod::Spec::Set.reset!
...@@ -32,16 +12,16 @@ describe "Pod::Resolver" do ...@@ -32,16 +12,16 @@ describe "Pod::Resolver" do
dependency 'ASIWebPageRequest' dependency 'ASIWebPageRequest'
end end
config.rootspec = @podfile config.rootspec = @podfile
@resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
end end
after do after do
Pod::Config.instance = @config_before Pod::Config.instance = @config_before
end end
it "has a ResolveContext which holds global state, such as cached specification sets" do it "holds the context state, such as cached specification sets" do
resolver = Pod::Resolver.new(@podfile, stub('sandbox')) @resolver.resolve
resolver.resolve @resolver.cached_sets.values.sort_by(&:name).should == [
resolver.context.sets.values.sort_by(&:name).should == [
Pod::Spec::Set.new(config.repos_dir + 'master/ASIHTTPRequest'), Pod::Spec::Set.new(config.repos_dir + 'master/ASIHTTPRequest'),
Pod::Spec::Set.new(config.repos_dir + 'master/ASIWebPageRequest'), Pod::Spec::Set.new(config.repos_dir + 'master/ASIWebPageRequest'),
Pod::Spec::Set.new(config.repos_dir + 'master/Reachability'), Pod::Spec::Set.new(config.repos_dir + 'master/Reachability'),
...@@ -49,35 +29,36 @@ describe "Pod::Resolver" do ...@@ -49,35 +29,36 @@ describe "Pod::Resolver" do
end end
it "returns all specs needed for the dependency" do it "returns all specs needed for the dependency" do
specs = Pod::Resolver.new(@podfile, stub('sandbox')).resolve.values.flatten specs = @resolver.resolve.values.flatten
specs.map(&:class).uniq.should == [Pod::Specification] specs.map(&:class).uniq.should == [Pod::Specification]
specs.map(&:name).sort.should == %w{ ASIHTTPRequest ASIWebPageRequest Reachability } specs.map(&:name).sort.should == %w{ ASIHTTPRequest ASIWebPageRequest Reachability }
end end
it "does not raise if all dependencies match the platform of the root spec (Podfile)" do it "does not raise if all dependencies match the platform of the root spec (Podfile)" do
resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
@podfile.platform :ios @podfile.platform :ios
lambda { resolver.resolve }.should.not.raise lambda { @resolver.resolve }.should.not.raise
@podfile.platform :osx @podfile.platform :osx
lambda { resolver.resolve }.should.not.raise lambda { @resolver.resolve }.should.not.raise
end end
it "raises once any of the dependencies does not match the platform of the root spec (Podfile)" do it "raises once any of the dependencies does not match the platform of the root spec (Podfile)" do
resolver = Pod::Resolver.new(config.rootspec, stub('sandbox')) set = Pod::Spec::Set.new(config.repos_dir + 'master/ASIHTTPRequest')
context = resolver.context = StubbedContext.new(resolver.sandbox) @resolver.cached_sets['ASIHTTPRequest'] = set
def set.stub_platform=(platform); @stubbed_platform = platform; end
def set.specification; spec = super; spec.platform = @stubbed_platform; spec; end
@podfile.platform :ios @podfile.platform :ios
context.stub_platform = :ios set.stub_platform = :ios
lambda { resolver.resolve }.should.not.raise lambda { @resolver.resolve }.should.not.raise
context.stub_platform = :osx set.stub_platform = :osx
lambda { resolver.resolve }.should.raise Pod::Informative lambda { @resolver.resolve }.should.raise Pod::Informative
@podfile.platform :osx @podfile.platform :osx
context.stub_platform = :osx set.stub_platform = :osx
lambda { resolver.resolve }.should.not.raise lambda { @resolver.resolve }.should.not.raise
context.stub_platform = :ios set.stub_platform = :ios
lambda { resolver.resolve }.should.raise Pod::Informative lambda { @resolver.resolve }.should.raise Pod::Informative
end end
it "resolves subspecs" do it "resolves subspecs" do
......
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