Commit ea9b1810 authored by Fabio Pelosin's avatar Fabio Pelosin

WIP Specification refactor.

parent 81d3550d
...@@ -23,7 +23,7 @@ module Pod ...@@ -23,7 +23,7 @@ module Pod
# specification information # specification information
def spec def spec
@spec ||= @set.specification.part_of_other_pod? ? @set.specification.part_of_specification : @set.specification @set.specification
end end
def authors def authors
......
...@@ -12,7 +12,6 @@ module Pod ...@@ -12,7 +12,6 @@ module Pod
def self.for_pod(pod) def self.for_pod(pod)
spec = pod.specification spec = pod.specification
spec = spec.part_of_specification if spec.part_of_other_pod?
for_target(pod.root, spec.source.dup) for_target(pod.root, spec.source.dup)
end end
......
...@@ -145,14 +145,6 @@ module Pod ...@@ -145,14 +145,6 @@ module Pod
end end
end end
unless download_only_specifications.empty?
file.puts
file.puts "DOWNLOAD_ONLY:"
download_only_specifications.map(&:to_s).sort.each do |name|
file.puts " - #{name}"
end
end
file.puts file.puts
file.puts "DEPENDENCIES:" file.puts "DEPENDENCIES:"
@podfile.dependencies.map(&:to_s).sort.each do |dep| @podfile.dependencies.map(&:to_s).sort.each do |dep|
...@@ -193,7 +185,7 @@ module Pod ...@@ -193,7 +185,7 @@ module Pod
result = {} result = {}
specs_by_target.each do |target_definition, specs| specs_by_target.each do |target_definition, specs|
result[target_definition] = specs.map do |spec| result[target_definition] = specs.map do |spec|
LocalPod.new(spec, @sandbox, target_definition.platform) if activated_spec?(spec) LocalPod.new(spec, @sandbox, target_definition.platform)
end.compact end.compact
end end
result result
...@@ -203,24 +195,15 @@ module Pod ...@@ -203,24 +195,15 @@ module Pod
# dependency that is not a download-only # dependency that is not a download-only
# one. # one.
def activated_specifications def activated_specifications
dependency_specifications.select { |spec| activated_spec?(spec) } dependency_specifications
end end
def activated_specifications_for_target(target_definition) def activated_specifications_for_target(target_definition)
specs_by_target[target_definition].select { |spec| activated_spec?(spec) } specs_by_target[target_definition]
end
def download_only_specifications
dependency_specifications - activated_specifications
end end
private private
def activated_spec?(spec)
# Don't activate specs which are only wrappers of subspecs, or share
# source with another pod but aren't activated themselves.
!spec.wrapper? && !@resolver.cached_sets[spec.name].only_part_of_other_pod?
end
def print_title(title, only_verbose = true) def print_title(title, only_verbose = true)
if config.verbose? if config.verbose?
......
...@@ -27,13 +27,7 @@ module Pod ...@@ -27,13 +27,7 @@ module Pod
targets_and_specs[target_definition] = @specs.values_at(*@loaded_specs).sort_by(&:name) targets_and_specs[target_definition] = @specs.values_at(*@loaded_specs).sort_by(&:name)
end end
# Specification doesn't need to know more about the context, so we assign @specs.values.sort_by(&:name)
# the other specification, of which this pod is a part, to the spec.
@specs.values.sort_by(&:name).each do |spec|
if spec.part_of_other_pod?
spec.part_of_specification = @cached_sets[spec.part_of.name].specification
end
end
targets_and_specs targets_and_specs
end end
...@@ -41,7 +35,8 @@ module Pod ...@@ -41,7 +35,8 @@ module Pod
private private
def find_cached_set(dependency, platform) def find_cached_set(dependency, platform)
@cached_sets[dependency.name] ||= begin set_name = dependency.name.split('/').first
@cached_sets[set_name] ||= begin
if dependency.specification if dependency.specification
Specification::Set::External.new(dependency.specification) Specification::Set::External.new(dependency.specification)
elsif external_source = dependency.external_source elsif external_source = dependency.external_source
...@@ -71,6 +66,7 @@ module Pod ...@@ -71,6 +66,7 @@ module Pod
if dependency.subspec_dependency? if dependency.subspec_dependency?
spec = spec.subspec_by_name(dependency.name) spec = spec.subspec_by_name(dependency.name)
end end
@loaded_specs << spec.name @loaded_specs << spec.name
@specs[spec.name] = spec @specs[spec.name] = spec
...@@ -84,8 +80,8 @@ module Pod ...@@ -84,8 +80,8 @@ module Pod
end end
def validate_platform!(spec, target) def validate_platform!(spec, target)
unless spec.platforms.any? { |platform| target.platform.support?(platform) } unless spec.available_platforms.any? { |platform| target.platform.support?(platform) }
raise Informative, "[!] The platform of the target `#{target.name}' (#{target.platform}) is not compatible with `#{spec}' which has a minimun requirement of #{spec.platforms.join(' - ')}.".red raise Informative, "[!] The platform of the target `#{target.name}' (#{target.platform}) is not compatible with `#{spec}' which has a minimun requirement of #{spec.available_platforms.join(' - ')}.".red
end end
end end
end end
......
...@@ -13,18 +13,21 @@ module Pod ...@@ -13,18 +13,21 @@ module Pod
autoload :Statistics, 'cocoapods/specification/statistics' autoload :Statistics, 'cocoapods/specification/statistics'
# The file is expected to define and return a Pods::Specification. # The file is expected to define and return a Pods::Specification.
def self.from_file(path) # If name is equals to nil it returns the top level Specification,
# otherwise it returned the specification with the name that matches
def self.from_file(path, subspec_name = nil)
unless path.exist? unless path.exist?
raise Informative, "No podspec exists at path `#{path}'." raise Informative, "No podspec exists at path `#{path}'."
end end
spec = ::Pod._eval_podspec(path) spec = ::Pod._eval_podspec(path)
spec.defined_in_file = path spec.defined_in_file = path
spec spec.subspec_by_name(subspec_name)
end end
attr_accessor :defined_in_file attr_accessor :defined_in_file, :parent
def initialize def initialize(parent = nil, name = nil)
@parent, @name = parent, name if parent
post_initialize post_initialize
yield self if block_given? yield self if block_given?
end end
...@@ -33,121 +36,110 @@ module Pod ...@@ -33,121 +36,110 @@ module Pod
def post_initialize def post_initialize
@define_for_platforms = [:osx, :ios] @define_for_platforms = [:osx, :ios]
@clean_paths, @subspecs = [], [] @clean_paths, @subspecs = [], []
@dependencies, @source_files, @resources = { :ios => [], :osx => [] }, { :ios => [], :osx => [] }, { :ios => [], :osx => [] }
@deployment_target = {} @deployment_target = {}
@platform = Platform.new(nil) @platform = Platform.new(nil)
@xcconfig = { :ios => Xcodeproj::Config.new, :osx => Xcodeproj::Config.new }
@compiler_flags = { :ios => '', :osx => '' }
end
# Attributes **without** multiple platform support initialized_multiplatform_attributes
attr_accessor :name # deprecated attributes
attr_accessor :homepage @source = {:git => ''}
attr_accessor :description
attr_accessor :source
attr_accessor :documentation
attr_reader :version
def version=(version)
@version = Version.new(version)
end end
def authors=(*names_and_email_addresses) # Deprecated attributes
list = names_and_email_addresses.flatten # TODO: remove once master repo and fixtures are updated
unless list.first.is_a?(Hash) def part_of_dependency=(value)
authors = list.last.is_a?(Hash) ? list.pop : {} puts "[!] `part_of_dependency' is deprecated in #{name}"
list.each { |name| authors[name] = nil }
end end
@authors = authors || list.first
end
alias_method :author=, :authors=
attr_reader :authors
def summary=(summary) def part_of=(value)
@summary = summary puts "[!] `part_of_dependency' is deprecated in #{name}"
end end
attr_reader :summary
def license=(license) # Normal attributes
if license.kind_of?(Array)
@license = license[1].merge({:type => license[0]})
elsif license.kind_of?(String)
@license = {:type => license}
else
@license = license
end
end
attr_reader :license
def description def name
@description || summary @parent ? "#{@parent.name}/#{@name}" : @name
end end
def part_of=(*name_and_version_requirements) attr_writer :name
self.part_of_dependency = *name_and_version_requirements
@part_of.only_part_of_other_pod = true
end
attr_reader :part_of
def part_of_dependency=(*name_and_version_requirements) def summary
@part_of = dependency(*name_and_version_requirements) @summary || ( @parent.summary if @parent )
end end
def prefix_header_file=(file) attr_writer :summary
@prefix_header_file = Pathname.new(file)
def available_platforms
@platform.nil? ? @define_for_platforms.map { |platform| Platform.new(platform, @deployment_target[platform]) } : [ platform ]
end end
attr_reader :prefix_header_file
attr_accessor :prefix_header_contents attr_accessor :main_subspec
def clean_paths=(patterns) ### Top level attributes. These attributes represent the unique features of pod and can't be specified by subspecs.
@clean_paths = pattern_list(patterns)
end
attr_reader :clean_paths
alias_method :clean_path=, :clean_paths=
def header_dir=(dir) # Attributes **without** multiple platform support
@header_dir = Pathname.new(dir)
# Creates a top level attribute reader.
def self.top_attr_reader(attr, block = nil)
define_method(attr) do
ivar = instance_variable_get("@#{attr}")
@parent ? top_level_parent.send(attr) : ( block ? block.call(self, ivar) : ivar )
end end
def header_dir
@header_dir || pod_destroot_name
end end
def platform=(platform) # Creates a top level attribute writer. A lambda can be passed to initialize the value.
@platform = Platform.new(*platform) def self.top_attr_writer(attr, block = nil)
raise Informative "Can't set #{attr} for subspecs" if @parent
define_method("#{attr}=") do |value|
instance_variable_set("@#{attr}", block ? block.call(value) : value);
end end
attr_reader :platform
def platforms
@platform.nil? ? @define_for_platforms.map { |platfrom| Platform.new(platfrom, @deployment_target[platfrom]) } : [platform]
end end
def requires_arc=(requires_arc) # Creates a top level attribute accessor. A lambda can be passed to initialize the value in the attribute writer.
self.compiler_flags = '-fobjc-arc' if requires_arc def self.top_attr_accessor(attr, block = nil)
@requires_arc = requires_arc top_attr_reader attr
top_attr_writer attr, block
end end
attr_reader :requires_arc
def subspec(name, &block) top_attr_accessor :homepage
subspec = Subspec.new(self, name, &block) top_attr_accessor :source
@subspecs << subspec top_attr_accessor :documentation
subspec top_attr_accessor :requires_arc
end top_attr_accessor :license, lambda { |l| ( l.kind_of? String ) ? { :type => l } : l }
attr_reader :subspecs top_attr_accessor :version, lambda { |v| Version.new(v) }
top_attr_accessor :platform, lambda { |p| Platform.new(*p) }
top_attr_accessor :readme_file, lambda { |file| Pathname.new(file) }
top_attr_accessor :authors, lambda { |a| parse_authors(a) }
alias_method :author=, :authors=
def recursive_subspecs top_attr_reader :description, lambda { |instance, ivar| ivar || instance.summary }
unless @recursive_subspecs top_attr_writer :description
mapper = lambda do |spec|
spec.subspecs.map do |subspec| #TODO: are those top level?
[subspec, *mapper.call(subspec)] top_attr_accessor :prefix_header_contents
end.flatten top_attr_accessor :prefix_header_file, lambda { |file| Pathname.new(file) }
end top_attr_reader :header_dir, lambda {|instance, ivar| ivar || instance.pod_destroot_name }
@recursive_subspecs = mapper.call self top_attr_writer :header_dir, lambda {|dir| Pathname.new(dir) }
#TODO: deprecate and clean all unused files
top_attr_accessor :clean_paths, lambda { |patterns| pattern_list(patterns) }
alias_method :clean_path=, :clean_paths=
def self.parse_authors(*names_and_email_addresses)
list = names_and_email_addresses.flatten
unless list.first.is_a?(Hash)
authors = list.last.is_a?(Hash) ? list.pop : {}
list.each { |name| authors[name] = nil }
end end
@recursive_subspecs authors || list.first
end end
# # TODO: move logic to compiler_flags
# def requires_arc=(requires_arc)
# self.compiler_flags = '-fobjc-arc' if requires_arc
# @requires_arc = requires_arc
# end
### Attributes **with** multiple platform support ### Attributes **with** multiple platform support
class PlatformProxy class PlatformProxy
...@@ -172,51 +164,86 @@ module Pod ...@@ -172,51 +164,86 @@ module Pod
PlatformProxy.new(self, :osx) PlatformProxy.new(self, :osx)
end end
def source_files=(patterns) # It returns the value of the attribute for the current platform. In this way clients do not need to be aware of wich
@define_for_platforms.each do |platform| # attributes are multiplatform
@source_files[platform] = pattern_list(patterns) def self.platform_attr_reader(attr)
end # TODO: implement
attr_reader attr
end end
attr_reader :source_files
def deployment_target=(version) # It returns the value of a pod merged with upstream. The optional lambda can specify how to merge the values
raise Informative, "The deployment target must be defined per platform like s.ios.deployment_target = '5.0'" unless @define_for_platforms.count == 1 def self.pltf_chained_attr_reader(attr, merge_lambda = nil)
@deployment_target[@define_for_platforms.first] = version # TODO: chain the value with the upstream
attr_reader attr
end end
def resources=(patterns) def self.platform_attr_writer(attr, block = nil)
define_method("#{attr}=") do |value|
current = instance_variable_get("@#{attr}")
@define_for_platforms.each do |platform| @define_for_platforms.each do |platform|
@resources[platform] = pattern_list(patterns) block ? current[platform] = block.call(value, current[platform]) : current[platform] = value
end
end end
end end
attr_reader :resources
alias_method :resource=, :resources=
def xcconfig=(build_settings) def initialized_multiplatform_attributes
@define_for_platforms.each do |platform| %w[ source_files resources frameworks libraries dependencies compiler_flags].each do |attr|
@xcconfig[platform].merge!(build_settings) instance_variable_set( "@#{attr}", { :ios => [], :osx => [] } )
end end
@dependencies = { :ios => [], :osx => [] }
@xcconfig = { :ios => Xcodeproj::Config.new, :osx => Xcodeproj::Config.new }
end end
attr_reader :xcconfig
def frameworks=(*frameworks) pltf_chained_attr_reader :source_files
frameworks.unshift('') platform_attr_writer :source_files, lambda {|value, current| pattern_list(value) }
self.xcconfig = { 'OTHER_LDFLAGS' => frameworks.join(' -framework ').strip }
end pltf_chained_attr_reader :resources
platform_attr_writer :resources, lambda {|value, current| pattern_list(value) }
alias_method :resource=, :resources=
# frameworks are chained by the xcofing attr_reader
platform_attr_reader :frameworks
platform_attr_writer :frameworks, lambda {|value, current| current << value }
alias_method :framework=, :frameworks= alias_method :framework=, :frameworks=
def libraries=(*libraries) # libraries are chained by the xcofing attr_reader
libraries.unshift('') platform_attr_reader :libraries
self.xcconfig = { 'OTHER_LDFLAGS' => libraries.join(' -l').strip } platform_attr_writer :libraries, lambda {|value, current| current << value }
end
alias_method :library=, :libraries= alias_method :library=, :libraries=
attr_reader :compiler_flags def xcconfig
def compiler_flags=(flags) result = {}
@define_for_platforms.each do |platform| @define_for_platforms.each do |platform|
@compiler_flags[platform] << ' ' << flags if @parent
chained = @xcconfig[platform].dup.unshift @parent.xcconfig[platform]
else
chained = @xcconfig[platform].dup
end end
chained.merge!({ 'OTHER_LDFLAGS' => '-l' << libraries[platform].join(' -l').strip }) unless libraries[platform].empty?
chained.merge!({ 'OTHER_LDFLAGS' => '-framework ' << frameworks[platform].join(' -framework ').strip }) unless frameworks[platform].empty?
result[platform] = chained
end end
result
end
platform_attr_writer :xcconfig, lambda {|value, current| current.tap { |c| c.merge!(value) } }
def compiler_flags
result = {}
@define_for_platforms.each do |platform|
if @parent
chained = @compiler_flags[platform].dup.unshift @parent.compiler_flags[platform]
else
chained = @compiler_flags[platform].dup
chained.unshift '-fobjc-arc' if @requires_arc
chained.unshift ''
end
result[platform] = chained.join(' ')
end
result
end
platform_attr_writer :compiler_flags, lambda {|value, current| current << value }
def dependency(*name_and_version_requirements) def dependency(*name_and_version_requirements)
name, *version_requirements = name_and_version_requirements.flatten name, *version_requirements = name_and_version_requirements.flatten
...@@ -226,7 +253,20 @@ module Pod ...@@ -226,7 +253,20 @@ module Pod
end end
dep dep
end end
attr_reader :dependencies
def dependencies
result = {}
@define_for_platforms.each do |platform|
inherited_subspecs = main_subspec ? [Dependency.new("#{name}/#{main_subspec}", version)] : subspecs.map {|s| Dependency.new(s.name, version) }
result[platform] = @dependencies[platform] + inherited_subspecs
end
result
end
def deployment_target=(version)
raise Informative, "The deployment target must be defined per platform like s.ios.deployment_target = '5.0'" unless @define_for_platforms.count == 1
@deployment_target[@define_for_platforms.first] = version
end
### Not attributes ### Not attributes
...@@ -242,30 +282,31 @@ module Pod ...@@ -242,30 +282,31 @@ module Pod
include Config::Mixin include Config::Mixin
def local? def top_level_parent
!source.nil? && !source[:local].nil? @parent ? @parent.top_level_parent : self
end end
def local_path def subspec(name, &block)
Pathname.new(File.expand_path(source[:local])) subspec = Specification.new(self, name, &block)
@subspecs << subspec
subspec
end end
attr_reader :subspecs
# This is assigned the other spec, of which this pod's source is a part, by def recursive_subspecs
# a Resolver. unless @recursive_subspecs
attr_accessor :part_of_specification mapper = lambda do |spec|
def part_of_specification spec.subspecs.map do |subspec|
@part_of_specification || begin [subspec, *mapper.call(subspec)]
set = Source.search(@part_of) end.flatten
set.required_by(self)
set.specification
end end
@recursive_subspecs = mapper.call self
end end
@recursive_subspecs
def wrapper?
source_files.values.all?(&:empty?) && !subspecs.empty?
end end
def subspec_by_name(name) def subspec_by_name(name)
return self if name.nil? || name == self.name
# Remove this spec's name from the beginning of the name we’re looking for # Remove this spec's name from the beginning of the name we’re looking for
# and take the first component from the remainder, which is the spec we need # and take the first component from the remainder, which is the spec we need
# to find now. # to find now.
...@@ -278,28 +319,30 @@ module Pod ...@@ -278,28 +319,30 @@ module Pod
remainder.empty? ? subspec : subspec.subspec_by_name(name) remainder.empty? ? subspec : subspec.subspec_by_name(name)
end end
def ==(other) # Returns if the specification is supported in a given platform
object_id == other.object_id || def supports_platform?(plaform)
(self.class === other && available_platforms.any? { |p| platform.supports? p }
name && name == other.name &&
version && version == other.version)
end end
def dependency_by_top_level_spec_name(name) # Defines the active platform for comsumption of the specification.
@dependencies.each do |_, platform_deps| def activate_for_platform(platform)
platform_deps.each do |dep| raise "[!] #{name} does not support platform".red unless supports_platform?(plaform)
return dep if dep.top_level_spec_name == name @active_platform = platform
end end
def local?
!source.nil? && !source[:local].nil?
end end
def local_path
Pathname.new(File.expand_path(source[:local]))
end end
def pod_destroot def pod_destroot
if part_of_other_pod? if local?
part_of_specification.pod_destroot
elsif local?
local_path local_path
else else
config.project_pods_root + @name config.project_pods_root + top_level_parent.name
end end
end end
...@@ -309,15 +352,7 @@ module Pod ...@@ -309,15 +352,7 @@ module Pod
end end
end end
def part_of_other_pod? def self.pattern_list(patterns)
!part_of.nil?
end
def podfile?
false
end
def pattern_list(patterns)
if patterns.is_a?(Array) && (!defined?(Rake) || !patterns.is_a?(Rake::FileList)) if patterns.is_a?(Array) && (!defined?(Rake) || !patterns.is_a?(Rake::FileList))
patterns patterns
else else
...@@ -332,15 +367,7 @@ module Pod ...@@ -332,15 +367,7 @@ module Pod
# namespacing. You can, however, override this method in the podspec, or # namespacing. You can, however, override this method in the podspec, or
# copy_header_mappings for full control. # copy_header_mappings for full control.
def copy_header_mapping(from) def copy_header_mapping(from)
from.basename @parent ? top_level_parent.copy_header_mapping(from) : from.basename
end
def to_s
"#{name} (#{version})"
end
def inspect
"#<#{self.class.name} for #{to_s}>"
end end
# This is a convenience method which gets called after all pods have been # This is a convenience method which gets called after all pods have been
...@@ -359,53 +386,32 @@ module Pod ...@@ -359,53 +386,32 @@ module Pod
def post_install(target) def post_install(target)
end end
class Subspec < Specification def podfile?
attr_reader :parent false
def initialize(parent, name)
@parent, @name = parent, name
# TODO a MacRuby bug, the correct super impl `initialize' is not called consistently
#super(&block)
post_initialize
# A subspec is _always_ part of the source of its top level spec.
self.part_of = top_level_parent.name, version
# A subspec has a dependency on the parent if the parent is a subspec too.
dependency(@parent.name, version) if @parent.is_a?(Subspec)
yield self if block_given?
end
undef_method :name=, :version=, :source=
def top_level_parent
top_level_parent = @parent
top_level_parent = top_level_parent.parent while top_level_parent.is_a?(Subspec)
top_level_parent
end end
def name def to_s
"#{@parent.name}/#{@name}" "#{name} (#{version})"
end end
# TODO manually forwarding the attributes that we have so far needed to forward, def inspect
# but need to think if there's a better way to do this. "#<#{self.class.name} for #{to_s}>"
def summary
@summary ? @summary : top_level_parent.summary
end end
# Override the getters to always return the value of the top level parent spec. def dependency_by_top_level_spec_name(name)
[:version, :summary, :platform, :license, :authors, :requires_arc, :compiler_flags, :documentation, :homepage].each do |attr| dependencies.each do |_, platform_deps|
define_method(attr) { top_level_parent.send(attr) } platform_deps.each do |dep|
return dep if dep.top_level_spec_name == name
end end
def copy_header_mapping(from)
top_level_parent.copy_header_mapping(from)
end end
end end
def ==(other)
object_id == other.object_id ||
(self.class === other &&
name && name == other.name &&
version && version == other.version)
end
end end
Spec = Specification Spec = Specification
end end
...@@ -27,10 +27,6 @@ module Pod ...@@ -27,10 +27,6 @@ module Pod
end end
end end
def only_part_of_other_pod?
@required_by.all? { |spec| spec.dependency_by_top_level_spec_name(name).only_part_of_other_pod? }
end
def name def name
@pod_dir.basename.to_s @pod_dir.basename.to_s
end end
...@@ -88,10 +84,6 @@ module Pod ...@@ -88,10 +84,6 @@ module Pod
@specification = before @specification = before
end end
def only_part_of_other_pod?
false
end
def specification_path def specification_path
raise "specification_path" raise "specification_path"
end end
......
...@@ -81,7 +81,7 @@ module Pod ...@@ -81,7 +81,7 @@ module Pod
def github_stats_if_needed(set) def github_stats_if_needed(set)
return if get_value(set, :gh_date) && get_value(set, :gh_date) > Time.now - cache_expiration return if get_value(set, :gh_date) && get_value(set, :gh_date) > Time.now - cache_expiration
spec = set.specification.part_of_other_pod? ? set.specification.part_of_specification : set.specification spec = set.specification
url = spec.source.reject {|k,_| k == :commit || k == :tag }.values.first url = spec.source.reject {|k,_| k == :commit || k == :tag }.values.first
repo_id = url[/github.com\/([^\/\.]*\/[^\/\.]*)\.*/, 1] repo_id = url[/github.com\/([^\/\.]*\/[^\/\.]*)\.*/, 1]
return unless repo_id return unless repo_id
......
...@@ -9,7 +9,6 @@ module SpecHelper ...@@ -9,7 +9,6 @@ module SpecHelper
def specs_by_target def specs_by_target
@specs_by_target ||= super.tap do |hash| @specs_by_target ||= super.tap do |hash|
hash.values.flatten.each do |spec| hash.values.flatten.each do |spec|
unless spec.part_of_other_pod?
source = spec.source source = spec.source
source[:git] = SpecHelper.fixture("integration/#{spec.name}").to_s source[:git] = SpecHelper.fixture("integration/#{spec.name}").to_s
spec.source = source spec.source = source
...@@ -17,7 +16,6 @@ module SpecHelper ...@@ -17,7 +16,6 @@ module SpecHelper
end end
end end
end end
end
end end
unless SpecHelper.fixture('integration/ASIHTTPRequest/Classes').exist? unless SpecHelper.fixture('integration/ASIHTTPRequest/Classes').exist?
...@@ -113,8 +111,8 @@ else ...@@ -113,8 +111,8 @@ else
installer.install! installer.install!
YAML.load(installer.lock_file.read).should == { YAML.load(installer.lock_file.read).should == {
'PODS' => [{ 'Reachability (1.2.3)' => ["ASIHTTPRequest (>= 1.8)"] }], 'PODS' => [ 'Reachability (1.2.3)' ],
'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"], # 'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"],
'DEPENDENCIES' => ["Reachability (from `#{url}')"] 'DEPENDENCIES' => ["Reachability (from `#{url}')"]
} }
end end
...@@ -254,7 +252,7 @@ else ...@@ -254,7 +252,7 @@ else
self.platform platform self.platform platform
xcodeproj 'dummy' xcodeproj 'dummy'
dependency 'Reachability', '> 2.0.5' if platform == :ios dependency 'Reachability', '> 2.0.5' if platform == :ios
dependency 'ASIWebPageRequest', '>= 1.8.1' # dependency 'ASIWebPageRequest', '>= 1.8.1'
dependency 'JSONKit', '>= 1.0' dependency 'JSONKit', '>= 1.0'
dependency 'SSZipArchive', '< 2' dependency 'SSZipArchive', '< 2'
end end
...@@ -264,14 +262,14 @@ else ...@@ -264,14 +262,14 @@ else
lock_file_contents = { lock_file_contents = {
'PODS' => [ 'PODS' => [
{ 'ASIHTTPRequest (1.8.1)' => ["Reachability"] }, # { 'ASIHTTPRequest (1.8.1)' => ["Reachability"] },
{ 'ASIWebPageRequest (1.8.1)' => ["ASIHTTPRequest (= 1.8.1)"] }, # { 'ASIWebPageRequest (1.8.1)' => ["ASIHTTPRequest (= 1.8.1)"] },
'JSONKit (1.5pre)', 'JSONKit (1.5pre)',
'Reachability (3.0.0)', 'Reachability (3.0.0)',
'SSZipArchive (0.1.2)', 'SSZipArchive (0.1.2)',
], ],
'DEPENDENCIES' => [ 'DEPENDENCIES' => [
"ASIWebPageRequest (>= 1.8.1)", # "ASIWebPageRequest (>= 1.8.1)",
"JSONKit (>= 1.0)", "JSONKit (>= 1.0)",
"Reachability (> 2.0.5)", "Reachability (> 2.0.5)",
"SSZipArchive (< 2)", "SSZipArchive (< 2)",
...@@ -279,9 +277,9 @@ else ...@@ -279,9 +277,9 @@ else
} }
unless platform == :ios unless platform == :ios
# No Reachability is required by ASIHTTPRequest on OSX # No Reachability is required by ASIHTTPRequest on OSX
lock_file_contents['DEPENDENCIES'].delete_at(2) lock_file_contents['DEPENDENCIES'].delete_at(1)
lock_file_contents['PODS'].delete_at(3) lock_file_contents['PODS'].delete_at(1)
lock_file_contents['PODS'][0] = 'ASIHTTPRequest (1.8.1)' # lock_file_contents['PODS'][0] = 'ASIHTTPRequest (1.8.1)'
end end
YAML.load(installer.lock_file.read).should == lock_file_contents YAML.load(installer.lock_file.read).should == lock_file_contents
...@@ -305,8 +303,9 @@ else ...@@ -305,8 +303,9 @@ else
installer.install! installer.install!
YAML.load(installer.lock_file.read).should == { YAML.load(installer.lock_file.read).should == {
'PODS' => [{ 'Reachability (2.0.4)' => ["ASIHTTPRequest (>= 1.8)"] }], # 'PODS' => [{ 'Reachability (2.0.4)' => ["ASIHTTPRequest (>= 1.8)"] }],
'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"], 'PODS' => [ 'Reachability (2.0.4)' ],
# 'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"],
'DEPENDENCIES' => ["Reachability (= 2.0.4)"] 'DEPENDENCIES' => ["Reachability (= 2.0.4)"]
} }
end end
......
...@@ -8,7 +8,8 @@ describe "Pod::Resolver" do ...@@ -8,7 +8,8 @@ describe "Pod::Resolver" do
config.repos_dir = fixture('spec-repos') config.repos_dir = fixture('spec-repos')
@podfile = Pod::Podfile.new do @podfile = Pod::Podfile.new do
platform :ios platform :ios
dependency 'ASIWebPageRequest' dependency 'BlocksKit'
# dependency 'ASIWebPageRequest'
end end
@resolver = Pod::Resolver.new(@podfile, stub('sandbox')) @resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
end end
...@@ -20,16 +21,15 @@ describe "Pod::Resolver" do ...@@ -20,16 +21,15 @@ describe "Pod::Resolver" do
it "holds the context state, such as cached specification sets" do it "holds the context state, such as cached specification sets" do
@resolver.resolve @resolver.resolve
@resolver.cached_sets.values.sort_by(&:name).should == [ @resolver.cached_sets.values.sort_by(&:name).should == [
Pod::Spec::Set.new(config.repos_dir + 'master/ASIHTTPRequest'), Pod::Spec::Set.new(config.repos_dir + 'master/A2DynamicDelegate'),
Pod::Spec::Set.new(config.repos_dir + 'master/ASIWebPageRequest'), Pod::Spec::Set.new(config.repos_dir + 'master/BlocksKit'),
Pod::Spec::Set.new(config.repos_dir + 'master/Reachability'),
].sort_by(&:name) ].sort_by(&:name)
end end
it "returns all specs needed for the dependency" do it "returns all specs needed for the dependency" do
specs = @resolver.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{ A2DynamicDelegate BlocksKit }
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
...@@ -40,8 +40,8 @@ describe "Pod::Resolver" do ...@@ -40,8 +40,8 @@ describe "Pod::Resolver" do
end end
it "raises once any of the dependencies does not match the platform of its podfile target" do it "raises once any of the dependencies does not match the platform of its podfile target" do
set = Pod::Spec::Set.new(config.repos_dir + 'master/ASIHTTPRequest') set = Pod::Spec::Set.new(config.repos_dir + 'master/BlocksKit')
@resolver.cached_sets['ASIHTTPRequest'] = set @resolver.cached_sets['BlocksKit'] = set
def set.stub_platform=(platform); @stubbed_platform = platform; end def set.stub_platform=(platform); @stubbed_platform = platform; end
def set.specification; spec = super; spec.platform = @stubbed_platform; spec; end def set.specification; spec = super; spec.platform = @stubbed_platform; spec; end
...@@ -60,14 +60,14 @@ describe "Pod::Resolver" do ...@@ -60,14 +60,14 @@ describe "Pod::Resolver" do
end end
it "raises once any of the dependencies does not have a deployment_target compatible with its podfile target" do it "raises once any of the dependencies does not have a deployment_target compatible with its podfile target" do
set = Pod::Spec::Set.new(config.repos_dir + 'master/ASIHTTPRequest') set = Pod::Spec::Set.new(config.repos_dir + 'master/BlocksKit')
@resolver.cached_sets['ASIHTTPRequest'] = set @resolver.cached_sets['BlocksKit'] = set
@podfile.platform :ios, "4.0" @podfile.platform :ios, "4.0"
Pod::Specification.any_instance.stubs(:platforms).returns([ Pod::Platform.new(:ios, '4.0'), Pod::Platform.new(:osx, '10.7') ]) Pod::Specification.any_instance.stubs(:available_platforms).returns([ Pod::Platform.new(:ios, '4.0'), Pod::Platform.new(:osx, '10.7') ])
lambda { @resolver.resolve }.should.not.raise lambda { @resolver.resolve }.should.not.raise
Pod::Specification.any_instance.stubs(:platforms).returns([ Pod::Platform.new(:ios, '5.0'), Pod::Platform.new(:osx, '10.7') ]) Pod::Specification.any_instance.stubs(:available_platforms).returns([ Pod::Platform.new(:ios, '5.0'), Pod::Platform.new(:osx, '10.7') ])
lambda { @resolver.resolve }.should.raise Pod::Informative lambda { @resolver.resolve }.should.raise Pod::Informative
end end
...@@ -75,20 +75,80 @@ describe "Pod::Resolver" do ...@@ -75,20 +75,80 @@ describe "Pod::Resolver" do
@podfile = Pod::Podfile.new do @podfile = Pod::Podfile.new do
platform :ios platform :ios
dependency 'RestKit/Network' dependency 'RestKit/Network'
dependency 'RestKit/ObjectMapping' dependency 'RestKit/ObjectMapping/XML'
end
resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
resolver.resolve.values.flatten.map(&:name).sort.should == %w{
FileMD5Hash
LibComponentLogging-Core
LibComponentLogging-NSLog
RestKit/Network
RestKit/ObjectMapping/XML
SOCKit
XMLReader
cocoa-oauth
}
end
it "includes all the subspecs of a specification node" do
@podfile = Pod::Podfile.new do
platform :ios
dependency 'RestKit'
end end
resolver = Pod::Resolver.new(@podfile, stub('sandbox')) resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
resolver.resolve.values.flatten.map(&:name).sort.should == %w{ resolver.resolve.values.flatten.map(&:name).sort.should == %w{
FileMD5Hash FileMD5Hash
ISO8601DateFormatter ISO8601DateFormatter
JSONKit
LibComponentLogging-Core LibComponentLogging-Core
LibComponentLogging-NSLog LibComponentLogging-NSLog
RestKit RestKit
RestKit/Network RestKit/Network
RestKit/ObjectMapping RestKit/ObjectMapping
RestKit/ObjectMapping/CoreData
RestKit/ObjectMapping/JSON
RestKit/ObjectMapping/XML
RestKit/UI
SOCKit SOCKit
UDTableView
XMLReader
cocoa-oauth cocoa-oauth
} }
end end
it "if defined it includes only the main subspec of of a specification node" do
@podfile = Pod::Podfile.new do
platform :ios
dependency do |s|
s.main_subspec = 'JSON'
s.name = 'RestKit'
s.version = '0.10.0'
s.subspec 'JSON' do |js|
js.dependency 'RestKit/Network'
js.dependency 'RestKit/UI'
js.dependency 'RestKit/ObjectMapping/JSON'
js.dependency 'RestKit/ObjectMapping/CoreData'
end
s.subspec 'Network'
s.subspec 'UI'
s.subspec 'ObjectMapping' do |os|
os.subspec 'JSON'
os.subspec 'XML'
os.subspec 'CoreData'
end
end
end
resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
resolver.resolve.values.flatten.map(&:name).sort.should == %w{
RestKit
RestKit/JSON
RestKit/Network
RestKit/ObjectMapping/CoreData
RestKit/ObjectMapping/JSON
RestKit/UI
}
end
end end
...@@ -29,12 +29,6 @@ describe "Pod::Specification::Set" do ...@@ -29,12 +29,6 @@ describe "Pod::Specification::Set" do
lambda { @set.required_version }.should.raise Pod::Informative lambda { @set.required_version }.should.raise Pod::Informative
end end
it "returns that this set is only part for other pods" do
@set.required_by(Pod::Spec.new { |s| s.part_of = 'CocoaLumberjack' })
@set.required_by(Pod::Spec.new { |s| s.part_of = 'CocoaLumberjack' })
@set.should.be.only_part_of_other_pod
end
before do before do
@set.required_by(Pod::Spec.new { |s| s.dependency 'CocoaLumberjack', '< 1.2.1' }) @set.required_by(Pod::Spec.new { |s| s.dependency 'CocoaLumberjack', '< 1.2.1' })
end end
...@@ -51,11 +45,6 @@ describe "Pod::Specification::Set" do ...@@ -51,11 +45,6 @@ describe "Pod::Specification::Set" do
@set.specification.should == Pod::Spec.new { |s| s.name = 'CocoaLumberjack'; s.version = '1.2' } @set.specification.should == Pod::Spec.new { |s| s.name = 'CocoaLumberjack'; s.version = '1.2' }
end end
it "returns that this set is not only part for other pods" do
@set.required_by(Pod::Spec.new { |s| s.part_of = 'CocoaLumberjack' })
@set.should.not.be.only_part_of_other_pod
end
it "ignores dotfiles when getting the version directories" do it "ignores dotfiles when getting the version directories" do
`touch #{fixture('spec-repos/master/CocoaLumberjack/.DS_Store')}` `touch #{fixture('spec-repos/master/CocoaLumberjack/.DS_Store')}`
lambda { @set.versions }.should.not.raise lambda { @set.versions }.should.not.raise
......
...@@ -6,6 +6,10 @@ describe "A Pod::Specification loaded from a podspec" do ...@@ -6,6 +6,10 @@ describe "A Pod::Specification loaded from a podspec" do
@spec = Pod::Specification.from_file(fixture('banana-lib/BananaLib.podspec')) @spec = Pod::Specification.from_file(fixture('banana-lib/BananaLib.podspec'))
end end
it "has no parent if it is the top level spec" do
@spec.parent.nil?.should == true
end
it "returns that it's not loaded from a podfile" do it "returns that it's not loaded from a podfile" do
@spec.should.not.be.podfile @spec.should.not.be.podfile
end end
...@@ -60,7 +64,6 @@ describe "A Pod::Specification loaded from a podspec" do ...@@ -60,7 +64,6 @@ describe "A Pod::Specification loaded from a podspec" do
it "returns the pod's dependencies" do it "returns the pod's dependencies" do
expected = Pod::Dependency.new('monkey', '~> 1.0.1', '< 1.0.9') expected = Pod::Dependency.new('monkey', '~> 1.0.1', '< 1.0.9')
@spec.dependencies.should == { :ios => [expected], :osx => [expected] } @spec.dependencies.should == { :ios => [expected], :osx => [expected] }
@spec.dependency_by_top_level_spec_name('monkey').should == expected
end end
it "returns the pod's xcconfig settings" do it "returns the pod's xcconfig settings" do
...@@ -97,6 +100,7 @@ describe "A Pod::Specification loaded from a podspec" do ...@@ -97,6 +100,7 @@ describe "A Pod::Specification loaded from a podspec" do
end end
it "adds compiler flags if ARC is required" do it "adds compiler flags if ARC is required" do
@spec.parent.should == nil
@spec.requires_arc = true @spec.requires_arc = true
@spec.compiler_flags.should == { :ios => " -fobjc-arc", :osx => " -fobjc-arc" } @spec.compiler_flags.should == { :ios => " -fobjc-arc", :osx => " -fobjc-arc" }
@spec.compiler_flags = "-Wunused-value" @spec.compiler_flags = "-Wunused-value"
...@@ -104,46 +108,6 @@ describe "A Pod::Specification loaded from a podspec" do ...@@ -104,46 +108,6 @@ describe "A Pod::Specification loaded from a podspec" do
end end
end end
describe "A Pod::Specification that's part of another pod's source" do
before do
config.repos_dir = fixture('spec-repos')
@spec = Pod::Specification.new
end
after do
config.repos_dir = SpecHelper.tmp_repos_path
end
it "adds a dependency on the other pod's source, but not the library" do
@spec.part_of = 'monkey', '>= 1'
@spec.should.be.part_of_other_pod
dep = Pod::Dependency.new('monkey', '>= 1')
@spec.dependencies.should.not == [dep]
dep.only_part_of_other_pod = true
@spec.dependencies.should == { :ios => [dep], :osx => [dep] }
end
it "adds a dependency on the other pod's source *and* the library" do
@spec.part_of_dependency = 'monkey', '>= 1'
@spec.should.be.part_of_other_pod
@spec.dependencies[:ios].should == [Pod::Dependency.new('monkey', '>= 1')]
end
it "searches the sources for a matching specification if it has not been assigned by the Resolver yet (e.g. the search command)" do
@spec.part_of_dependency = 'SSZipArchive', '0.1.1'
@spec.part_of_specification.to_s.should == 'SSZipArchive (0.1.1)'
end
# TODO
#it "returns the specification of the pod that it's part of" do
# @spec.part_of_specification
#end
#
#it "returns the destroot of the pod that it's part of" do
# @spec.pod_destroot
#end
end
describe "A Pod::Specification, in general," do describe "A Pod::Specification, in general," do
before do before do
@spec = Pod::Spec.new @spec = Pod::Spec.new
...@@ -160,11 +124,11 @@ describe "A Pod::Specification, in general," do ...@@ -160,11 +124,11 @@ describe "A Pod::Specification, in general," do
@spec.platform.deployment_target.should == Pod::Version.new('4.0') @spec.platform.deployment_target.should == Pod::Version.new('4.0')
end end
it "returns the platfroms for which the pod is supported" do it "returns the available platforms for which the pod is supported" do
@spec.platform = :ios, '4.0' @spec.platform = :ios, '4.0'
@spec.platforms.count.should == 1 @spec.available_platforms.count.should == 1
@spec.platforms.first.should == :ios @spec.available_platforms.first.should == :ios
@spec.platforms.first.deployment_target.should == Pod::Version.new('4.0') @spec.available_platforms.first.deployment_target.should == Pod::Version.new('4.0')
end end
it "returns the license of the Pod" do it "returns the license of the Pod" do
...@@ -251,11 +215,6 @@ describe "A Pod::Specification subspec" do ...@@ -251,11 +215,6 @@ describe "A Pod::Specification subspec" do
end end
end end
it "makes a parent spec a wrapper if it has no source files of its own" do
@spec.should.be.wrapper
@spec.subspecs.first.should.not.be.wrapper
end
it "returns the top level parent spec" do it "returns the top level parent spec" do
@spec.subspecs.first.top_level_parent.should == @spec @spec.subspecs.first.top_level_parent.should == @spec
@spec.subspecs.first.subspecs.first.top_level_parent.should == @spec @spec.subspecs.first.subspecs.first.top_level_parent.should == @spec
...@@ -266,18 +225,9 @@ describe "A Pod::Specification subspec" do ...@@ -266,18 +225,9 @@ describe "A Pod::Specification subspec" do
@spec.subspecs.first.subspecs.first.name.should == 'MainSpec/FirstSubSpec/SecondSubSpec' @spec.subspecs.first.subspecs.first.name.should == 'MainSpec/FirstSubSpec/SecondSubSpec'
end end
it "is a `part_of' the top level parent spec" do it "correctly resolves the inheritance chain" do
dependency = Pod::Dependency.new('MainSpec', '1.2.3').tap { |d| d.only_part_of_other_pod = true } @spec.subspecs.first.subspecs.first.parent.should == @spec.subspecs.first
@spec.subspecs.first.part_of.should == dependency @spec.subspecs.first.parent.should == @spec
@spec.subspecs.first.subspecs.first.part_of.should == dependency
end
it "depends on the parent spec, if it is a subspec" do
dependency = Pod::Dependency.new('MainSpec', '1.2.3').tap { |d| d.only_part_of_other_pod = true }
@spec.subspecs.first.dependencies[:ios].should == [dependency]
@spec.subspecs.first.dependencies[:osx].should == [dependency]
@spec.subspecs.first.subspecs.first.dependencies[:ios].should == [dependency, Pod::Dependency.new('MainSpec/FirstSubSpec', '1.2.3')]
@spec.subspecs.first.subspecs.first.dependencies[:osx].should == [dependency, Pod::Dependency.new('MainSpec/FirstSubSpec', '1.2.3')]
end end
it "automatically forwards undefined attributes to the top level parent" do it "automatically forwards undefined attributes to the top level parent" do
...@@ -288,6 +238,8 @@ describe "A Pod::Specification subspec" do ...@@ -288,6 +238,8 @@ describe "A Pod::Specification subspec" do
end end
it "returns subspecs by name" do it "returns subspecs by name" do
@spec.subspec_by_name(nil).should == @spec
@spec.subspec_by_name('MainSpec').should == @spec
@spec.subspec_by_name('MainSpec/FirstSubSpec').should == @spec.subspecs.first @spec.subspec_by_name('MainSpec/FirstSubSpec').should == @spec.subspecs.first
@spec.subspec_by_name('MainSpec/FirstSubSpec/SecondSubSpec').should == @spec.subspecs.first.subspecs.first @spec.subspec_by_name('MainSpec/FirstSubSpec/SecondSubSpec').should == @spec.subspecs.first.subspecs.first
end end
...@@ -337,12 +289,12 @@ describe "A Pod::Specification, concerning its attributes that support different ...@@ -337,12 +289,12 @@ describe "A Pod::Specification, concerning its attributes that support different
end end
it "returns the same list of xcconfig build settings for each platform" do it "returns the same list of xcconfig build settings for each platform" do
build_settings = { 'OTHER_LDFLAGS' => '-lObjC -framework QuartzCore -lz' } build_settings = { 'OTHER_LDFLAGS' => '-lObjC -lz -framework QuartzCore' }
@spec.xcconfig.should == { :ios => build_settings, :osx => build_settings } @spec.xcconfig.should == { :ios => build_settings, :osx => build_settings }
end end
it "returns the same list of compiler flags for each platform" do it "returns the same list of compiler flags for each platform" do
compiler_flags = ' -Wdeprecated-implementations -fobjc-arc' compiler_flags = ' -fobjc-arc -Wdeprecated-implementations'
@spec.compiler_flags.should == { :ios => compiler_flags, :osx => compiler_flags } @spec.compiler_flags.should == { :ios => compiler_flags, :osx => compiler_flags }
end end
...@@ -392,21 +344,21 @@ describe "A Pod::Specification, concerning its attributes that support different ...@@ -392,21 +344,21 @@ describe "A Pod::Specification, concerning its attributes that support different
it "returns a different list of xcconfig build settings for each platform" do it "returns a different list of xcconfig build settings for each platform" do
@spec.xcconfig.should == { @spec.xcconfig.should == {
:ios => { 'OTHER_LDFLAGS' => '-lObjC -framework QuartzCore -lz' }, :ios => { 'OTHER_LDFLAGS' => '-lObjC -lz -framework QuartzCore' },
:osx => { 'OTHER_LDFLAGS' => '-lObjC -all_load -framework QuartzCore -framework CoreData -lz -lxml' } :osx => { 'OTHER_LDFLAGS' => '-lObjC -all_load -lz -lxml -framework QuartzCore -framework CoreData' }
} }
end end
it "returns the list of the supported platfroms and deployment targets" do it "returns the list of the supported platfroms and deployment targets" do
@spec.platforms.count.should == 2 @spec.available_platforms.count.should == 2
@spec.platforms.should.include? Pod::Platform.new(:osx) @spec.available_platforms.should.include? Pod::Platform.new(:osx)
@spec.platforms.should.include? Pod::Platform.new(:ios, '4.0') @spec.available_platforms.should.include? Pod::Platform.new(:ios, '4.0')
end end
it "returns the same list of compiler flags for each platform" do it "returns the same list of compiler flags for each platform" do
@spec.compiler_flags.should == { @spec.compiler_flags.should == {
:ios => ' -Wdeprecated-implementations -fobjc-arc', :ios => ' -fobjc-arc -Wdeprecated-implementations',
:osx => ' -Wfloat-equal -fobjc-arc' :osx => ' -fobjc-arc -Wfloat-equal'
} }
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