cocoapods-square-stable 0.19.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1296 -0
  3. data/LICENSE +20 -0
  4. data/README.md +94 -0
  5. data/bin/pod +16 -0
  6. data/bin/sandbox-pod +120 -0
  7. data/lib/cocoapods.rb +77 -0
  8. data/lib/cocoapods/command.rb +116 -0
  9. data/lib/cocoapods/command/help.rb +23 -0
  10. data/lib/cocoapods/command/inter_process_communication.rb +178 -0
  11. data/lib/cocoapods/command/list.rb +77 -0
  12. data/lib/cocoapods/command/outdated.rb +56 -0
  13. data/lib/cocoapods/command/podfile_info.rb +91 -0
  14. data/lib/cocoapods/command/project.rb +88 -0
  15. data/lib/cocoapods/command/push.rb +172 -0
  16. data/lib/cocoapods/command/repo.rb +145 -0
  17. data/lib/cocoapods/command/search.rb +61 -0
  18. data/lib/cocoapods/command/setup.rb +134 -0
  19. data/lib/cocoapods/command/spec.rb +590 -0
  20. data/lib/cocoapods/config.rb +231 -0
  21. data/lib/cocoapods/downloader.rb +59 -0
  22. data/lib/cocoapods/executable.rb +118 -0
  23. data/lib/cocoapods/external_sources.rb +363 -0
  24. data/lib/cocoapods/file_list.rb +36 -0
  25. data/lib/cocoapods/gem_version.rb +7 -0
  26. data/lib/cocoapods/generator/acknowledgements.rb +107 -0
  27. data/lib/cocoapods/generator/acknowledgements/markdown.rb +40 -0
  28. data/lib/cocoapods/generator/acknowledgements/plist.rb +64 -0
  29. data/lib/cocoapods/generator/bridge_support.rb +22 -0
  30. data/lib/cocoapods/generator/copy_resources_script.rb +54 -0
  31. data/lib/cocoapods/generator/dummy_source.rb +22 -0
  32. data/lib/cocoapods/generator/prefix_header.rb +82 -0
  33. data/lib/cocoapods/generator/target_environment_header.rb +86 -0
  34. data/lib/cocoapods/generator/xcconfig.rb +185 -0
  35. data/lib/cocoapods/hooks/installer_representation.rb +134 -0
  36. data/lib/cocoapods/hooks/library_representation.rb +94 -0
  37. data/lib/cocoapods/hooks/pod_representation.rb +74 -0
  38. data/lib/cocoapods/installer.rb +571 -0
  39. data/lib/cocoapods/installer/analyzer.rb +559 -0
  40. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +253 -0
  41. data/lib/cocoapods/installer/file_references_installer.rb +179 -0
  42. data/lib/cocoapods/installer/pod_source_installer.rb +248 -0
  43. data/lib/cocoapods/installer/target_installer.rb +379 -0
  44. data/lib/cocoapods/installer/user_project_integrator.rb +180 -0
  45. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +224 -0
  46. data/lib/cocoapods/library.rb +202 -0
  47. data/lib/cocoapods/open_uri.rb +24 -0
  48. data/lib/cocoapods/project.rb +209 -0
  49. data/lib/cocoapods/resolver.rb +212 -0
  50. data/lib/cocoapods/sandbox.rb +343 -0
  51. data/lib/cocoapods/sandbox/file_accessor.rb +217 -0
  52. data/lib/cocoapods/sandbox/headers_store.rb +96 -0
  53. data/lib/cocoapods/sandbox/path_list.rb +208 -0
  54. data/lib/cocoapods/sources_manager.rb +276 -0
  55. data/lib/cocoapods/user_interface.rb +304 -0
  56. data/lib/cocoapods/user_interface/error_report.rb +101 -0
  57. data/lib/cocoapods/validator.rb +350 -0
  58. metadata +238 -0
@@ -0,0 +1,571 @@
1
+ module Pod
2
+
3
+ # The Installer is responsible of taking a Podfile and transform it in the
4
+ # Pods libraries. It also integrates the user project so the Pods
5
+ # libraries can be used out of the box.
6
+ #
7
+ # The Installer is capable of doing incremental updates to an existing Pod
8
+ # installation.
9
+ #
10
+ # The Installer gets the information that it needs mainly from 3 files:
11
+ #
12
+ # - Podfile: The specification written by the user that contains
13
+ # information about targets and Pods.
14
+ # - Podfile.lock: Contains information about the pods that were previously
15
+ # installed and in concert with the Podfile provides information about
16
+ # which specific version of a Pod should be installed. This file is
17
+ # ignored in update mode.
18
+ # - Manifest.lock: A file contained in the Pods folder that keeps track of
19
+ # the pods installed in the local machine. This files is used once the
20
+ # exact versions of the Pods has been computed to detect if that version
21
+ # is already installed. This file is not intended to be kept under source
22
+ # control and is a copy of the Podfile.lock.
23
+ #
24
+ # The Installer is designed to work in environments where the Podfile folder
25
+ # is under source control and environments where it is not. The rest of the
26
+ # files, like the user project and the workspace are assumed to be under
27
+ # source control.
28
+ #
29
+ class Installer
30
+
31
+ autoload :Analyzer, 'cocoapods/installer/analyzer'
32
+ autoload :FileReferencesInstaller, 'cocoapods/installer/file_references_installer'
33
+ autoload :PodSourceInstaller, 'cocoapods/installer/pod_source_installer'
34
+ autoload :TargetInstaller, 'cocoapods/installer/target_installer'
35
+ autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'
36
+
37
+ include Config::Mixin
38
+
39
+ # @return [Sandbox] The sandbox where the Pods should be installed.
40
+ #
41
+ attr_reader :sandbox
42
+
43
+ # @return [Podfile] The Podfile specification that contains the information
44
+ # of the Pods that should be installed.
45
+ #
46
+ attr_reader :podfile
47
+
48
+ # @return [Lockfile] The Lockfile that stores the information about the
49
+ # Pods previously installed on any machine.
50
+ #
51
+ attr_reader :lockfile
52
+
53
+ # @param [Sandbox] sandbox @see sandbox
54
+ # @param [Podfile] podfile @see podfile
55
+ # @param [Lockfile] lockfile @see lockfile
56
+ #
57
+ def initialize(sandbox, podfile, lockfile = nil)
58
+ @sandbox = sandbox
59
+ @podfile = podfile
60
+ @lockfile = lockfile
61
+ end
62
+
63
+ # @return [Bool] Whether the installer is in update mode. In update mode
64
+ # the contents of the Lockfile are not taken into account for
65
+ # deciding what Pods to install.
66
+ #
67
+ attr_accessor :update_mode
68
+
69
+ # Installs the Pods.
70
+ #
71
+ # The installation process of is mostly linear with few minor complications
72
+ # to keep in mind:
73
+ #
74
+ # - The stored podspecs need to be cleaned before the resolution step
75
+ # otherwise the sandbox might return an old podspec and not download
76
+ # the new one from an external source.
77
+ # - The resolver might trigger the download of Pods from external sources
78
+ # necessary to retrieve their podspec (unless it is instructed not to
79
+ # do it).
80
+ #
81
+ # @return [void]
82
+ #
83
+ def install!
84
+ resolve_dependencies
85
+ download_dependencies
86
+ generate_pods_project
87
+ integrate_user_project if config.integrate_targets?
88
+ end
89
+
90
+ def resolve_dependencies
91
+ UI.section "Analyzing dependencies" do
92
+ analyze
93
+ prepare_for_legacy_compatibility
94
+ clean_sandbox
95
+ end
96
+ end
97
+
98
+ def download_dependencies
99
+ UI.section "Downloading dependencies" do
100
+ create_file_accessors
101
+ install_pod_sources
102
+ run_pre_install_hooks
103
+ clean_pod_sources
104
+ end
105
+ end
106
+
107
+ def generate_pods_project
108
+ UI.section "Generating Pods project" do
109
+ prepare_pods_project
110
+ install_file_references
111
+ install_targets
112
+ run_post_install_hooks
113
+ write_pod_project
114
+ write_lockfiles
115
+ end
116
+ end
117
+
118
+ #-------------------------------------------------------------------------#
119
+
120
+ public
121
+
122
+ # @!group Installation results
123
+
124
+ # @return [Analyzer] the analyzer which provides the information about what
125
+ # needs to be installed.
126
+ #
127
+ attr_reader :analysis_result
128
+
129
+ # @return [Pod::Project] the `Pods/Pods.xcodeproj` project.
130
+ #
131
+ attr_reader :pods_project
132
+
133
+ # @return [Array<String>] The Pods that should be installed.
134
+ #
135
+ attr_reader :names_of_pods_to_install
136
+
137
+ # @return [Array<Library>] The libraries generated by the installation
138
+ # process.
139
+ #
140
+ attr_reader :libraries
141
+
142
+ # @return [Array<Specification>] The specifications that where installed.
143
+ #
144
+ attr_accessor :installed_specs
145
+
146
+ #-------------------------------------------------------------------------#
147
+
148
+ private
149
+
150
+ # @!group Installation steps
151
+
152
+ # @return [void]
153
+ #
154
+ # @note The warning about the version of the Lockfile doesn't uses the
155
+ # `UI.warn` method because it prints the output only at the end
156
+ # of the installation. At that time CocoaPods could have crashed.
157
+ #
158
+ def analyze
159
+ if lockfile && lockfile.cocoapods_version > Version.new(VERSION)
160
+ STDERR.puts '[!] The version of CocoaPods used to generate the lockfile is '\
161
+ 'higher that the one of the current executable. Incompatibility' \
162
+ 'issues might arise.'.yellow
163
+ end
164
+
165
+ analyzer = Analyzer.new(sandbox, podfile, lockfile)
166
+ analyzer.update_mode = update_mode
167
+ @analysis_result = analyzer.analyze
168
+ @libraries = analyzer.result.libraries
169
+ end
170
+
171
+ # Prepares the Pods folder in order to be compatible with the most recent
172
+ # version of CocoaPods.
173
+ #
174
+ # @return [void]
175
+ #
176
+ def prepare_for_legacy_compatibility
177
+ # move_target_support_files_if_needed
178
+ # move_Local_Podspecs_to_Podspecs_if_needed
179
+ # move_pods_to_sources_folder_if_needed
180
+ end
181
+
182
+ # @return [void] In this step we clean all the folders that will be
183
+ # regenerated from scratch and any file which might not be
184
+ # overwritten.
185
+ #
186
+ # @todo [#247] Clean the headers of only the pods to install.
187
+ #
188
+ def clean_sandbox
189
+ sandbox.build_headers.implode!
190
+ sandbox.public_headers.implode!
191
+
192
+ unless sandbox_state.deleted.empty?
193
+ title_options = { :verbose_prefix => "-> ".red }
194
+ sandbox_state.deleted.each do |pod_name|
195
+ UI.titled_section("Removing #{pod_name}".red, title_options) do
196
+ sandbox.clean_pod(pod_name)
197
+ end
198
+ end
199
+ end
200
+ end
201
+
202
+ # TODO: the file accessor should be initialized by the sandbox as they
203
+ # created by the Pod source installer as well.
204
+ #
205
+ def create_file_accessors
206
+ libraries.each do |library|
207
+ library.specs.each do |spec|
208
+ pod_root = sandbox.pod_dir(spec.root.name)
209
+ path_list = Sandbox::PathList.new(pod_root)
210
+ file_accessor = Sandbox::FileAccessor.new(path_list, spec.consumer(library.platform))
211
+ library.file_accessors ||= []
212
+ library.file_accessors << file_accessor
213
+ end
214
+ end
215
+ end
216
+
217
+ # Downloads, installs the documentation and cleans the sources of the Pods
218
+ # which need to be installed.
219
+ #
220
+ # @return [void]
221
+ #
222
+ def install_pod_sources
223
+ @installed_specs = []
224
+ pods_to_install = sandbox_state.added | sandbox_state.changed
225
+ title_options = { :verbose_prefix => "-> ".green }
226
+ root_specs.sort_by(&:name).each do |spec|
227
+ if pods_to_install.include?(spec.name)
228
+ UI.titled_section("Installing #{spec}".green, title_options) do
229
+ install_source_of_pod(spec.name)
230
+ end
231
+ else
232
+ UI.titled_section("Using #{spec}", title_options)
233
+ end
234
+ end
235
+ end
236
+
237
+ # Install the Pods. If the resolver indicated that a Pod should be
238
+ # installed and it exits, it is removed an then reinstalled. In any case if
239
+ # the Pod doesn't exits it is installed.
240
+ #
241
+ # @return [void]
242
+ #
243
+ def install_source_of_pod(pod_name)
244
+ specs_by_platform = {}
245
+ libraries.each do |library|
246
+ specs = library.specs.select { |spec| spec.root.name == pod_name }
247
+
248
+ unless specs.empty?
249
+ specs_by_platform[library.platform] ||= []
250
+ specs_by_platform[library.platform].concat(specs)
251
+ end
252
+ end
253
+
254
+ @pod_installers ||= []
255
+ pod_installer = PodSourceInstaller.new(sandbox, specs_by_platform)
256
+ pod_installer.aggressive_cache = config.aggressive_cache?
257
+ pod_installer.install!
258
+ @pod_installers << pod_installer
259
+ @installed_specs.concat(specs_by_platform.values.flatten.uniq)
260
+ end
261
+
262
+ # Cleans the sources of the Pods if the config instructs to do so.
263
+ #
264
+ # @todo Why the @pod_installers might be empty?
265
+ #
266
+ def clean_pod_sources
267
+ return unless config.clean?
268
+ return unless @pod_installers
269
+ @pod_installers.each do |pod_installer|
270
+ pod_installer.clean!
271
+ end
272
+ end
273
+
274
+ # Creates the Pods project from scratch if it doesn't exists.
275
+ #
276
+ # @return [void]
277
+ #
278
+ # @todo Clean and modify the project if it exists.
279
+ #
280
+ def prepare_pods_project
281
+ UI.message "- Creating Pods project" do
282
+ @pods_project = Pod::Project.new(sandbox.project_path)
283
+ if config.podfile_path.exist?
284
+ @pods_project.add_podfile(config.podfile_path)
285
+ end
286
+ sandbox.project = @pods_project
287
+ platforms = libraries.map(&:platform)
288
+ osx_deployment_target = platforms.select { |p| p.name == :osx }.map(&:deployment_target).min
289
+ ios_deployment_target = platforms.select { |p| p.name == :ios }.map(&:deployment_target).min
290
+ @pods_project.build_configurations.each do |build_configuration|
291
+ build_configuration.build_settings['MACOSX_DEPLOYMENT_TARGET'] = osx_deployment_target.to_s if osx_deployment_target
292
+ build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = ios_deployment_target.to_s if ios_deployment_target
293
+ end
294
+ end
295
+ end
296
+
297
+
298
+ # Installs the file references in the Pods project. This is done once per
299
+ # Pod as the same file reference might be shared by multiple targets.
300
+ #
301
+ # @return [void]
302
+ #
303
+ def install_file_references
304
+ installer = FileReferencesInstaller.new(sandbox, libraries, pods_project)
305
+ installer.install!
306
+ end
307
+
308
+ # Installs the targets of the Pods projects and generates their support
309
+ # files.
310
+ #
311
+ # @return [void]
312
+ #
313
+ def install_targets
314
+ UI.message"- Installing targets" do
315
+ libraries.sort_by(&:name).each do |library|
316
+ next if library.target_definition.empty?
317
+ target_installer = TargetInstaller.new(sandbox, library)
318
+ target_installer.install!
319
+ end
320
+ end
321
+ end
322
+
323
+ # Writes the Pods project to the disk.
324
+ #
325
+ # @return [void]
326
+ #
327
+ def write_pod_project
328
+ UI.message "- Writing Xcode project file to #{UI.path sandbox.project_path}" do
329
+ pods_project.main_group.sort_by_type!
330
+ pods_project['Frameworks'].sort_by_type!
331
+ pods_project.save_as(sandbox.project_path)
332
+ end
333
+ end
334
+
335
+ # Writes the Podfile and the lock files.
336
+ #
337
+ # @todo Pass the checkout options to the Lockfile.
338
+ #
339
+ # @return [void]
340
+ #
341
+ def write_lockfiles
342
+ # checkout_options = sandbox.checkout_options
343
+ @lockfile = Lockfile.generate(podfile, analysis_result.specifications)
344
+
345
+ UI.message "- Writing Lockfile in #{UI.path config.lockfile_path}" do
346
+ @lockfile.write_to_disk(config.lockfile_path)
347
+ end
348
+
349
+ UI.message "- Writing Manifest in #{UI.path sandbox.manifest_path}" do
350
+ @lockfile.write_to_disk(sandbox.manifest_path)
351
+ end
352
+ end
353
+
354
+ # Integrates the user projects adding the dependencies on the CocoaPods
355
+ # libraries, setting them up to use the xcconfigs and performing other
356
+ # actions. This step is also responsible of creating the workspace if
357
+ # needed.
358
+ #
359
+ # @return [void]
360
+ #
361
+ # @todo [#397] The libraries should be cleaned and the re-added on every
362
+ # installation. Maybe a clean_user_project phase should be added.
363
+ # In any case it appears to be a good idea store target definition
364
+ # information in the lockfile.
365
+ #
366
+ def integrate_user_project
367
+ UI.section "Integrating client #{'project'.pluralize(libraries.map(&:user_project_path).uniq.count) }" do
368
+ installation_root = config.installation_root
369
+ integrator = UserProjectIntegrator.new(podfile, sandbox, installation_root, libraries)
370
+ integrator.integrate!
371
+ end
372
+ end
373
+
374
+ #-------------------------------------------------------------------------#
375
+
376
+ private
377
+
378
+ # @!group Hooks
379
+
380
+ # Runs the pre install hooks of the installed specs and of the Podfile.
381
+ #
382
+ # @return [void]
383
+ #
384
+ def run_pre_install_hooks
385
+ UI.message "- Running pre install hooks" do
386
+ analysis_result.specifications.each do |spec|
387
+ executed = false
388
+ libraries_using_spec(spec).each do |lib|
389
+ lib_representation = library_rep(lib)
390
+ executed |= run_spec_pre_install_hook(spec, lib_representation)
391
+ end
392
+ UI.message "- #{spec.name}" if executed
393
+ end
394
+
395
+ executed = run_podfile_pre_install_hook
396
+ UI.message "- Podfile" if executed
397
+ end
398
+ end
399
+
400
+ # Runs the pre install hook of the given specification with the given
401
+ # library representation.
402
+ #
403
+ # @param [Specification] spec
404
+ # The spec for which the pre install hook should be run.
405
+ #
406
+ # @param [Hooks::LibraryRepresentation] lib_representation
407
+ # The library representation to be passed as an argument to the
408
+ # hook.
409
+ #
410
+ # @raise Raises an informative if the hooks raises.
411
+ #
412
+ # @return [Bool] Whether the hook was run.
413
+ #
414
+ def run_spec_pre_install_hook(spec, lib_representation)
415
+ spec.pre_install!(pod_rep(spec.root.name), lib_representation)
416
+ rescue => e
417
+ raise Informative, "An error occurred while processing the pre-install " \
418
+ "hook of #{spec}." \
419
+ "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
420
+ end
421
+
422
+ # Runs the pre install hook of the Podfile
423
+ #
424
+ # @raise Raises an informative if the hooks raises.
425
+ #
426
+ # @return [Bool] Whether the hook was run.
427
+ #
428
+ def run_podfile_pre_install_hook
429
+ podfile.pre_install!(installer_rep)
430
+ rescue => e
431
+ raise Informative, "An error occurred while processing the pre-install " \
432
+ "hook of the Podfile." \
433
+ "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
434
+ end
435
+
436
+ # Runs the post install hooks of the installed specs and of the Podfile.
437
+ #
438
+ # @note Post install hooks run _before_ saving of project, so that they
439
+ # can alter it before it is written to the disk.
440
+ #
441
+ # @return [void]
442
+ #
443
+ def run_post_install_hooks
444
+ UI.message "- Running post install hooks" do
445
+ analysis_result.specifications.each do |spec|
446
+ executed = false
447
+ libraries_using_spec(spec).each do |lib|
448
+ lib_representation = library_rep(lib)
449
+ executed |= run_spec_post_install_hook(spec, lib_representation)
450
+ end
451
+ UI.message "- #{spec.name}" if executed
452
+ end
453
+ executed = run_podfile_post_install_hook
454
+ UI.message "- Podfile" if executed
455
+ end
456
+ end
457
+
458
+
459
+ # Runs the post install hook of the given specification with the given
460
+ # library representation.
461
+ #
462
+ # @param [Specification] spec
463
+ # The spec for which the post install hook should be run.
464
+ #
465
+ # @param [Hooks::LibraryRepresentation] lib_representation
466
+ # The library representation to be passed as an argument to the
467
+ # hook.
468
+ #
469
+ # @raise Raises an informative if the hooks raises.
470
+ #
471
+ # @return [Bool] Whether the hook was run.
472
+ #
473
+ def run_spec_post_install_hook(spec, lib_representation)
474
+ spec.post_install!(lib_representation)
475
+ rescue => e
476
+ raise Informative, "An error occurred while processing the post-install " \
477
+ "hook of #{spec}." \
478
+ "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
479
+ end
480
+
481
+ # Runs the post install hook of the Podfile
482
+ #
483
+ # @raise Raises an informative if the hooks raises.
484
+ #
485
+ # @return [Bool] Whether the hook was run.
486
+ #
487
+ def run_podfile_post_install_hook
488
+ podfile.post_install!(installer_rep)
489
+ rescue => e
490
+ raise Informative, "An error occurred while processing the post-install " \
491
+ "hook of the Podfile." \
492
+ "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
493
+ end
494
+
495
+ #-------------------------------------------------------------------------#
496
+
497
+ public
498
+
499
+ # @!group Hooks Data
500
+
501
+ # @return [InstallerRepresentation]
502
+ #
503
+ def installer_rep
504
+ Hooks::InstallerRepresentation.new(self)
505
+ end
506
+
507
+ # @return [PodRepresentation] The hook representation of a Pod.
508
+ #
509
+ # @param [String] pod
510
+ # The name of the pod.
511
+ #
512
+ # @return [PodRepresentation] The pod representation.
513
+ #
514
+ def pod_rep(pod)
515
+ all_file_accessors = libraries.map(&:file_accessors).flatten.compact
516
+ file_accessors = all_file_accessors.select { |fa| fa.spec.root.name == pod }
517
+ Hooks::PodRepresentation.new(pod, file_accessors)
518
+ end
519
+
520
+ # @return [LibraryRepresentation]
521
+ #
522
+ def library_rep(library)
523
+ Hooks::LibraryRepresentation.new(sandbox, library)
524
+ end
525
+
526
+ # @return [Array<LibraryRepresentation>]
527
+ #
528
+ def library_reps
529
+ @library_reps ||= libraries.map { |lib| library_rep(lib) }
530
+ end
531
+
532
+ # @return [Array<PodRepresentation>]
533
+ #
534
+ def pod_reps
535
+ root_specs.sort_by { |spec| spec.name }.map { |spec| pod_rep(spec.name) }
536
+ end
537
+
538
+ # Returns the libraries which use the given specification.
539
+ #
540
+ # @param [Specification] spec
541
+ # The specification for which the client libraries are needed.
542
+ #
543
+ # @return [Array<Library>] The library.
544
+ #
545
+ def libraries_using_spec(spec)
546
+ libraries.select { |lib| lib.specs.include?(spec) }
547
+ end
548
+
549
+ #-------------------------------------------------------------------------#
550
+
551
+ private
552
+
553
+ # @!group Private helpers
554
+
555
+ # @return [Array<Specification>] All the root specifications of the
556
+ # installation.
557
+ #
558
+ def root_specs
559
+ analysis_result.specifications.map { |spec| spec.root }.uniq
560
+ end
561
+
562
+ # @return [SpecsState] The state of the sandbox returned by the analyzer.
563
+ #
564
+ def sandbox_state
565
+ analysis_result.sandbox_state
566
+ end
567
+
568
+ #-------------------------------------------------------------------------#
569
+
570
+ end
571
+ end