cocoapods 0.16.4 → 0.17.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +108 -0
  3. data/README.md +3 -3
  4. data/bin/pod +1 -1
  5. data/lib/cocoapods.rb +31 -31
  6. data/lib/cocoapods/command.rb +62 -107
  7. data/lib/cocoapods/command/inter_process_communication.rb +103 -0
  8. data/lib/cocoapods/command/list.rb +45 -44
  9. data/lib/cocoapods/command/outdated.rb +28 -25
  10. data/lib/cocoapods/command/project.rb +90 -0
  11. data/lib/cocoapods/command/push.rb +50 -32
  12. data/lib/cocoapods/command/repo.rb +125 -155
  13. data/lib/cocoapods/command/search.rb +23 -12
  14. data/lib/cocoapods/command/setup.rb +103 -64
  15. data/lib/cocoapods/command/spec.rb +329 -90
  16. data/lib/cocoapods/config.rb +197 -44
  17. data/lib/cocoapods/downloader.rb +47 -34
  18. data/lib/cocoapods/executable.rb +98 -41
  19. data/lib/cocoapods/external_sources.rb +325 -0
  20. data/lib/cocoapods/file_list.rb +8 -1
  21. data/lib/cocoapods/gem_version.rb +7 -0
  22. data/lib/cocoapods/generator/acknowledgements.rb +71 -7
  23. data/lib/cocoapods/generator/acknowledgements/markdown.rb +10 -9
  24. data/lib/cocoapods/generator/acknowledgements/plist.rb +9 -8
  25. data/lib/cocoapods/generator/copy_resources_script.rb +2 -2
  26. data/lib/cocoapods/generator/documentation.rb +153 -37
  27. data/lib/cocoapods/generator/prefix_header.rb +82 -0
  28. data/lib/cocoapods/generator/target_header.rb +58 -0
  29. data/lib/cocoapods/generator/xcconfig.rb +130 -0
  30. data/lib/cocoapods/hooks/installer_representation.rb +123 -0
  31. data/lib/cocoapods/hooks/library_representation.rb +79 -0
  32. data/lib/cocoapods/hooks/pod_representation.rb +74 -0
  33. data/lib/cocoapods/installer.rb +398 -147
  34. data/lib/cocoapods/installer/analyzer.rb +556 -0
  35. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +253 -0
  36. data/lib/cocoapods/installer/file_references_installer.rb +179 -0
  37. data/lib/cocoapods/installer/pod_source_installer.rb +289 -0
  38. data/lib/cocoapods/installer/target_installer.rb +307 -112
  39. data/lib/cocoapods/installer/user_project_integrator.rb +140 -176
  40. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +193 -0
  41. data/lib/cocoapods/library.rb +195 -0
  42. data/lib/cocoapods/open_uri.rb +16 -14
  43. data/lib/cocoapods/project.rb +175 -52
  44. data/lib/cocoapods/resolver.rb +151 -164
  45. data/lib/cocoapods/sandbox.rb +276 -54
  46. data/lib/cocoapods/sandbox/file_accessor.rb +210 -0
  47. data/lib/cocoapods/sandbox/headers_store.rb +96 -0
  48. data/lib/cocoapods/sandbox/path_list.rb +178 -0
  49. data/lib/cocoapods/sources_manager.rb +218 -0
  50. data/lib/cocoapods/user_interface.rb +82 -18
  51. data/lib/cocoapods/{command → user_interface}/error_report.rb +5 -5
  52. data/lib/cocoapods/validator.rb +379 -0
  53. metadata +74 -55
  54. data/lib/cocoapods/command/install.rb +0 -55
  55. data/lib/cocoapods/command/linter.rb +0 -317
  56. data/lib/cocoapods/command/update.rb +0 -25
  57. data/lib/cocoapods/dependency.rb +0 -285
  58. data/lib/cocoapods/downloader/git.rb +0 -276
  59. data/lib/cocoapods/downloader/http.rb +0 -99
  60. data/lib/cocoapods/downloader/mercurial.rb +0 -26
  61. data/lib/cocoapods/downloader/subversion.rb +0 -42
  62. data/lib/cocoapods/local_pod.rb +0 -620
  63. data/lib/cocoapods/lockfile.rb +0 -274
  64. data/lib/cocoapods/platform.rb +0 -127
  65. data/lib/cocoapods/podfile.rb +0 -551
  66. data/lib/cocoapods/source.rb +0 -223
  67. data/lib/cocoapods/specification.rb +0 -579
  68. data/lib/cocoapods/specification/set.rb +0 -175
  69. data/lib/cocoapods/specification/statistics.rb +0 -112
  70. data/lib/cocoapods/user_interface/ui_pod.rb +0 -130
  71. data/lib/cocoapods/version.rb +0 -26
@@ -1,99 +0,0 @@
1
- require 'open-uri'
2
- require 'tempfile'
3
- require 'zlib'
4
- require 'yaml'
5
-
6
- module Pod
7
- class Downloader
8
- class Http < Downloader
9
- class UnsupportedFileTypeError < StandardError; end
10
-
11
- executable :curl
12
- executable :unzip
13
- executable :tar
14
-
15
- attr_accessor :filename, :download_path
16
- def download
17
- @filename = filename_with_type type
18
- @download_path = target_path + @filename
19
- UI.section(' > Downloading from HTTP', '', 3) do
20
- download_file @download_path
21
- extract_with_type @download_path, type
22
- end
23
- end
24
-
25
- def type
26
- options[:type] || type_with_url(url)
27
- end
28
-
29
- def should_flatten?
30
- if options.has_key? :flatten
31
- options[:flatten] # spec file can always override
32
- elsif [:tgz, :tar, :tbz].include? type
33
- true # those archives flatten by default
34
- else
35
- false # all others (actually only .zip) default not to flatten
36
- end
37
- end
38
-
39
- private
40
- def type_with_url(url)
41
- if url =~ /.zip$/
42
- :zip
43
- elsif url =~ /.(tgz|tar\.gz)$/
44
- :tgz
45
- elsif url =~ /.tar$/
46
- :tar
47
- elsif url =~ /.(tbz|tar\.bz2)$/
48
- :tbz
49
- else
50
- nil
51
- end
52
- end
53
-
54
- def filename_with_type(type=:zip)
55
- case type
56
- when :zip
57
- "file.zip"
58
- when :tgz
59
- "file.tgz"
60
- when :tar
61
- "file.tar"
62
- when :tbz
63
- "file.tbz"
64
- else
65
- raise UnsupportedFileTypeError.new "Unsupported file type: #{type}"
66
- end
67
- end
68
-
69
- def download_file(full_filename)
70
- curl! "-L -o '#{full_filename}' '#{url}'"
71
- end
72
-
73
- def extract_with_type(full_filename, type=:zip)
74
- case type
75
- when :zip
76
- unzip! "'#{full_filename}' -d '#{target_path}'"
77
- when :tgz
78
- tar! "xfz '#{full_filename}' -C '#{target_path}'"
79
- when :tar
80
- tar! "xf '#{full_filename}' -C '#{target_path}'"
81
- when :tbz
82
- tar! "xfj '#{full_filename}' -C '#{target_path}'"
83
- else
84
- raise UnsupportedFileTypeError.new "Unsupported file type: #{type}"
85
- end
86
-
87
- if should_flatten?
88
- contents = target_path.children
89
- contents.delete(full_filename)
90
- entry = contents.first
91
- if contents.count == 1 && entry.directory?
92
- FileUtils.move(entry.children, target_path)
93
- end
94
- end
95
- end
96
-
97
- end
98
- end
99
- end
@@ -1,26 +0,0 @@
1
- module Pod
2
- class Downloader
3
- class Mercurial < Downloader
4
- executable :hg
5
-
6
- def download
7
- UI.section(' > Cloning mercurial repo', '', 3) do
8
- if options[:revision]
9
- download_revision
10
- else
11
- download_head
12
- end
13
- end
14
- end
15
-
16
- def download_head
17
- hg! "clone \"#{url}\" \"#{target_path}\""
18
- end
19
-
20
- def download_revision
21
- hg! "clone \"#{url}\" --rev '#{options[:revision]}' \"#{target_path}\""
22
- end
23
- end
24
- end
25
- end
26
-
@@ -1,42 +0,0 @@
1
- module Pod
2
- class Downloader
3
- class Subversion < Downloader
4
- executable :svn
5
-
6
- def initialize(target_path, url, options)
7
- @target_path, @url, @options = target_path, url, options
8
- end
9
-
10
- def download
11
- UI.section(' > Exporting subversion repo', '', 3) do
12
- svn! %|#{export_subcommand} "#{reference_url}" "#{target_path}"|
13
- end
14
- end
15
-
16
- def download_head
17
- UI.section(' > Exporting subversion repo', '', 3) do
18
- svn! %|#{export_subcommand} "#{trunk_url}" "#{target_path}"|
19
- end
20
- end
21
-
22
- def export_subcommand
23
- result = 'export --non-interactive --trust-server-cert'
24
- end
25
-
26
- def reference_url
27
- result = url.dup
28
- result << '/' << options[:folder] if options[:folder]
29
- result << '/tags/' << options[:tag] if options[:tag]
30
- result << '" -r "' << options[:revision] if options[:revision]
31
- result
32
- end
33
-
34
- def trunk_url
35
- result = url.dup
36
- result << '/' << options[:folder] if options[:folder]
37
- result << '/trunk'
38
- result
39
- end
40
- end
41
- end
42
- end
@@ -1,620 +0,0 @@
1
- module Pod
2
-
3
- # A {LocalPod} interfaces one or more specifications belonging to one pod
4
- # (a library) and their concrete instance in the file system.
5
- #
6
- # The {LocalPod} is responsible for orchestrating the activated
7
- # specifications of a single pod. Specifically, it keeps track of the
8
- # activated specifications and handles issues related to duplicates
9
- # files.
10
- # Inheritance logic belongs to the {Specification} class.
11
- #
12
- # The activated specifications are used to compute the paths that can be
13
- # safely cleaned by the pod.
14
- #
15
- # @example
16
- # pod = LocalPod.new 'RestKit/Networking'
17
- # pod.add_specification 'RestKit/UI'
18
- #
19
- # @note
20
- # Unless otherwise specified in the name of the method the {LocalPod}
21
- # returns absolute paths.
22
- #
23
- class LocalPod
24
-
25
- # @return [Specification] The specification that describes the pod.
26
- #
27
- attr_reader :top_specification
28
-
29
- # @return [Specification] The activated specifications of the pod.
30
- #
31
- attr_reader :specifications
32
-
33
- # @return [Sandbox] The sandbox where the pod is installed.
34
- #
35
- attr_reader :sandbox
36
-
37
- # @return [Platform] The platform that will be used to build the pod.
38
- #
39
- attr_reader :platform
40
-
41
- # @return [Boolean] Wether or not the pod has been downloaded in the
42
- # current install process and still needs its docs
43
- # generated and be cleaned.
44
- #
45
- attr_accessor :downloaded
46
- alias_method :downloaded?, :downloaded
47
-
48
- # @param [Specification] specification The first activated specification
49
- # of the pod.
50
- #
51
- # @param [Sandbox] sandbox The sandbox where the files of the
52
- # pod will be located.
53
- #
54
- # @param [Platform] platform The platform that will be used to
55
- # build the pod.
56
- #
57
- # @todo The local pod should be initialized with all the activated
58
- # specifications passed as an array, in order to be able to cache the
59
- # computed values. In other words, it should be immutable.
60
- #
61
- def initialize(specification, sandbox, platform)
62
- @top_specification, @sandbox, @platform = specification.top_level_parent, sandbox, platform
63
- @top_specification.activate_platform(platform)
64
- @specifications = [] << specification
65
- end
66
-
67
- # Initializes a local pod from the top specification of a podspec file.
68
- #
69
- # @return [LocalPod] A new local pod.
70
- #
71
- def self.from_podspec(podspec, sandbox, platform)
72
- new(Specification.from_file(podspec), sandbox, platform)
73
- end
74
-
75
- # Activates a specification or subspecs for the pod.
76
- # Adding specifications is idempotent.
77
- #
78
- # @param {Specification} spec The specification to add to the pod.
79
- #
80
- # @raise {Informative} If the specification is not part of the same pod.
81
- #
82
- def add_specification(spec)
83
- unless spec.top_level_parent == top_specification
84
- raise Informative,
85
- "[Local Pod] Attempt to add a specification from another pod"
86
- end
87
- spec.activate_platform(platform)
88
- @specifications << spec unless @specifications.include?(spec)
89
- end
90
-
91
- # @return [Pathname] The root directory of the pod
92
- #
93
- def root
94
- @sandbox.root + top_specification.name
95
- end
96
-
97
- # @return [String] A string representation of the pod which indicates if
98
- # the pods comes from a local source or has a preferred
99
- # dependency.
100
- #
101
- def to_s
102
- s = top_specification.to_s
103
- s << " defaulting to #{top_specification.preferred_dependency} subspec" if top_specification.preferred_dependency
104
- s
105
- end
106
-
107
- # @return [String] The name of the Pod.
108
- #
109
- def name
110
- top_specification.name
111
- end
112
-
113
- # @!group Installation
114
-
115
- # Creates the root path of the pod.
116
- #
117
- # @return [void]
118
- #
119
- def create
120
- root.mkpath unless exists?
121
- end
122
-
123
- # Whether the root path of the pod exists.
124
- #
125
- def exists?
126
- root.exist?
127
- end
128
-
129
- # Executes a block in the root directory of the Pod.
130
- #
131
- # @return [void]
132
- #
133
- def chdir(&block)
134
- create
135
- Dir.chdir(root, &block)
136
- end
137
-
138
- # Deletes the pod from the file system.
139
- #
140
- # @return [void]
141
- #
142
- def implode
143
- root.rmtree if exists?
144
- end
145
-
146
- def local?
147
- false
148
- end
149
-
150
- # @!group Cleaning
151
-
152
- # Deletes any path that is not used by the pod.
153
- #
154
- # @return [void]
155
- #
156
- def clean!
157
- clean_paths.each { |path| FileUtils.rm_rf(path) }
158
- @cleaned = true
159
- end
160
-
161
- # Finds the absolute paths, including hidden ones, of the files
162
- # that are not used by the pod and thus can be safely deleted.
163
- #
164
- # @return [Array<Strings>] The paths that can be deleted.
165
- #
166
- # @note Implementation detail: Don't use Dir#glob as there is an
167
- # unexplained issue (#568, #572 and #602).
168
- #
169
- def clean_paths
170
- cached_used = used_files
171
- files = Pathname.glob(root + "**/*", File::FNM_DOTMATCH | File::FNM_CASEFOLD).map(&:to_s)
172
-
173
- files.reject! do |candidate|
174
- candidate.end_with?('.', '..') || cached_used.any? do |path|
175
- path.include?(candidate) || candidate.include?(path)
176
- end
177
- end
178
- files
179
- end
180
-
181
- # @return [Array<String>] The absolute path of the files used by the pod.
182
- #
183
- def used_files
184
- files = [ source_files, resource_files, preserve_files, readme_file, license_file, prefix_header_file ]
185
- files.compact!
186
- files.flatten!
187
- files.map!{ |path| path.to_s }
188
- files
189
- end
190
-
191
- # @!group Files
192
-
193
- # @return [Pathname] Returns the relative path from the sandbox.
194
- #
195
- # @note If the two abosule paths don't share the same root directory an
196
- # extra `../` is added to the result of {Pathname#relative_path_from}
197
- #
198
- # path = Pathname.new('/Users/dir')
199
- # @sandbox
200
- # #=> Pathname('/tmp/CocoaPods/Lint/Pods')
201
- #
202
- # p.relative_path_from(@sandbox
203
- # #=> '../../../../Users/dir'
204
- #
205
- # relativize_from_sandbox(path)
206
- # #=> '../../../../../Users/dir'
207
- #
208
- def relativize_from_sandbox(path)
209
- result = path.relative_path_from(@sandbox.root)
210
- result = Pathname.new('../') + result unless @sandbox.root.to_s.split('/')[1] == path.to_s.split('/')[1]
211
- result
212
- end
213
-
214
- # @return [Array<Pathname>] The paths of the source files.
215
- #
216
- def source_files
217
- source_files_by_spec.values.flatten
218
- end
219
-
220
- # @return [Array<Pathname>] The *relative* paths of the source files.
221
- #
222
- def relative_source_files
223
- source_files.map{ |p| relativize_from_sandbox(p) }
224
- end
225
-
226
- def relative_source_files_by_spec
227
- result = {}
228
- source_files_by_spec.each do |spec, paths|
229
- result[spec] = paths.map{ |p| relativize_from_sandbox(p) }
230
- end
231
- result
232
- end
233
-
234
-
235
- # Finds the source files that every activated {Specification} requires.
236
- #
237
- # @note If the same file is required by two specifications the one at the
238
- # higher level in the inheritance chain wins.
239
- #
240
- # @return [Hash{Specification => Array<Pathname>}] The files grouped by
241
- # {Specification}.
242
- #
243
- def source_files_by_spec
244
- options = {:glob => '*.{h,hpp,hh,m,mm,c,cpp}'}
245
- paths_by_spec(:source_files, options)
246
- end
247
-
248
- # @return [Array<Pathname>] The paths of the header files.
249
- #
250
- def header_files
251
- header_files_by_spec.values.flatten
252
- end
253
-
254
- # @return [Array<Pathname>] The *relative* paths of the source files.
255
- #
256
- def relative_header_files
257
- header_files.map{ |p| relativize_from_sandbox(p) }
258
- end
259
-
260
- # @return [Hash{Specification => Array<Pathname>}] The paths of the header
261
- # files grouped by {Specification}.
262
- #
263
- def header_files_by_spec
264
- result = {}
265
- source_files_by_spec.each do |spec, paths|
266
- headers = paths.select { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
267
- result[spec] = headers unless headers.empty?
268
- end
269
- result
270
- end
271
-
272
- # @return [Hash{Specification => Array<Pathname>}] The paths of the header
273
- # files grouped by {Specification} that should be copied in the public
274
- # folder.
275
- #
276
- # If a spec does not match any public header it means that all the
277
- # header files (i.e. the build ones) are intended to be public.
278
- #
279
- def public_header_files_by_spec
280
- public_headers = paths_by_spec(:public_header_files, :glob => '*.{h,hpp,hh}')
281
- build_headers = header_files_by_spec
282
-
283
- result = {}
284
- specifications.each do |spec|
285
- if (public_h = public_headers[spec]) && !public_h.empty?
286
- result[spec] = public_h
287
- elsif (build_h = build_headers[spec]) && !build_h.empty?
288
- result[spec] = build_h
289
- end
290
- end
291
- result
292
- end
293
-
294
- # @return [Array<Pathname>] The paths of the resources.
295
- #
296
- def resource_files
297
- paths_by_spec(:resources).values.flatten
298
- end
299
-
300
- # @return [Array<Pathname>] The *relative* paths of the resources.
301
- #
302
- def relative_resource_files
303
- resource_files.map{ |p| relativize_from_sandbox(p) }
304
- end
305
-
306
- # @return [Pathname] The absolute path of the prefix header file
307
- #
308
- def prefix_header_file
309
- root + top_specification.prefix_header_file if top_specification.prefix_header_file
310
- end
311
-
312
- # @return [Array<Pathname>] The absolute paths of the files of the pod
313
- # that should be preserved.
314
- #
315
- def preserve_files
316
- paths = paths_by_spec(:preserve_paths).values
317
- paths += expanded_paths(%w[ *.podspec notice* NOTICE* CREDITS* ])
318
- paths.compact!
319
- paths.uniq!
320
- paths
321
- end
322
-
323
- # @return [Pathname] The automatically detected absolute path of the README
324
- # file.
325
- #
326
- def readme_file
327
- expanded_paths(%w[ readme{*,.*} ]).first
328
- end
329
-
330
- # @return [Pathname] The absolute path of the license file from the
331
- # specification or automatically detected.
332
- #
333
- def license_file
334
- if top_specification.license && top_specification.license[:file]
335
- root + top_specification.license[:file]
336
- else
337
- expanded_paths(%w[ licen{c,s}e{*,.*} ]).first
338
- end
339
- end
340
-
341
- # @return [String] The text of the license of the pod from the
342
- # specification or from the license file.
343
- #
344
- def license_text
345
- if (license_hash = top_specification.license)
346
- if (result = license_hash[:text])
347
- result
348
- elsif license_file
349
- result = IO.read(license_file)
350
- end
351
- end
352
- end
353
-
354
- def xcconfig
355
- specifications.map { |s| s.xcconfig }.reduce(:merge)
356
- end
357
-
358
- # Computes the paths of all the public headers of the pod including every
359
- # subspec (activated or not).
360
- # For this reason the pod must not be cleaned when calling this command.
361
- #
362
- # This method is used by {Generator::Documentation}.
363
- #
364
- # @raise [Informative] If the pod was cleaned.
365
- #
366
- # @return [Array<Pathname>] The path of all the public headers of the pod.
367
- #
368
- def documentation_headers
369
- if @cleaned
370
- raise Informative, "The pod is cleaned and cannot compute the " \
371
- "header files, as some might have been deleted."
372
- end
373
-
374
- specs = [top_specification] + top_specification.recursive_subspecs
375
- source_files = paths_by_spec(:source_files, { :glob => '*.{h}'}, specs)
376
- public_headers = paths_by_spec(:public_header_files,{ :glob => '*.{h}'}, specs)
377
-
378
- result = []
379
- specs.each do |spec|
380
- if (public_h = public_headers[spec]) && !public_h.empty?
381
- result += public_h
382
- elsif (source_f = source_files[spec]) && !source_f.empty?
383
- build_h = source_f.select { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
384
- result += build_h unless build_h.empty?
385
- end
386
- end
387
- result
388
- end
389
-
390
- # @!group Xcodeproj integration
391
-
392
- # Adds the file references, to the given `Pods.xcodeproj` project, for the
393
- # source files of the pod. The file references are grouped by specification
394
- # and stored in {#file_references_by_spec}.
395
- #
396
- # @note If the pod is locally sourced the file references are stored in the
397
- # `Local Pods` group otherwise they are stored in the `Pods` group.
398
- #
399
- # @return [void]
400
- #
401
- def add_file_references_to_project(project)
402
- @file_references_by_spec = {}
403
- parent_group = local? ? project.local_pods : project.pods
404
-
405
- relative_source_files_by_spec.each do |spec, paths|
406
- group = project.add_spec_group(spec.name, parent_group)
407
- file_references = []
408
- paths.each do |path|
409
- file_references << group.new_file(path)
410
- end
411
- @file_references_by_spec[spec] = file_references
412
- end
413
- end
414
-
415
- # @return [Hash{Specification => Array<PBXFileReference>}] The file
416
- # references of the pod in the `Pods.xcodeproj` project.
417
- #
418
- attr_reader :file_references_by_spec
419
-
420
- # Adds a build file for each file reference to a given target taking into
421
- # account the compiler flags of the corresponding specification.
422
- #
423
- # @raise If the {#add_file_references_to_project} was not called before of
424
- # calling this method.
425
- #
426
- # @return [void]
427
- #
428
- def add_build_files_to_target(target)
429
- unless file_references_by_spec
430
- raise Informative, "Local Pod needs to add the file references to the " \
431
- "project before adding the build files to the target."
432
- end
433
- file_references_by_spec.each do |spec, file_reference|
434
- target.add_file_references(file_reference, spec.compiler_flags.strip)
435
- end
436
- end
437
-
438
- # @return [void] Copies the pods headers to the sandbox.
439
- #
440
- def link_headers
441
- @sandbox.build_headers.add_search_path(headers_sandbox)
442
- @sandbox.public_headers.add_search_path(headers_sandbox)
443
-
444
- header_mappings(header_files_by_spec).each do |namespaced_path, files|
445
- @sandbox.build_headers.add_files(namespaced_path, files)
446
- end
447
-
448
- header_mappings(public_header_files_by_spec).each do |namespaced_path, files|
449
- @sandbox.public_headers.add_files(namespaced_path, files)
450
- end
451
- end
452
-
453
- # @return Whether the pod requires ARC.
454
- #
455
- # TODO: this should be not used anymore.
456
- #
457
- def requires_arc?
458
- top_specification.requires_arc
459
- end
460
-
461
- private
462
-
463
- # @return [Array<Pathname>] The implementation files
464
- # (the files the need to compiled) of the pod.
465
- #
466
- def implementation_files
467
- relative_source_files.reject { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
468
- end
469
-
470
- # @return [Pathname] The path of the pod relative from the sandbox.
471
- #
472
- def relative_root
473
- root.relative_path_from(@sandbox.root)
474
- end
475
-
476
- # @return Hash{Pathname => [Array<Pathname>]} A hash containing the headers
477
- # folders as the keys and the the absolute paths of the header files
478
- # as the values.
479
- #
480
- # @todo this is being overridden in the RestKit 0.9.4 spec, need to do
481
- # something with that, and this method also still exists in Specification.
482
- #
483
- # @todo This is not overridden anymore in specification refactor and the
484
- # code Pod::Specification#copy_header_mapping can be moved here.
485
- def header_mappings(files_by_spec)
486
- mappings = {}
487
- files_by_spec.each do |spec, paths|
488
- paths = paths - headers_excluded_from_search_paths
489
- dir = spec.header_dir ? (headers_sandbox + spec.header_dir) : headers_sandbox
490
- paths.each do |from|
491
- from_relative = from.relative_path_from(root)
492
- to = dir + spec.copy_header_mapping(from_relative)
493
- (mappings[to.dirname] ||= []) << from
494
- end
495
- end
496
- mappings
497
- end
498
-
499
- # @return <Pathname> The name of the folder where the headers of this pod
500
- # will be namespaced.
501
- #
502
- def headers_sandbox
503
- @headers_sandbox ||= Pathname.new(top_specification.name)
504
- end
505
-
506
- # @return [<Pathname>] The relative path of the headers that should not be
507
- # included in the linker search paths.
508
- #
509
- def headers_excluded_from_search_paths
510
- options = { :glob => '*.{h,hpp,hh}' }
511
- paths = paths_by_spec(:exclude_header_search_paths, options)
512
- paths.values.compact.uniq
513
- end
514
-
515
- # @!group Paths Patterns
516
-
517
- # The paths obtained by resolving the patterns of an attribute
518
- # groupped by spec.
519
- #
520
- # @param [Symbol] accessor The accessor to use to obtain the paths patterns.
521
- # @param [Hash] options (see #expanded_paths)
522
- #
523
- def paths_by_spec(accessor, options = {}, specs = nil)
524
- specs ||= specifications
525
- paths_by_spec = {}
526
- processed_paths = []
527
-
528
- specs = specs.sort_by { |s| s.name.length }
529
- specs.each do |spec|
530
- paths = expanded_paths(spec.send(accessor), options)
531
- unless paths.empty?
532
- paths_by_spec[spec] = paths - processed_paths
533
- processed_paths += paths
534
- end
535
- end
536
- paths_by_spec
537
- end
538
-
539
- # Converts patterns of paths to the {Pathname} of the files present in the
540
- # pod.
541
- #
542
- # @param [String, FileList, Array<String, Pathname>] patterns
543
- # The patterns to expand.
544
- # @param [Hash] options
545
- # The options to used for expanding the paths patterns.
546
- # @option options [String] :glob
547
- # The pattern to use for globing directories.
548
- #
549
- # @raise [Informative] If the pod does not exists.
550
- #
551
- # @todo implement case insensitive search
552
- #
553
- # @return [Array<Pathname>] A list of the paths.
554
- #
555
- def expanded_paths(patterns, options = {})
556
- unless exists?
557
- raise Informative, "[Local Pod] Attempt to resolve paths for nonexistent pod.\n" \
558
- "\tSpecifications: #{@specifications.inspect}\n" \
559
- "\t Patterns: #{patterns.inspect}\n" \
560
- "\t Options: #{options.inspect}"
561
- end
562
-
563
- return [] if patterns.empty?
564
- patterns = [ patterns ] if patterns.is_a?(String)
565
- file_lists = patterns.select { |p| p.is_a?(FileList) }
566
- glob_patterns = patterns - file_lists
567
-
568
- result = []
569
-
570
- result << file_lists.map do |file_list|
571
- file_list.prepend_patterns(root)
572
- file_list.glob
573
- end
574
-
575
- result << glob_patterns.map do |pattern|
576
- pattern = root + pattern
577
- if pattern.directory? && options[:glob]
578
- pattern += options[:glob]
579
- end
580
- Pathname.glob(pattern, File::FNM_CASEFOLD)
581
- end.flatten
582
-
583
- result.flatten.compact.uniq
584
- end
585
-
586
- # A {LocalSourcedPod} is a {LocalPod} that interacts with the files of
587
- # a folder controlled by the users. As such this class does not alter
588
- # in any way the contents of the folder.
589
- #
590
- class LocalSourcedPod < LocalPod
591
- def downloaded?
592
- true
593
- end
594
-
595
- def create
596
- # No ops
597
- end
598
-
599
- def root
600
- @root ||= Pathname.new(@top_specification.source[:local]).expand_path
601
- end
602
-
603
- def implode
604
- # No ops
605
- end
606
-
607
- def clean!
608
- # No ops
609
- end
610
-
611
- def to_s
612
- super + " [LOCAL]"
613
- end
614
-
615
- def local?
616
- true
617
- end
618
- end
619
- end
620
- end