Commit d7d3d785 authored by Fabio Pelosin's avatar Fabio Pelosin

[LocalPod] Support for header dir specification in subspecs.

The change is small refactoring to make clear which methods
return relative paths.
parent d4bc7371
......@@ -51,4 +51,5 @@ end
if ENV['COCOA_PODS_ENV'] == 'development'
require 'pry'
require 'awesome_print'
require 'ruby-prof'
end
......@@ -406,7 +406,7 @@ module Pod
def file_patterns_errors
messages = []
messages << "The sources did not match any file" if !@spec.source_files.empty? && @pod.source_files.empty?
messages << "The resources did not match any file" if !@spec.resources.empty? && @pod.resources.empty?
messages << "The resources did not match any file" if !@spec.resources.empty? && @pod.resource_files.empty?
messages << "The preserve_paths did not match any file" if !@spec.preserve_paths.empty? && @pod.preserve_paths.empty?
messages << "The exclude_header_search_paths did not match any file" if !@spec.exclude_header_search_paths.empty? && @pod.headers_excluded_from_search_paths.empty?
messages
......
......@@ -29,7 +29,7 @@ module Pod
pods.each do |pod|
# Add all source files to the project grouped by pod
group = @project.add_pod_group(pod.name)
pod.source_files.each do |path|
pod.relative_source_files.each do |path|
group.files.new('path' => path.to_s)
end
end
......
......@@ -20,12 +20,12 @@ module Pod
end
def copy_resources_script_for(pods)
@copy_resources_script ||= Generator::CopyResourcesScript.new(pods.map { |p| p.resources }.flatten)
@copy_resources_script ||= Generator::CopyResourcesScript.new(pods.map { |p| p.relative_resource_files }.flatten)
end
def bridge_support_generator_for(pods, sandbox)
Generator::BridgeSupport.new(pods.map do |pod|
pod.header_files.map { |header| sandbox.root + header }
pod.relative_header_files.map { |header| sandbox.root + header }
end.flatten)
end
......
......@@ -13,10 +13,13 @@ module Pod
# safely cleaned by the pod.
#
# @example
#
# pod = LocalPod.new 'RestKit/Networking'
# pod.add_specification 'RestKit/UI'
#
# @note
# Unless otherwise specified in the name of the method the {LocalPod}
# returns absolute paths.
#
class LocalPod
# @return [Specification] The specification that describes the pod.
......@@ -140,6 +143,7 @@ module Pod
#
def clean
clean_paths.each { |path| FileUtils.rm_rf(path) }
@cleaned = true
end
# Finds the absolute paths, including hidden ones, of the files
......@@ -148,7 +152,7 @@ module Pod
# @return [Array<Strings>] The paths that can be deleted.
#
def clean_paths
cached_used_paths = used_paths.map{ |path| path.to_s }
cached_used_paths = used_files
files = Dir.glob(root + "**/*", File::FNM_DOTMATCH)
files.reject! do |candidate|
......@@ -159,51 +163,74 @@ module Pod
files
end
# @return [Array<Pathname>] The relative path of the files used by the pod.
# @return [Array<String>] The absolute path of the files used by the pod.
#
def used_paths
files = [ source_files(false),
resources(false),
preserve_paths,
readme_file,
license_file,
prefix_header_file ]
def used_files
files = [ source_files, resource_files, preserve_files, readme_file, license_file, prefix_header_file ]
files.compact!
files.flatten!
files.map!{ |path| path.to_s }
files
end
# @!group Files
# @param (see #source_files_by_spec)
#
# @return [Array<Pathname>] The paths of the source files.
#
def source_files(relative = true)
chained_expanded_paths(:source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => relative)
def source_files
source_files_by_spec.values.flatten
end
# Finds the source files that every activated {Specification} requires.
# @return [Array<Pathname>] The *relative* paths of the source files.
#
# @param [Boolean] relative Whether the paths should be returned relative
# to the sandbox.
def relative_source_files
source_files.map{ |p| p.relative_path_from(@sandbox.root) }
end
# Finds the source files that every activated {Specification} requires.
#
# @note If the same file is required by two specifications the one at the
# higher level in the inheritance chain wins.
#
# @return [Hash{Specification => Array<Pathname>}] The files grouped by
# {Specification}.
#
def source_files_by_spec
options = {:glob => '*.{h,m,mm,c,cpp}'}
paths_by_spec(:source_files, options)
end
# @return [Array<Pathname>] The paths of the header files.
#
def header_files
source_files.select { |f| f.extname == '.h' }
header_files_by_spec.values.flatten
end
# @return [Array<Pathname>] The *relative* paths of the source files.
#
def relative_header_files
header_files.map{ |p| p.relative_path_from(@sandbox.root) }
end
# @return [Hash{Specification => Array<Pathname>}] The paths of the header
# files grouped by {Specification}.
#
def header_files_by_spec
source_files_by_spec.dup.each do |spec, paths|
paths.select! { |f| f.extname == '.h' }
end
end
# @return [Array<Pathname>] The paths of the resources.
#
def resources(relative = true)
chained_expanded_paths(:resources, :relative_to_sandbox => relative)
def resource_files
paths_by_spec(:resources).values.flatten
end
# @return [Array<Pathname>] The *relative* paths of the resources.
#
def relative_resource_files
resource_files.map{ |p| p.relative_path_from(@sandbox.root) }
end
# @return [Pathname] The absolute path of the prefix header file
......@@ -215,11 +242,15 @@ module Pod
# @return [Array<Pathname>] The absolute paths of the files of the pod
# that should be preserved.
#
def preserve_paths
chained_expanded_paths(:preserve_paths) + expanded_paths(%w[ *.podspec notice* NOTICE* CREDITS* ])
def preserve_files
paths = paths_by_spec(:preserve_paths).values
paths += expanded_paths(%w[ *.podspec notice* NOTICE* CREDITS* ])
paths.compact!
paths.uniq!
paths
end
# @return [Pathname] The automatically detected path of the README
# @return [Pathname] The automatically detected absolute path of the README
# file.
#
def readme_file
......@@ -266,9 +297,16 @@ module Pod
# @return [Array<Pathname>] The path of all the public headers of the pod.
#
def all_specs_public_header_files
#TODO: merge with #221
specs = top_specification.recursive_subspecs << top_specification
specs.map { |s| expanded_paths(s.source_files, :glob => '*.{h}') }.compact.flatten.select { |f| f.extname == '.h' }.uniq
if @cleaned
raise Informative, "The pod is cleaned and cannot compute the all the "\
"header files as they might be deleted."
end
all_specs = top_specification.recursive_subspecs << top_specification
files = all_specs.map { |s| expanded_paths(s.source_files, :glob => '*.{h}') }
files.flatten!
files.select! { |f| f && f.extname == '.h' }
files.uniq!
files
end
# @!group Target integration
......@@ -276,7 +314,7 @@ module Pod
# @return [void] Copies the pods headers to the sandbox.
#
def link_headers
copy_header_mappings.each do |namespaced_path, files|
header_mappings.each do |namespaced_path, files|
@sandbox.add_header_files(namespaced_path, files)
end
end
......@@ -287,8 +325,9 @@ module Pod
# @return [void] Adds the pods source files to a given target.
#
def add_to_target(target)
sources_files_by_specification.each do | spec, files |
source_files_by_spec.each do | spec, files |
files.each do |file|
file = file.relative_path_from(@sandbox.root)
target.add_source_file(file, nil, spec.compiler_flags.strip)
end
end
......@@ -306,7 +345,7 @@ module Pod
# (the files the need to compiled) of the pod.
#
def implementation_files
source_files.select { |f| f.extname != '.h' }
relative_source_files.select { |f| f.extname != '.h' }
end
# @return [Pathname] The path of the pod relative from the sandbox.
......@@ -315,63 +354,62 @@ module Pod
root.relative_path_from(@sandbox.root)
end
# @return Hash{Pathname => [Array<Pathname>]} A hash containing the headers
# folders as the keys and the the absolute paths of the header files
# as the values.
#
# @todo this is being overridden in the RestKit 0.9.4 spec, need to do
# something with that, and this method also still exists in Specification.
#
# @todo This is not overridden anymore in specification refactor and the
# code Pod::Specification#copy_header_mapping can be moved here.
def copy_header_mappings
search_path_headers = header_files - headers_excluded_from_search_paths
search_path_headers.inject({}) do |mappings, from|
from_without_prefix = from.relative_path_from(relative_root)
to = top_specification.header_dir + top_specification.copy_header_mapping(from_without_prefix)
def header_mappings
mappings = {}
header_files_by_spec.each do |spec, paths|
paths = paths - headers_excluded_from_search_paths
paths.each do |from|
from_relative = from.relative_path_from(root)
to = spec.header_dir + spec.copy_header_mapping(from_relative)
(mappings[to.dirname] ||= []) << from
mappings
end
end
# Finds the source files that every activate {Specification} requires.
#
# @note The paths of the files are relative to the sandbox.
# @note If the same file is required by two specifications the one at the higher level in the inheritance chain wins.
#
# @return [Hash{Specification => Array<Pathname>}] The files grouped by {Specification}.
#
def sources_files_by_specification
files_by_spec = {}
processed_files = []
specifications.sort_by { |s| s.name.length }.each do |spec|
files = []
expanded_paths(spec.source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => true).each do | file |
files << file unless processed_files.include?(file)
end
files_by_spec[spec] = files
processed_files += files
end
files_by_spec
mappings
end
# @todo merge with #221
# @return [<Pathname>] The relative path of the headers that should not be
# included in the linker search paths.
#
def headers_excluded_from_search_paths
chained_expanded_paths(:exclude_header_search_paths, :glob => '*.h', :relative_to_sandbox => true)
options = { :glob => '*.h' }
paths = paths_by_spec(:exclude_header_search_paths, options)
paths.values.compact.uniq
end
# @!group Paths Patterns
# Finds all the paths patterns of a each activated specifications and
# converts them to the actual paths present in the pod.
# The paths obtained by resolving the patterns of an attribute
# groupped by spec.
#
# @return [Array<Pathname>] A list of the paths.
# @param [Symbol] accessor The accessor to use to obtain the paths patterns.
# @param [Hash] options (see #expanded_paths)
#
def chained_expanded_paths(accessor, options = {})
specifications.map { |s| expanded_paths(s.send(accessor), options) }.compact.flatten.uniq
def paths_by_spec(accessor, options = {})
paths_by_spec = {}
processed_paths = []
specs = specifications.sort_by { |s| s.name.length }
specs.each do |spec|
paths = expanded_paths(spec.send(accessor), options)
unless paths.empty?
paths_by_spec[spec] = paths - processed_paths
processed_paths += paths
end
end
paths_by_spec
end
# The paths obtained by interpolating the patterns of a given attribute
# collected by spec.
#
# @todo implement case insensitive search
# Converts patterns of paths to the {Pathname} of the files present in the
# pod.
#
# @param [String, FileList, Array<String, Pathname>] patterns
# The patterns to expand.
......@@ -379,8 +417,6 @@ module Pod
# The options to used for expanding the paths patterns.
# @option options [String] :glob
# The pattern to use for globing directories.
# @option options [Boolean] :relative_to_sandbox
# Whether the paths should be returned relative to the sandbox.
#
# @raise [Informative] If the pod does not exists.
#
......@@ -405,12 +441,8 @@ module Pod
end
pattern.glob.map do |file|
if options[:relative_to_sandbox]
file.relative_path_from(@sandbox.root)
else
file
end
end
end.flatten
end
end
......
......@@ -38,10 +38,18 @@ module Pod
end
# multi-platform attributes
%w[ source_files resources preserve_paths exclude_header_search_paths frameworks libraries dependencies compiler_flags].each do |attr|
%w[ source_files
resources
preserve_paths
exclude_header_search_paths
frameworks
libraries
dependencies
compiler_flags ].each do |attr|
instance_variable_set( "@#{attr}", { :ios => [], :osx => [] } )
end
@xcconfig = { :ios => Xcodeproj::Config.new, :osx => Xcodeproj::Config.new }
@header_dir = { :ios => nil, :osx => nil }
yield self if block_given?
end
......@@ -122,6 +130,7 @@ module Pod
libraries=
compiler_flags=
deployment_target=
header_dir=
dependency }.each do |method|
define_method(method) do |args|
@specification._on_platform(@platform) do
......@@ -190,9 +199,6 @@ module Pod
top_attr_reader :description, lambda {|instance, ivar| ivar || instance.summary }
top_attr_writer :description
top_attr_reader :header_dir, lambda {|instance, ivar| ivar || instance.pod_destroot_name }
top_attr_writer :header_dir, lambda {|dir| Pathname.new(dir) }
alias_method :author=, :authors=
def self.parse_authors(*names_and_email_addresses)
......@@ -218,6 +224,16 @@ module Pod
alias_method :framework=, :frameworks=
alias_method :library=, :libraries=
# @return The directory to namespace the headers.
#
# It defaults to the name of the top level specification.
#
platform_attr_writer :header_dir, lambda { |dir,_| Pathname.new(dir) }
def header_dir
@header_dir[active_platform] || pod_destroot_name
end
platform_attr_writer :xcconfig, lambda {|value, current| current.tap { |c| c.merge!(value) } }
def xcconfig
......
......@@ -31,12 +31,29 @@ describe Pod::LocalPod do
end
it 'returns an expanded list of source files, relative to the sandbox root' do
@pod.source_files.sort.should == [
@pod.relative_source_files.sort.should == [
Pathname.new("BananaLib/Classes/Banana.m"),
Pathname.new("BananaLib/Classes/Banana.h")
].sort
end
it 'returns the source files groupped by specification' do
files = @pod.source_files_by_spec[@pod.specifications.first].sort
files.should == [
@pod.root + "Classes/Banana.m",
@pod.root + "Classes/Banana.h"
].sort
end
it 'returns a list of header files' do
@pod.relative_header_files.should == [Pathname.new("BananaLib/Classes/Banana.h")]
end
it 'returns a list of header files by specification' do
files = @pod.header_files_by_spec[@pod.specifications.first].sort
files.should == [ @pod.root + "Classes/Banana.h" ]
end
it 'returns an expanded list the files to clean' do
clean_paths = @pod.clean_paths.map { |p| p.to_s.gsub(/.*Pods\/BananaLib/,'') }
clean_paths.should.include "/.git/config"
......@@ -46,11 +63,7 @@ describe Pod::LocalPod do
end
it 'returns an expanded list of resources, relative to the sandbox root' do
@pod.resources.should == [Pathname.new("BananaLib/Resources/logo-sidebar.png")]
end
it 'returns a list of header files' do
@pod.header_files.should == [Pathname.new("BananaLib/Classes/Banana.h")]
@pod.relative_resource_files.should == [Pathname.new("BananaLib/Resources/logo-sidebar.png")]
end
it "can link it's headers into the sandbox" 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