Skip to content
This repository
Browse code

Merge pull request #347 from CocoaPods/t-296

Support for `header_dir` attr in subspecs.
  • Loading branch information...
commit 16a324a7aebbbed3fa8619daa739b693f853cc9f 2 parents d4bc737 + f4326c7
Fabio Pelosin irrationalfab authored
1  .gitignore
@@ -13,6 +13,7 @@ examples/Pods
13 13 examples/**/Pods
14 14 examples/RelativePathProject/RelativePathProject/RelativePathProject.xcodeproj
15 15 spec/fixtures/banana-lib
  16 +spec/fixtures/chameleon
16 17 spec/fixtures/integration/Headers/
17 18 /concatenated.*
18 19 spec/fixtures/mercurial-repo/.hg/*cache
2  Rakefile
@@ -145,7 +145,7 @@ namespace :gem do
145 145 # Update the last version in CocoaPods-version.yml
146 146 specs_branch = '0.6'
147 147
148   - Dir.chdir ('../Specs') do
  148 + Dir.chdir('../Specs') do
149 149 puts Dir.pwd
150 150 sh "git checkout #{specs_branch}"
151 151 sh "git pull"
2  lib/cocoapods/command/spec.rb
@@ -406,7 +406,7 @@ def process_xcode_build_output(output)
406 406 def file_patterns_errors
407 407 messages = []
408 408 messages << "The sources did not match any file" if !@spec.source_files.empty? && @pod.source_files.empty?
409   - messages << "The resources did not match any file" if !@spec.resources.empty? && @pod.resources.empty?
  409 + messages << "The resources did not match any file" if !@spec.resources.empty? && @pod.resource_files.empty?
410 410 messages << "The preserve_paths did not match any file" if !@spec.preserve_paths.empty? && @pod.preserve_paths.empty?
411 411 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?
412 412 messages
2  lib/cocoapods/installer.rb
@@ -29,7 +29,7 @@ def project
29 29 pods.each do |pod|
30 30 # Add all source files to the project grouped by pod
31 31 group = @project.add_pod_group(pod.name)
32   - pod.source_files.each do |path|
  32 + pod.relative_source_files.each do |path|
33 33 group.files.new('path' => path.to_s)
34 34 end
35 35 end
4 lib/cocoapods/installer/target_installer.rb
@@ -20,12 +20,12 @@ def xcconfig
20 20 end
21 21
22 22 def copy_resources_script_for(pods)
23   - @copy_resources_script ||= Generator::CopyResourcesScript.new(pods.map { |p| p.resources }.flatten)
  23 + @copy_resources_script ||= Generator::CopyResourcesScript.new(pods.map { |p| p.relative_resource_files }.flatten)
24 24 end
25 25
26 26 def bridge_support_generator_for(pods, sandbox)
27 27 Generator::BridgeSupport.new(pods.map do |pod|
28   - pod.header_files.map { |header| sandbox.root + header }
  28 + pod.relative_header_files.map { |header| sandbox.root + header }
29 29 end.flatten)
30 30 end
31 31
187 lib/cocoapods/local_pod.rb
@@ -13,10 +13,13 @@ module Pod
13 13 # safely cleaned by the pod.
14 14 #
15 15 # @example
16   - #
17 16 # pod = LocalPod.new 'RestKit/Networking'
18 17 # pod.add_specification 'RestKit/UI'
19 18 #
  19 + # @note
  20 + # Unless otherwise specified in the name of the method the {LocalPod}
  21 + # returns absolute paths.
  22 + #
20 23 class LocalPod
21 24
22 25 # @return [Specification] The specification that describes the pod.
@@ -140,6 +143,7 @@ def implode
140 143 #
141 144 def clean
142 145 clean_paths.each { |path| FileUtils.rm_rf(path) }
  146 + @cleaned = true
143 147 end
144 148
145 149 # Finds the absolute paths, including hidden ones, of the files
@@ -148,7 +152,7 @@ def clean
148 152 # @return [Array<Strings>] The paths that can be deleted.
149 153 #
150 154 def clean_paths
151   - cached_used_paths = used_paths.map{ |path| path.to_s }
  155 + cached_used_paths = used_files
152 156 files = Dir.glob(root + "**/*", File::FNM_DOTMATCH)
153 157
154 158 files.reject! do |candidate|
@@ -159,51 +163,77 @@ def clean_paths
159 163 files
160 164 end
161 165
162   - # @return [Array<Pathname>] The relative path of the files used by the pod.
  166 + # @return [Array<String>] The absolute path of the files used by the pod.
163 167 #
164   - def used_paths
165   - files = [ source_files(false),
166   - resources(false),
167   - preserve_paths,
168   - readme_file,
169   - license_file,
170   - prefix_header_file ]
  168 + def used_files
  169 + files = [ source_files, resource_files, preserve_files, readme_file, license_file, prefix_header_file ]
171 170 files.compact!
172 171 files.flatten!
  172 + files.map!{ |path| path.to_s }
173 173 files
174 174 end
175 175
176 176 # @!group Files
177 177
178   - # @param (see #source_files_by_spec)
179   - #
180 178 # @return [Array<Pathname>] The paths of the source files.
181 179 #
182   - def source_files(relative = true)
183   - chained_expanded_paths(:source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => relative)
  180 + def source_files
  181 + source_files_by_spec.values.flatten
184 182 end
185 183
186   - # Finds the source files that every activated {Specification} requires.
  184 + # @return [Array<Pathname>] The *relative* paths of the source files.
187 185 #
188   - # @param [Boolean] relative Whether the paths should be returned relative
189   - # to the sandbox.
  186 + def relative_source_files
  187 + source_files.map{ |p| p.relative_path_from(@sandbox.root) }
  188 + end
  189 +
  190 + # Finds the source files that every activated {Specification} requires.
190 191 #
191 192 # @note If the same file is required by two specifications the one at the
192 193 # higher level in the inheritance chain wins.
193 194 #
  195 + # @return [Hash{Specification => Array<Pathname>}] The files grouped by
  196 + # {Specification}.
  197 + #
  198 + def source_files_by_spec
  199 + options = {:glob => '*.{h,m,mm,c,cpp}'}
  200 + paths_by_spec(:source_files, options)
  201 + end
  202 +
194 203 # @return [Array<Pathname>] The paths of the header files.
195 204 #
196 205 def header_files
197   - source_files.select { |f| f.extname == '.h' }
  206 + header_files_by_spec.values.flatten
  207 + end
  208 +
  209 + # @return [Array<Pathname>] The *relative* paths of the source files.
  210 + #
  211 + def relative_header_files
  212 + header_files.map{ |p| p.relative_path_from(@sandbox.root) }
198 213 end
199 214
200 215 # @return [Hash{Specification => Array<Pathname>}] The paths of the header
201 216 # files grouped by {Specification}.
202 217 #
  218 + def header_files_by_spec
  219 + result = {}
  220 + source_files_by_spec.each do |spec, paths|
  221 + headers = paths.select { |f| f.extname == '.h' }
  222 + result[spec] = headers unless headers.empty?
  223 + end
  224 + result
  225 + end
  226 +
203 227 # @return [Array<Pathname>] The paths of the resources.
204 228 #
205   - def resources(relative = true)
206   - chained_expanded_paths(:resources, :relative_to_sandbox => relative)
  229 + def resource_files
  230 + paths_by_spec(:resources).values.flatten
  231 + end
  232 +
  233 + # @return [Array<Pathname>] The *relative* paths of the resources.
  234 + #
  235 + def relative_resource_files
  236 + resource_files.map{ |p| p.relative_path_from(@sandbox.root) }
207 237 end
208 238
209 239 # @return [Pathname] The absolute path of the prefix header file
@@ -215,11 +245,15 @@ def prefix_header_file
215 245 # @return [Array<Pathname>] The absolute paths of the files of the pod
216 246 # that should be preserved.
217 247 #
218   - def preserve_paths
219   - chained_expanded_paths(:preserve_paths) + expanded_paths(%w[ *.podspec notice* NOTICE* CREDITS* ])
  248 + def preserve_files
  249 + paths = paths_by_spec(:preserve_paths).values
  250 + paths += expanded_paths(%w[ *.podspec notice* NOTICE* CREDITS* ])
  251 + paths.compact!
  252 + paths.uniq!
  253 + paths
220 254 end
221 255
222   - # @return [Pathname] The automatically detected path of the README
  256 + # @return [Pathname] The automatically detected absolute path of the README
223 257 # file.
224 258 #
225 259 def readme_file
@@ -266,9 +300,16 @@ def xcconfig
266 300 # @return [Array<Pathname>] The path of all the public headers of the pod.
267 301 #
268 302 def all_specs_public_header_files
269   - #TODO: merge with #221
270   - specs = top_specification.recursive_subspecs << top_specification
271   - specs.map { |s| expanded_paths(s.source_files, :glob => '*.{h}') }.compact.flatten.select { |f| f.extname == '.h' }.uniq
  303 + if @cleaned
  304 + raise Informative, "The pod is cleaned and cannot compute the all the "\
  305 + "header files as they might be deleted."
  306 + end
  307 +
  308 + all_specs = [ top_specification ] + top_specification.subspecs
  309 + options = {:glob => '*.{h}'}
  310 + files = paths_by_spec(:source_files, options, all_specs).values.flatten!
  311 + headers = files.select { |f| f.extname == '.h' }
  312 + headers
272 313 end
273 314
274 315 # @!group Target integration
@@ -276,7 +317,8 @@ def all_specs_public_header_files
276 317 # @return [void] Copies the pods headers to the sandbox.
277 318 #
278 319 def link_headers
279   - copy_header_mappings.each do |namespaced_path, files|
  320 + @sandbox.add_header_search_path(headers_sandbox)
  321 + header_mappings.each do |namespaced_path, files|
280 322 @sandbox.add_header_files(namespaced_path, files)
281 323 end
282 324 end
@@ -287,8 +329,9 @@ def link_headers
287 329 # @return [void] Adds the pods source files to a given target.
288 330 #
289 331 def add_to_target(target)
290   - sources_files_by_specification.each do | spec, files |
  332 + source_files_by_spec.each do | spec, files |
291 333 files.each do |file|
  334 + file = file.relative_path_from(@sandbox.root)
292 335 target.add_source_file(file, nil, spec.compiler_flags.strip)
293 336 end
294 337 end
@@ -306,7 +349,7 @@ def requires_arc?
306 349 # (the files the need to compiled) of the pod.
307 350 #
308 351 def implementation_files
309   - source_files.select { |f| f.extname != '.h' }
  352 + relative_source_files.select { |f| f.extname != '.h' }
310 353 end
311 354
312 355 # @return [Pathname] The path of the pod relative from the sandbox.
@@ -315,63 +358,67 @@ def relative_root
315 358 root.relative_path_from(@sandbox.root)
316 359 end
317 360
  361 + # @return Hash{Pathname => [Array<Pathname>]} A hash containing the headers
  362 + # folders as the keys and the the absolute paths of the header files
  363 + # as the values.
  364 + #
318 365 # @todo this is being overridden in the RestKit 0.9.4 spec, need to do
319 366 # something with that, and this method also still exists in Specification.
320 367 #
321 368 # @todo This is not overridden anymore in specification refactor and the
322 369 # code Pod::Specification#copy_header_mapping can be moved here.
323   - def copy_header_mappings
324   - search_path_headers = header_files - headers_excluded_from_search_paths
325   - search_path_headers.inject({}) do |mappings, from|
326   - from_without_prefix = from.relative_path_from(relative_root)
327   - to = top_specification.header_dir + top_specification.copy_header_mapping(from_without_prefix)
328   - (mappings[to.dirname] ||= []) << from
329   - mappings
  370 + def header_mappings
  371 + mappings = {}
  372 + header_files_by_spec.each do |spec, paths|
  373 + paths = paths - headers_excluded_from_search_paths
  374 + paths.each do |from|
  375 + from_relative = from.relative_path_from(root)
  376 + to = headers_sandbox + (spec.header_dir) + spec.copy_header_mapping(from_relative)
  377 + (mappings[to.dirname] ||= []) << from
  378 + end
330 379 end
  380 + mappings
331 381 end
332 382
333   - # Finds the source files that every activate {Specification} requires.
334   - #
335   - # @note The paths of the files are relative to the sandbox.
336   - # @note If the same file is required by two specifications the one at the higher level in the inheritance chain wins.
337   - #
338   - # @return [Hash{Specification => Array<Pathname>}] The files grouped by {Specification}.
339   - #
340   - def sources_files_by_specification
341   - files_by_spec = {}
342   - processed_files = []
343   - specifications.sort_by { |s| s.name.length }.each do |spec|
344   - files = []
345   - expanded_paths(spec.source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => true).each do | file |
346   - files << file unless processed_files.include?(file)
347   - end
348   - files_by_spec[spec] = files
349   - processed_files += files
350   - end
351   - files_by_spec
  383 + def headers_sandbox
  384 + @headers_sandbox ||= Pathname.new(top_specification.name)
352 385 end
353 386
354   - # @todo merge with #221
  387 + # @return [<Pathname>] The relative path of the headers that should not be
  388 + # included in the linker search paths.
355 389 #
356 390 def headers_excluded_from_search_paths
357   - chained_expanded_paths(:exclude_header_search_paths, :glob => '*.h', :relative_to_sandbox => true)
  391 + options = { :glob => '*.h' }
  392 + paths = paths_by_spec(:exclude_header_search_paths, options)
  393 + paths.values.compact.uniq
358 394 end
359 395
360 396 # @!group Paths Patterns
361 397
362   - # Finds all the paths patterns of a each activated specifications and
363   - # converts them to the actual paths present in the pod.
  398 + # The paths obtained by resolving the patterns of an attribute
  399 + # groupped by spec.
364 400 #
365   - # @return [Array<Pathname>] A list of the paths.
  401 + # @param [Symbol] accessor The accessor to use to obtain the paths patterns.
  402 + # @param [Hash] options (see #expanded_paths)
366 403 #
367   - def chained_expanded_paths(accessor, options = {})
368   - specifications.map { |s| expanded_paths(s.send(accessor), options) }.compact.flatten.uniq
  404 + def paths_by_spec(accessor, options = {}, specs = nil)
  405 + specs ||= specifications
  406 + paths_by_spec = {}
  407 + processed_paths = []
  408 +
  409 + specs = specs.sort_by { |s| s.name.length }
  410 + specs.each do |spec|
  411 + paths = expanded_paths(spec.send(accessor), options)
  412 + unless paths.empty?
  413 + paths_by_spec[spec] = paths - processed_paths
  414 + processed_paths += paths
  415 + end
  416 + end
  417 + paths_by_spec
369 418 end
370 419
371   - # The paths obtained by interpolating the patterns of a given attribute
372   - # collected by spec.
373   - #
374   - # @todo implement case insensitive search
  420 + # Converts patterns of paths to the {Pathname} of the files present in the
  421 + # pod.
375 422 #
376 423 # @param [String, FileList, Array<String, Pathname>] patterns
377 424 # The patterns to expand.
@@ -379,8 +426,6 @@ def chained_expanded_paths(accessor, options = {})
379 426 # The options to used for expanding the paths patterns.
380 427 # @option options [String] :glob
381 428 # The pattern to use for globing directories.
382   - # @option options [Boolean] :relative_to_sandbox
383   - # Whether the paths should be returned relative to the sandbox.
384 429 #
385 430 # @raise [Informative] If the pod does not exists.
386 431 #
@@ -405,11 +450,7 @@ def expanded_paths(patterns, options = {})
405 450 end
406 451
407 452 pattern.glob.map do |file|
408   - if options[:relative_to_sandbox]
409   - file.relative_path_from(@sandbox.root)
410   - else
411   - file
412   - end
  453 + file
413 454 end
414 455 end.flatten
415 456 end
10 lib/cocoapods/sandbox.rb
@@ -42,6 +42,16 @@ def header_search_paths
42 42 @header_search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" }
43 43 end
44 44
  45 + # Adds an header search path to the sandbox.
  46 + #
  47 + # @param path [Pathname] The path tho add.
  48 + #
  49 + # @return [void]
  50 + #
  51 + def add_header_search_path(path)
  52 + @header_search_paths << Pathname.new(HEADERS_DIR) + path
  53 + end
  54 +
45 55 def prepare_for_install
46 56 headers_root.rmtree if headers_root.exist?
47 57 end
53 lib/cocoapods/specification.rb
@@ -38,10 +38,18 @@ def initialize(parent = nil, name = nil)
38 38 end
39 39
40 40 # multi-platform attributes
41   - %w[ source_files resources preserve_paths exclude_header_search_paths frameworks libraries dependencies compiler_flags].each do |attr|
  41 + %w[ source_files
  42 + resources
  43 + preserve_paths
  44 + exclude_header_search_paths
  45 + frameworks
  46 + libraries
  47 + dependencies
  48 + compiler_flags ].each do |attr|
42 49 instance_variable_set( "@#{attr}", { :ios => [], :osx => [] } )
43 50 end
44 51 @xcconfig = { :ios => Xcodeproj::Config.new, :osx => Xcodeproj::Config.new }
  52 + @header_dir = { :ios => nil, :osx => nil }
45 53
46 54 yield self if block_given?
47 55 end
@@ -122,6 +130,7 @@ def initialize(specification, platform)
122 130 libraries=
123 131 compiler_flags=
124 132 deployment_target=
  133 + header_dir=
125 134 dependency }.each do |method|
126 135 define_method(method) do |args|
127 136 @specification._on_platform(@platform) do
@@ -183,16 +192,10 @@ def available_platforms
183 192 top_attr_accessor :license, lambda { |l| ( l.kind_of? String ) ? { :type => l } : l }
184 193 top_attr_accessor :version, lambda { |v| Version.new(v) }
185 194 top_attr_accessor :authors, lambda { |a| parse_authors(a) }
186   - top_attr_accessor :header_mappings_dir, lambda { |file| Pathname.new(file) } # If not provided the headers files are flattened
187   - top_attr_accessor :prefix_header_file, lambda { |file| Pathname.new(file) }
188   - top_attr_accessor :prefix_header_contents
189 195
190 196 top_attr_reader :description, lambda {|instance, ivar| ivar || instance.summary }
191 197 top_attr_writer :description
192 198
193   - top_attr_reader :header_dir, lambda {|instance, ivar| ivar || instance.pod_destroot_name }
194   - top_attr_writer :header_dir, lambda {|dir| Pathname.new(dir) }
195   -
196 199 alias_method :author=, :authors=
197 200
198 201 def self.parse_authors(*names_and_email_addresses)
@@ -206,6 +209,13 @@ def self.parse_authors(*names_and_email_addresses)
206 209
207 210 ### Attributes **with** multiple platform support
208 211
  212 + # @todo allow for subspecs
  213 + #
  214 + top_attr_accessor :header_mappings_dir, lambda { |file| Pathname.new(file) } # If not provided the headers files are flattened
  215 + top_attr_accessor :prefix_header_file, lambda { |file| Pathname.new(file) }
  216 + top_attr_accessor :prefix_header_contents
  217 +
  218 +
209 219 pltf_chained_attr_accessor :source_files, lambda {|value, current| pattern_list(value) }
210 220 pltf_chained_attr_accessor :resources, lambda {|value, current| pattern_list(value) }
211 221 pltf_chained_attr_accessor :preserve_paths, lambda {|value, current| pattern_list(value) } # Paths that should not be cleaned
@@ -218,7 +228,28 @@ def self.parse_authors(*names_and_email_addresses)
218 228 alias_method :framework=, :frameworks=
219 229 alias_method :library=, :libraries=
220 230
221   - platform_attr_writer :xcconfig, lambda {|value, current| current.tap { |c| c.merge!(value) } }
  231 + # @!method header_dir=
  232 + #
  233 + # @abstract The directory where to name space the headers files of
  234 + # the specification.
  235 + #
  236 + # @param [String] The headers directory.
  237 + #
  238 + platform_attr_writer :header_dir, lambda { |dir, _| Pathname.new(dir) }
  239 +
  240 + # @abstract (see #header_dir=)
  241 + #
  242 + # @return [Pathname] The headers directory.
  243 + #
  244 + # @note If no value is provided it returns an empty {Pathname}.
  245 + #
  246 + def header_dir
  247 + @header_dir[active_platform] || (@parent.header_dir if @parent) || Pathname.new('')
  248 + end
  249 +
  250 + # @!method xcconfig=
  251 + #
  252 + platform_attr_writer :xcconfig, lambda {|value, current| current.tap { |c| c.merge!(value) } }
222 253
223 254 def xcconfig
224 255 raw_xconfig.dup.
@@ -341,12 +372,6 @@ def pod_destroot
341 372 end
342 373 end
343 374
344   - def pod_destroot_name
345   - if root = pod_destroot
346   - root.basename
347   - end
348   - end
349   -
350 375 def self.pattern_list(patterns)
351 376 if patterns.is_a?(Array) && (!defined?(Rake) || !patterns.is_a?(Rake::FileList))
352 377 patterns
BIN  spec/fixtures/chameleon.tar.gz
Binary file not shown
373 spec/unit/local_pod_spec.rb
@@ -6,7 +6,8 @@
6 6 describe "in general" do
7 7 before do
8 8 @sandbox = temporary_sandbox
9   - @pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), @sandbox, Pod::Platform.new(:ios))
  9 + @spec = fixture_spec('banana-lib/BananaLib.podspec')
  10 + @pod = Pod::LocalPod.new(@spec, @sandbox, Pod::Platform.new(:ios))
10 11 copy_fixture_to_pod('banana-lib', @pod)
11 12 end
12 13
@@ -31,12 +32,29 @@
31 32 end
32 33
33 34 it 'returns an expanded list of source files, relative to the sandbox root' do
34   - @pod.source_files.sort.should == [
  35 + @pod.relative_source_files.sort.should == [
35 36 Pathname.new("BananaLib/Classes/Banana.m"),
36 37 Pathname.new("BananaLib/Classes/Banana.h")
37 38 ].sort
38 39 end
39 40
  41 + it 'returns the source files groupped by specification' do
  42 + files = @pod.source_files_by_spec[@pod.specifications.first].sort
  43 + files.should == [
  44 + @pod.root + "Classes/Banana.m",
  45 + @pod.root + "Classes/Banana.h"
  46 + ].sort
  47 + end
  48 +
  49 + it 'returns a list of header files' do
  50 + @pod.relative_header_files.should == [Pathname.new("BananaLib/Classes/Banana.h")]
  51 + end
  52 +
  53 + it 'returns a list of header files by specification' do
  54 + files = @pod.header_files_by_spec[@pod.specifications.first].sort
  55 + files.should == [ @pod.root + "Classes/Banana.h" ]
  56 + end
  57 +
40 58 it 'returns an expanded list the files to clean' do
41 59 clean_paths = @pod.clean_paths.map { |p| p.to_s.gsub(/.*Pods\/BananaLib/,'') }
42 60 clean_paths.should.include "/.git/config"
@@ -46,11 +64,7 @@
46 64 end
47 65
48 66 it 'returns an expanded list of resources, relative to the sandbox root' do
49   - @pod.resources.should == [Pathname.new("BananaLib/Resources/logo-sidebar.png")]
50   - end
51   -
52   - it 'returns a list of header files' do
53   - @pod.header_files.should == [Pathname.new("BananaLib/Classes/Banana.h")]
  67 + @pod.relative_resource_files.should == [Pathname.new("BananaLib/Resources/logo-sidebar.png")]
54 68 end
55 69
56 70 it "can link it's headers into the sandbox" do
@@ -84,172 +98,201 @@
84 98 end
85 99 end
86 100
87   - describe "with installed source," do
88   - #before do
89   - #config.project_pods_root = fixture('integration')
90   - #podspec = fixture('spec-repos/master/SSZipArchive/0.1.0/SSZipArchive.podspec')
91   - #@spec = Pod::Specification.from_file(podspec)
92   - #@destroot = fixture('integration/SSZipArchive')
93   - #end
94   -
95   - xit "returns the list of files that the source_files pattern expand to" do
96   - files = @destroot.glob('**/*.{h,c,m}')
97   - files = files.map { |file| file.relative_path_from(config.project_pods_root) }
98   - @spec.expanded_source_files[:ios].sort.should == files.sort
99   - end
100   -
101   - xit "returns the list of headers" do
102   - files = @destroot.glob('**/*.h')
103   - files = files.map { |file| file.relative_path_from(config.project_pods_root) }
104   - @spec.header_files[:ios].sort.should == files.sort
105   - end
106   -
107   - xit "returns a hash of mappings from the pod's destroot to its header dirs, which by default is just the pod's header dir" do
108   - @spec.copy_header_mappings[:ios].size.should == 1
109   - @spec.copy_header_mappings[:ios][Pathname.new('SSZipArchive')].sort.should == %w{
110   - SSZipArchive.h
111   - minizip/crypt.h
112   - minizip/ioapi.h
113   - minizip/mztools.h
114   - minizip/unzip.h
115   - minizip/zip.h
116   - }.map { |f| Pathname.new("SSZipArchive/#{f}") }.sort
117   - end
118   -
119   - xit "allows for customization of header mappings by overriding copy_header_mapping" do
120   - def @spec.copy_header_mapping(from)
121   - Pathname.new('ns') + from.basename
122   - end
123   - @spec.copy_header_mappings[:ios].size.should == 1
124   - @spec.copy_header_mappings[:ios][Pathname.new('SSZipArchive/ns')].sort.should == %w{
125   - SSZipArchive.h
126   - minizip/crypt.h
127   - minizip/ioapi.h
128   - minizip/mztools.h
129   - minizip/unzip.h
130   - minizip/zip.h
131   - }.map { |f| Pathname.new("SSZipArchive/#{f}") }.sort
132   - end
133   -
134   - xit "returns a hash of mappings with a custom header dir prefix" do
135   - @spec.header_dir = 'AnotherRoot'
136   - @spec.copy_header_mappings[:ios][Pathname.new('AnotherRoot')].sort.should == %w{
137   - SSZipArchive.h
138   - minizip/crypt.h
139   - minizip/ioapi.h
140   - minizip/mztools.h
141   - minizip/unzip.h
142   - minizip/zip.h
143   - }.map { |f| Pathname.new("SSZipArchive/#{f}") }.sort
144   - end
145   -
146   - xit "returns the user header search paths" do
147   - def @spec.copy_header_mapping(from)
148   - Pathname.new('ns') + from.basename
149   - end
150   - @spec.header_search_paths.should == %w{
151   - "$(PODS_ROOT)/Headers/SSZipArchive"
152   - "$(PODS_ROOT)/Headers/SSZipArchive/ns"
153   - }
154   - end
  101 + describe "with installed source and multiple subspecs" do
155 102
156   - xit "returns the user header search paths with a custom header dir prefix" do
157   - @spec.header_dir = 'AnotherRoot'
158   - def @spec.copy_header_mapping(from)
159   - Pathname.new('ns') + from.basename
160   - end
161   - @spec.header_search_paths.should == %w{
162   - "$(PODS_ROOT)/Headers/AnotherRoot"
163   - "$(PODS_ROOT)/Headers/AnotherRoot/ns"
164   - }
  103 + def assert_array_equals(expected, computed)
  104 + delta1 = computed - expected
  105 + delta1.should == []
  106 + delta2 = expected - computed
  107 + delta2.should == []
165 108 end
166 109
167   - xit "returns the list of files that the resources pattern expand to" do
168   - @spec.expanded_resources.should == {}
169   - @spec.resource = 'LICEN*'
170   - @spec.expanded_resources[:ios].map(&:to_s).should == %w{ SSZipArchive/LICENSE }
171   - @spec.expanded_resources[:osx].map(&:to_s).should == %w{ SSZipArchive/LICENSE }
172   - @spec.resources = 'LICEN*', 'Readme.*'
173   - @spec.expanded_resources[:ios].map(&:to_s).should == %w{ SSZipArchive/LICENSE SSZipArchive/Readme.markdown }
174   - @spec.expanded_resources[:osx].map(&:to_s).should == %w{ SSZipArchive/LICENSE SSZipArchive/Readme.markdown }
175   - end
176   - end
177   -
178   - describe "regarding multiple subspecs" do
179   -
180 110 before do
181   - # specification with only some subspecs activated
182   - # to check that only the needed files are being activated
183   - # A fixture is needed.
184   - #
185   - # specification = Pod::Spec.new do |s|
186   - # ...
187   - # s.xcconfig = ...
188   - # s.compiler_flags = ...
189   - # s.subspec 's1' do |s1|
190   - # s1.xcconfig = ...
191   - # s1.compiler_flags = ...
192   - # s1.ns.source_files = 's1.{h,m}'
193   - # end
194   - #
195   - # s.subspec 's2' do |s2|
196   - # s2.ns.source_files = 's2.{h,m}'
197   - # end
198   - #
199   - # Add only s1 to the localPod
200   - # s1 = specification.subspec_by_name(s1)
201   - # @pod = Pod::LocalPod.new(s1, @sandbox, Pod::Platform.new(:ios))
202   - # @pod.add_specification(specification)
203   - end
204   -
205   - xit "returns the subspecs" do
206   - @pod.subspecs.map{ |s| name }.should == %w[ s1 ]
207   - end
208   -
209   - xit "resolve the source files" do
210   - @pod.source_files.should == %w[ s1.h s1.m ]
211   - end
212   -
213   - xit "resolve the resources" do
214   - end
215   -
216   - xit "resolve the clean paths" do
217   - @pod.clean_paths.should == %w[ s2.h s2.m ]
218   - end
219   -
220   - xit "resolves the used files" do
221   - @pod.used_files.should == %w[ s1.h s1.m README.md ]
222   - end
223   -
224   - xit "resolved the header files" do
225   - @pod.header_files.should == %w[ s1.h ]
226   - end
227   -
228   - xit "resolves the header files of every subspec" do
229   - @pod.all_specs_public_header_files.should == %w[ s1.h s2.h ]
230   - end
231   -
232   - xit "merges the xcconfigs" do
233   - end
234   -
235   - xit "adds each file to a target with the compiler flags of its specification" do
236   - # @pod.add_to_target(target)
237   - end
238   -
239   - xit "can provide the source files of all the subspecs" do
240   - sources = @pod.all_specs_source_files.map { |p| p.relative_path_from(@sandbox.root).to_s }
241   - sources.should == %w[ s1.h s1.m s2.h s2.m ]
  111 + @sandbox = temporary_sandbox
  112 + subspecs = fixture_spec('chameleon/Chameleon.podspec').subspecs
  113 + @pod = Pod::LocalPod.new(subspecs[0], @sandbox, Pod::Platform.new(:osx))
  114 + @pod.add_specification(subspecs[1])
  115 + copy_fixture_to_pod('chameleon', @pod)
  116 + end
  117 +
  118 + it "identifies the top level specification" do
  119 + @pod.top_specification.name.should == 'Chameleon'
  120 + end
  121 +
  122 + it "returns the subspecs" do
  123 + @pod.specifications.map(&:name).should == %w[ Chameleon/UIKit Chameleon/StoreKit ]
  124 + end
  125 +
  126 + it "resolve the source files" do
  127 + computed = @pod.relative_source_files.map(&:to_s)
  128 + expected = %w[
  129 + Chameleon/UIKit/Classes/UIKit.h
  130 + Chameleon/UIKit/Classes/UIView.h
  131 + Chameleon/UIKit/Classes/UIWindow.h
  132 + Chameleon/UIKit/Classes/UIView.m
  133 + Chameleon/UIKit/Classes/UIWindow.m
  134 + Chameleon/StoreKit/Classes/SKPayment.h
  135 + Chameleon/StoreKit/Classes/StoreKit.h
  136 + Chameleon/StoreKit/Classes/SKPayment.m ]
  137 +
  138 + assert_array_equals(expected, computed)
  139 + end
  140 +
  141 + it "resolve the resources" do
  142 + @pod.relative_resource_files.map(&:to_s).sort.should == [
  143 + "Chameleon/UIKit/Resources/<UITabBar> background.png",
  144 + "Chameleon/UIKit/Resources/<UITabBar> background@2x.png" ]
  145 + end
  146 +
  147 + it "resolve the clean paths" do
  148 + # fake_git serves to check that source control files are deleted
  149 + expected = %w[
  150 + /.fake_git
  151 + /.fake_git/branches
  152 + /.fake_git/HEAD
  153 + /.fake_git/index
  154 + /AddressBookUI
  155 + /AddressBookUI/AddressBookUI_Prefix.pch
  156 + /AddressBookUI/Classes
  157 + /AddressBookUI/Classes/ABUnknownPersonViewController.h
  158 + /AddressBookUI/Classes/ABUnknownPersonViewController.m
  159 + /AddressBookUI/Classes/AddressBookUI.h
  160 + /AssetsLibrary
  161 + /AssetsLibrary/AssetsLibrary_Prefix.pch
  162 + /AssetsLibrary/Classes
  163 + /AssetsLibrary/Classes/ALAsset.h
  164 + /AssetsLibrary/Classes/ALAsset.m
  165 + /AssetsLibrary/Classes/ALAssetRepresentation.h
  166 + /AssetsLibrary/Classes/ALAssetRepresentation.m
  167 + /AssetsLibrary/Classes/ALAssetsFilter.h
  168 + /AssetsLibrary/Classes/ALAssetsFilter.m
  169 + /AssetsLibrary/Classes/ALAssetsGroup.h
  170 + /AssetsLibrary/Classes/ALAssetsGroup.m
  171 + /AssetsLibrary/Classes/ALAssetsLibrary.h
  172 + /AssetsLibrary/Classes/ALAssetsLibrary.m
  173 + /AssetsLibrary/Classes/AssetsLibrary.h
  174 + /AVFoundation
  175 + /AVFoundation/AVFoundation_Prefix.pch
  176 + /AVFoundation/Classes
  177 + /AVFoundation/Classes/AVAudioPlayer.h
  178 + /AVFoundation/Classes/AVAudioPlayer.m
  179 + /AVFoundation/Classes/AVAudioSession.h
  180 + /AVFoundation/Classes/AVAudioSession.m
  181 + /AVFoundation/Classes/AVFoundation.h
  182 + /MediaPlayer
  183 + /MediaPlayer/Classes
  184 + /MediaPlayer/Classes/MediaPlayer.h
  185 + /MediaPlayer/Classes/MPMediaPlayback.h
  186 + /MediaPlayer/Classes/MPMoviePlayerController.h
  187 + /MediaPlayer/Classes/MPMoviePlayerController.m
  188 + /MediaPlayer/Classes/MPMusicPlayerController.h
  189 + /MediaPlayer/Classes/MPMusicPlayerController.m
  190 + /MediaPlayer/Classes/UIInternalMovieView.h
  191 + /MediaPlayer/Classes/UIInternalMovieView.m
  192 + /MediaPlayer/MediaPlayer_Prefix.pch
  193 + /MessageUI
  194 + /MessageUI/Classes
  195 + /MessageUI/Classes/MessageUI.h
  196 + /MessageUI/Classes/MFMailComposeViewController.h
  197 + /MessageUI/Classes/MFMailComposeViewController.m
  198 + /MessageUI/MessageUI_Prefix.pch
  199 + /StoreKit/StoreKit_Prefix.pch
  200 + /UIKit/UIKit_Prefix.pch
  201 + ]
  202 + computed = @pod.clean_paths.each{ |p| p.gsub!(@pod.root.to_s, '') }
  203 + assert_array_equals(expected, computed)
  204 + end
  205 +
  206 + it "resolves the used files" do
  207 + expected = %w[
  208 + /UIKit/Classes/UIKit.h
  209 + /UIKit/Classes/UIView.h
  210 + /UIKit/Classes/UIWindow.h
  211 + /UIKit/Classes/UIView.m
  212 + /UIKit/Classes/UIWindow.m
  213 + /StoreKit/Classes/SKPayment.h
  214 + /StoreKit/Classes/StoreKit.h
  215 + /StoreKit/Classes/SKPayment.m
  216 + /Chameleon.podspec
  217 + /README.md
  218 + /LICENSE
  219 + ] + [
  220 + "/UIKit/Resources/<UITabBar> background.png",
  221 + "/UIKit/Resources/<UITabBar> background@2x.png"
  222 + ]
  223 + computed = @pod.used_files.map{ |p| p.gsub!(@pod.root.to_s, '').to_s }
  224 + assert_array_equals(expected, computed)
  225 + end
  226 +
  227 +
  228 + it "resolved the header files" do
  229 + expected = %w[
  230 + Chameleon/UIKit/Classes/UIKit.h
  231 + Chameleon/UIKit/Classes/UIView.h
  232 + Chameleon/UIKit/Classes/UIWindow.h
  233 + Chameleon/StoreKit/Classes/SKPayment.h
  234 + Chameleon/StoreKit/Classes/StoreKit.h ]
  235 + computed = @pod.relative_header_files.map(&:to_s)
  236 + assert_array_equals(expected, computed)
  237 + end
  238 +
  239 + it "resolves the header files of **every** subspec" do
  240 + computed = @pod.all_specs_public_header_files.map { |p| p.relative_path_from(@pod.root).to_s }
  241 + expected = %w[
  242 + UIKit/Classes/UIKit.h
  243 + UIKit/Classes/UIView.h
  244 + UIKit/Classes/UIWindow.h
  245 + StoreKit/Classes/SKPayment.h
  246 + StoreKit/Classes/StoreKit.h
  247 + MessageUI/Classes/MessageUI.h
  248 + MessageUI/Classes/MFMailComposeViewController.h
  249 + MediaPlayer/Classes/MediaPlayer.h
  250 + MediaPlayer/Classes/MPMediaPlayback.h
  251 + MediaPlayer/Classes/MPMoviePlayerController.h
  252 + MediaPlayer/Classes/MPMusicPlayerController.h
  253 + MediaPlayer/Classes/UIInternalMovieView.h
  254 + AVFoundation/Classes/AVAudioPlayer.h
  255 + AVFoundation/Classes/AVAudioSession.h
  256 + AVFoundation/Classes/AVFoundation.h
  257 + AssetsLibrary/Classes/ALAsset.h
  258 + AssetsLibrary/Classes/ALAssetRepresentation.h
  259 + AssetsLibrary/Classes/ALAssetsFilter.h
  260 + AssetsLibrary/Classes/ALAssetsGroup.h
  261 + AssetsLibrary/Classes/ALAssetsLibrary.h
  262 + AssetsLibrary/Classes/AssetsLibrary.h
  263 + ]
  264 + assert_array_equals(expected, computed)
  265 + end
  266 +
  267 + it "merges the xcconfigs without duplicates" do
  268 + @pod.xcconfig.should == {
  269 + "OTHER_LDFLAGS"=>"-framework AppKit -framework Foundation -framework IOKit -framework QTKit -framework QuartzCore -framework SystemConfiguration -framework WebKit" }
  270 + end
  271 +
  272 + it "returns a hash of mappings with a custom header dir prefix" do
  273 + mappings = @pod.send(:header_mappings)
  274 + mappings = mappings.map do |folder, headers|
  275 + "#{folder} > #{headers.sort.map{ |p| p.relative_path_from(@pod.root).to_s }.join(' ')}"
  276 + end
  277 + mappings.sort.should == [
  278 + "Chameleon/StoreKit > StoreKit/Classes/SKPayment.h StoreKit/Classes/StoreKit.h",
  279 + "Chameleon/UIKit > UIKit/Classes/UIKit.h UIKit/Classes/UIView.h UIKit/Classes/UIWindow.h" ]
242 280 end
243 281
244   - xit 'can clean the unused files' do
245   - # copy fixture to another folder
246   - @pod.clean
247   - @pod.clean_paths.tap do |paths|
248   - paths.each do |path|
249   - path.should.not.exist
250   - end
  282 + it "respects the headers excluded from the search paths" do
  283 + @pod.stubs(:headers_excluded_from_search_paths).returns([@pod.root + 'UIKit/Classes/UIKit.h'])
  284 + mappings = @pod.send(:header_mappings)
  285 + mappings = mappings.map do |folder, headers|
  286 + "#{folder} > #{headers.sort.map{ |p| p.relative_path_from(@pod.root).to_s }.join(' ')}"
251 287 end
  288 + mappings.sort.should == [
  289 + "Chameleon/StoreKit > StoreKit/Classes/SKPayment.h StoreKit/Classes/StoreKit.h",
  290 + "Chameleon/UIKit > UIKit/Classes/UIView.h UIKit/Classes/UIWindow.h" ]
252 291 end
253 292
  293 + it "includes the sandbox of the pod's headers while linking" do
  294 + @sandbox.expects(:add_header_search_path).with(Pathname.new('Chameleon'))
  295 + @pod.link_headers
  296 + end
254 297 end
255 298 end

0 comments on commit 16a324a

Please sign in to comment.
Something went wrong with that request. Please try again.