cocoapods 1.11.0 → 1.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +162 -2
  3. data/README.md +7 -8
  4. data/lib/cocoapods/command/lib/lint.rb +3 -0
  5. data/lib/cocoapods/command/repo/push.rb +3 -0
  6. data/lib/cocoapods/command/setup.rb +2 -2
  7. data/lib/cocoapods/command/spec/lint.rb +3 -0
  8. data/lib/cocoapods/config.rb +5 -5
  9. data/lib/cocoapods/executable.rb +1 -1
  10. data/lib/cocoapods/external_sources/abstract_external_source.rb +1 -1
  11. data/lib/cocoapods/external_sources/path_source.rb +1 -1
  12. data/lib/cocoapods/gem_version.rb +1 -1
  13. data/lib/cocoapods/generator/acknowledgements.rb +12 -0
  14. data/lib/cocoapods/generator/app_target_helper.rb +1 -1
  15. data/lib/cocoapods/generator/copy_resources_script.rb +1 -1
  16. data/lib/cocoapods/generator/copy_xcframework_script.rb +48 -22
  17. data/lib/cocoapods/generator/embed_frameworks_script.rb +1 -1
  18. data/lib/cocoapods/generator/info_plist_file.rb +1 -1
  19. data/lib/cocoapods/installer/analyzer/analysis_result.rb +3 -3
  20. data/lib/cocoapods/installer/analyzer/pod_variant.rb +1 -1
  21. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +8 -7
  22. data/lib/cocoapods/installer/analyzer.rb +9 -5
  23. data/lib/cocoapods/installer/base_install_hooks_context.rb +18 -3
  24. data/lib/cocoapods/installer/installation_options.rb +11 -0
  25. data/lib/cocoapods/installer/pod_source_downloader.rb +159 -0
  26. data/lib/cocoapods/installer/pod_source_installer.rb +10 -36
  27. data/lib/cocoapods/installer/project_cache/project_cache_analyzer.rb +2 -2
  28. data/lib/cocoapods/installer/project_cache/target_cache_key.rb +1 -1
  29. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +2 -1
  30. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +37 -3
  31. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +6 -0
  32. data/lib/cocoapods/installer/xcode/pods_project_generator/project_generator.rb +1 -1
  33. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +9 -3
  34. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +36 -1
  35. data/lib/cocoapods/installer/xcode/target_validator.rb +1 -1
  36. data/lib/cocoapods/installer.rb +102 -34
  37. data/lib/cocoapods/native_target_extension.rb +1 -1
  38. data/lib/cocoapods/open-uri.rb +1 -1
  39. data/lib/cocoapods/project.rb +8 -8
  40. data/lib/cocoapods/resolver/resolver_specification.rb +1 -1
  41. data/lib/cocoapods/resolver.rb +3 -3
  42. data/lib/cocoapods/sandbox/file_accessor.rb +11 -2
  43. data/lib/cocoapods/sandbox/path_list.rb +1 -1
  44. data/lib/cocoapods/sandbox.rb +48 -12
  45. data/lib/cocoapods/sources_manager.rb +7 -4
  46. data/lib/cocoapods/target/build_settings.rb +9 -2
  47. data/lib/cocoapods/target/pod_target.rb +2 -2
  48. data/lib/cocoapods/user_interface.rb +2 -2
  49. data/lib/cocoapods/validator.rb +31 -20
  50. data/lib/cocoapods/xcode/xcframework/xcframework_slice.rb +12 -6
  51. data/lib/cocoapods/xcode/xcframework.rb +1 -1
  52. metadata +14 -13
@@ -39,6 +39,7 @@ module Pod
39
39
  autoload :PreIntegrateHooksContext, 'cocoapods/installer/pre_integrate_hooks_context'
40
40
  autoload :SourceProviderHooksContext, 'cocoapods/installer/source_provider_hooks_context'
41
41
  autoload :PodfileValidator, 'cocoapods/installer/podfile_validator'
42
+ autoload :PodSourceDownloader, 'cocoapods/installer/pod_source_downloader'
42
43
  autoload :PodSourceInstaller, 'cocoapods/installer/pod_source_installer'
43
44
  autoload :PodSourcePreparer, 'cocoapods/installer/pod_source_preparer'
44
45
  autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'
@@ -161,8 +162,10 @@ module Pod
161
162
  resolve_dependencies
162
163
  download_dependencies
163
164
  validate_targets
165
+ clean_sandbox
164
166
  if installation_options.skip_pods_project_generation?
165
167
  show_skip_pods_project_generation_message
168
+ run_podfile_post_install_hooks
166
169
  else
167
170
  integrate
168
171
  end
@@ -296,7 +299,10 @@ module Pod
296
299
  pod_targets_to_generate = cache_analysis_result.pod_targets_to_generate
297
300
  aggregate_targets_to_generate = cache_analysis_result.aggregate_targets_to_generate
298
301
 
299
- clean_sandbox(pod_targets_to_generate)
302
+ pod_targets_to_generate.each do |pod_target|
303
+ pod_target.build_headers.implode_path!(pod_target.headers_sandbox)
304
+ sandbox.public_headers.implode_path!(pod_target.headers_sandbox)
305
+ end
300
306
 
301
307
  create_and_save_projects(pod_targets_to_generate, aggregate_targets_to_generate,
302
308
  cache_analysis_result.build_configurations, cache_analysis_result.project_object_version)
@@ -443,23 +449,30 @@ module Pod
443
449
  end
444
450
  end
445
451
 
446
- # @return [void] In this step we clean all the header folders for pod targets that will be
447
- # regenerated from scratch and cleanup any pods that have been removed.
452
+ # @return [void] Performs a general clean up of the sandbox related to the sandbox state that was
453
+ # calculated. For example, pods that were marked for deletion are removed.
448
454
  #
449
- def clean_sandbox(pod_targets)
450
- pod_targets.each do |pod_target|
451
- pod_target.build_headers.implode_path!(pod_target.headers_sandbox)
452
- sandbox.public_headers.implode_path!(pod_target.headers_sandbox)
453
- end
454
-
455
+ def clean_sandbox
455
456
  unless sandbox_state.deleted.empty?
456
457
  title_options = { :verbose_prefix => '-> '.red }
457
458
  sandbox_state.deleted.each do |pod_name|
458
459
  UI.titled_section("Removing #{pod_name}".red, title_options) do
459
- sandbox.clean_pod(pod_name)
460
+ root_name = Specification.root_name(pod_name)
461
+ pod_dir = sandbox.local?(root_name) ? nil : sandbox.pod_dir(root_name)
462
+ sandbox.clean_pod(pod_name, pod_dir)
460
463
  end
461
464
  end
462
465
  end
466
+
467
+ # Check any changed pods that became local pods and used to be remote pods and
468
+ # ensure the sandbox is cleaned up.
469
+ unless sandbox_state.changed.empty?
470
+ sandbox_state.changed.each do |pod_name|
471
+ previous_spec_repo = sandbox.manifest.spec_repo(pod_name)
472
+ should_clean = !previous_spec_repo.nil? && sandbox.local?(pod_name)
473
+ sandbox.clean_pod(pod_name, sandbox.sources_root + Specification.root_name(pod_name)) if should_clean
474
+ end
475
+ end
463
476
  end
464
477
 
465
478
  # @raise [Informative] If there are any Podfile changes
@@ -490,26 +503,38 @@ module Pod
490
503
  # @return [void]
491
504
  #
492
505
  def install_pod_sources
506
+ @downloaded_specs = []
493
507
  @installed_specs = []
494
508
  pods_to_install = sandbox_state.added | sandbox_state.changed
495
509
  title_options = { :verbose_prefix => '-> '.green }
496
- root_specs.sort_by(&:name).each do |spec|
497
- if pods_to_install.include?(spec.name)
498
- if sandbox_state.changed.include?(spec.name) && sandbox.manifest
499
- current_version = spec.version
500
- previous_version = sandbox.manifest.version(spec.name)
501
- has_changed_version = current_version != previous_version
502
- current_repo = analysis_result.specs_by_source.detect { |key, values| break key if values.map(&:name).include?(spec.name) }
503
- current_repo &&= (Pod::TrunkSource::TRUNK_REPO_NAME if current_repo.name == Pod::TrunkSource::TRUNK_REPO_NAME) || current_repo.url || current_repo.name
504
- previous_spec_repo = sandbox.manifest.spec_repo(spec.name)
505
- has_changed_repo = !previous_spec_repo.nil? && current_repo && !current_repo.casecmp(previous_spec_repo).zero?
506
- title = "Installing #{spec.name} #{spec.version}"
507
- title << " (was #{previous_version} and source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if has_changed_version && has_changed_repo
508
- title << " (was #{previous_version})" if has_changed_version && !has_changed_repo
509
- title << " (source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if !has_changed_version && has_changed_repo
510
- else
511
- title = "Installing #{spec}"
510
+
511
+ sorted_root_specs = root_specs.sort_by(&:name)
512
+
513
+ # Download pods in parallel before installing if the option is set
514
+ if installation_options.parallel_pod_downloads
515
+ require 'concurrent/executor/fixed_thread_pool'
516
+ thread_pool_size = installation_options.parallel_pod_download_thread_pool_size
517
+ thread_pool = Concurrent::FixedThreadPool.new(thread_pool_size, :idletime => 300)
518
+
519
+ sorted_root_specs.each do |spec|
520
+ if pods_to_install.include?(spec.name)
521
+ title = section_title(spec, 'Downloading')
522
+ UI.titled_section(title.green, title_options) do
523
+ thread_pool.post do
524
+ download_source_of_pod(spec.name)
525
+ end
526
+ end
512
527
  end
528
+ end
529
+
530
+ thread_pool.shutdown
531
+ thread_pool.wait_for_termination
532
+ end
533
+
534
+ # Install pods, which includes downloading only if parallel_pod_downloads is set to false
535
+ sorted_root_specs.each do |spec|
536
+ if pods_to_install.include?(spec.name)
537
+ title = section_title(spec, 'Installing')
513
538
  UI.titled_section(title.green, title_options) do
514
539
  install_source_of_pod(spec.name)
515
540
  end
@@ -521,13 +546,32 @@ module Pod
521
546
  end
522
547
  end
523
548
 
549
+ def section_title(spec, current_action)
550
+ if sandbox_state.changed.include?(spec.name) && sandbox.manifest
551
+ current_version = spec.version
552
+ previous_version = sandbox.manifest.version(spec.name)
553
+ has_changed_version = current_version != previous_version
554
+ current_repo = analysis_result.specs_by_source.detect { |key, values| break key if values.map(&:name).include?(spec.name) }
555
+ current_repo &&= (Pod::TrunkSource::TRUNK_REPO_NAME if current_repo.name == Pod::TrunkSource::TRUNK_REPO_NAME) || current_repo.url || current_repo.name
556
+ previous_spec_repo = sandbox.manifest.spec_repo(spec.name)
557
+ has_changed_repo = !previous_spec_repo.nil? && current_repo && !current_repo.casecmp(previous_spec_repo).zero?
558
+ title = "#{current_action} #{spec.name} #{spec.version}"
559
+ title << " (was #{previous_version} and source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if has_changed_version && has_changed_repo
560
+ title << " (was #{previous_version})" if has_changed_version && !has_changed_repo
561
+ title << " (source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if !has_changed_version && has_changed_repo
562
+ else
563
+ title = "#{current_action} #{spec}"
564
+ end
565
+ title
566
+ end
567
+
524
568
  def create_pod_installer(pod_name)
525
569
  specs_by_platform = specs_for_pod(pod_name)
526
570
 
527
571
  if specs_by_platform.empty?
528
572
  requiring_targets = pod_targets.select { |pt| pt.recursive_dependent_targets.any? { |dt| dt.pod_name == pod_name } }
529
573
  message = "Could not install '#{pod_name}' pod"
530
- message += ", dependended upon by #{requiring_targets.to_sentence}" unless requiring_targets.empty?
574
+ message += ", depended upon by #{requiring_targets.to_sentence}" unless requiring_targets.empty?
531
575
  message += '. There is either no platform to build for, or no target to build.'
532
576
  raise StandardError, message
533
577
  end
@@ -537,6 +581,20 @@ module Pod
537
581
  pod_installer
538
582
  end
539
583
 
584
+ def create_pod_downloader(pod_name)
585
+ specs_by_platform = specs_for_pod(pod_name)
586
+
587
+ if specs_by_platform.empty?
588
+ requiring_targets = pod_targets.select { |pt| pt.recursive_dependent_targets.any? { |dt| dt.pod_name == pod_name } }
589
+ message = "Could not download '#{pod_name}' pod"
590
+ message += ", depended upon by #{requiring_targets.to_sentence}" unless requiring_targets.empty?
591
+ message += '. There is either no platform to build for, or no target to build.'
592
+ raise StandardError, message
593
+ end
594
+
595
+ PodSourceDownloader.new(sandbox, podfile, specs_by_platform, :can_cache => installation_options.clean?)
596
+ end
597
+
540
598
  # The specifications matching the specified pod name
541
599
  #
542
600
  # @param [String] pod_name the name of the pod
@@ -564,8 +622,19 @@ module Pod
564
622
  @installed_specs.concat(pod_installer.specs_by_platform.values.flatten.uniq)
565
623
  end
566
624
 
567
- # Cleans the sources of the Pods if the config instructs to do so.
625
+ # Download the pod unless it is local or has been predownloaded from an
626
+ # external source.
627
+ #
628
+ # @return [void]
568
629
  #
630
+ def download_source_of_pod(pod_name)
631
+ return if sandbox.local?(pod_name) || sandbox.predownloaded?(pod_name)
632
+
633
+ pod_downloader = create_pod_downloader(pod_name)
634
+ pod_downloader.download!
635
+ end
636
+
637
+ # Cleans the sources of the Pods if the config instructs to do so.
569
638
  #
570
639
  def clean_pod_sources
571
640
  return unless installation_options.clean?
@@ -633,7 +702,7 @@ module Pod
633
702
  #
634
703
  def run_plugins_pre_integrate_hooks
635
704
  if any_plugin_pre_integrate_hooks?
636
- context = PreIntegrateHooksContext.generate(sandbox, pods_project, aggregate_targets)
705
+ context = PreIntegrateHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
637
706
  HooksManager.run(:pre_integrate, context, plugins)
638
707
  end
639
708
  end
@@ -645,7 +714,7 @@ module Pod
645
714
  if any_plugin_post_install_hooks?
646
715
  unlock_pod_sources
647
716
 
648
- context = PostInstallHooksContext.generate(sandbox, pods_project, aggregate_targets)
717
+ context = PostInstallHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
649
718
  HooksManager.run(:post_install, context, plugins)
650
719
  end
651
720
 
@@ -656,7 +725,7 @@ module Pod
656
725
  #
657
726
  def run_plugins_post_integrate_hooks
658
727
  if any_plugin_post_integrate_hooks?
659
- context = PostIntegrateHooksContext.generate(sandbox, pods_project, aggregate_targets)
728
+ context = PostIntegrateHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
660
729
  HooksManager.run(:post_integrate, context, plugins)
661
730
  end
662
731
  end
@@ -893,10 +962,9 @@ module Pod
893
962
  "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
894
963
  end
895
964
 
896
- # Runs the post integrate hooks of the installed specs and of the Podfile.
965
+ # Runs the pre integrate hooks of the installed specs and of the Podfile.
897
966
  #
898
- # @note Post integrate hooks run _after_ saving of project, so that they
899
- # can alter it after it is written to the disk.
967
+ # @note Pre integrate hooks run _before_ generation of the Pods project.
900
968
  #
901
969
  # @return [void]
902
970
  #
@@ -43,7 +43,7 @@ module Pod
43
43
  # @param [TargetMetadata] cached_target
44
44
  # the target to search for.
45
45
  #
46
- # @return [Bool]
46
+ # @return [Boolean]
47
47
  #
48
48
  def self.dependency_for_cached_target?(sandbox, target, cached_target)
49
49
  target.dependencies.find do |dep|
@@ -24,7 +24,7 @@ module OpenURI
24
24
  # @param [URI::Generic] uri2
25
25
  # the target uri where to where the redirect points to
26
26
  #
27
- # @return [Bool]
27
+ # @return [Boolean]
28
28
  #
29
29
  def self.redirectable?(uri1, uri2)
30
30
  uri1.scheme.downcase == uri2.scheme.downcase ||
@@ -26,7 +26,7 @@ module Pod
26
26
  #
27
27
  attr_reader :dependencies_group
28
28
 
29
- # @return [Bool] Bool indicating if this project is a pod target subproject.
29
+ # @return [Boolean] Bool indicating if this project is a pod target subproject.
30
30
  # Used by `generate_multiple_pod_projects` installation option.
31
31
  #
32
32
  attr_reader :pod_target_subproject
@@ -39,7 +39,7 @@ module Pod
39
39
  # Initialize a new instance
40
40
  #
41
41
  # @param [Pathname, String] path @see Xcodeproj::Project#path
42
- # @param [Bool] skip_initialization Whether the project should be initialized from scratch.
42
+ # @param [Boolean] skip_initialization Whether the project should be initialized from scratch.
43
43
  # @param [Int] object_version Object version to use for serialization, defaults to Xcode 3.2 compatible.
44
44
  #
45
45
  def initialize(path, skip_initialization = false,
@@ -107,10 +107,10 @@ module Pod
107
107
  # @param [#to_s] path
108
108
  # The path to the root of the Pod.
109
109
  #
110
- # @param [Bool] development
110
+ # @param [Boolean] development
111
111
  # Whether the group should be added to the Development Pods group.
112
112
  #
113
- # @param [Bool] absolute
113
+ # @param [Boolean] absolute
114
114
  # Whether the path of the group should be set as absolute.
115
115
  #
116
116
  # @return [PBXGroup] The new group.
@@ -136,7 +136,7 @@ module Pod
136
136
  # @param [Project] project
137
137
  # The subproject to be added.
138
138
  #
139
- # @param [Bool] development
139
+ # @param [Boolean] development
140
140
  # Whether the project should be added to the Development Pods group.
141
141
  # For projects where `pod_target_subproject` is enabled, all subprojects are added into the Dependencies group.
142
142
  #
@@ -156,7 +156,7 @@ module Pod
156
156
  # @param [TargetMetadata] metadata
157
157
  # The project metadata to be added.
158
158
  #
159
- # @param [Bool] development
159
+ # @param [Boolean] development
160
160
  # Whether the project should be added to the Development Pods group.
161
161
  # For projects where `pod_target_subproject` is enabled, all subprojects are added into the Dependencies group.
162
162
  #
@@ -253,7 +253,7 @@ module Pod
253
253
  # @param [PBXGroup] group
254
254
  # The group for the new file reference.
255
255
  #
256
- # @param [Bool] reflect_file_system_structure
256
+ # @param [Boolean] reflect_file_system_structure
257
257
  # Whether group structure should reflect the file system structure.
258
258
  # If yes, where needed, intermediate groups are created, similar to
259
259
  # how mkdir -p operates.
@@ -430,7 +430,7 @@ module Pod
430
430
  # @param [PBXGroup] group
431
431
  # The parent group used as the base of the relative path.
432
432
  #
433
- # @param [Bool] reflect_file_system_structure
433
+ # @param [Boolean] reflect_file_system_structure
434
434
  # Whether group structure should reflect the file system structure.
435
435
  # If yes, where needed, intermediate groups are created, similar to
436
436
  # how mkdir -p operates.
@@ -12,7 +12,7 @@ module Pod
12
12
  #
13
13
  attr_reader :source
14
14
 
15
- # @return [Bool] whether this resolved specification is used by non-library targets.
15
+ # @return [Boolean] whether this resolved specification is used by non-library targets.
16
16
  #
17
17
  attr_reader :used_by_non_library_targets_only
18
18
  alias used_by_non_library_targets_only? used_by_non_library_targets_only
@@ -34,7 +34,7 @@ module Pod
34
34
  #
35
35
  attr_reader :sources
36
36
 
37
- # @return [Bool] Whether the resolver has sources repositories up-to-date.
37
+ # @return [Boolean] Whether the resolver has sources repositories up-to-date.
38
38
  #
39
39
  attr_reader :specs_updated
40
40
  alias specs_updated? specs_updated
@@ -531,7 +531,7 @@ You have either:#{specs_update_message}
531
531
  #
532
532
  # @param [Specification] spec
533
533
  #
534
- # @return [Bool]
534
+ # @return [Boolean]
535
535
  #
536
536
  def spec_is_platform_compatible?(dependency_graph, dependency, spec)
537
537
  # This is safe since a pod will only be in locked dependencies if we're
@@ -575,7 +575,7 @@ You have either:#{specs_update_message}
575
575
  # Whether the given `edge` should be followed to find dependencies for the
576
576
  # given `target_platform`.
577
577
  #
578
- # @return [Bool]
578
+ # @return [Boolean]
579
579
  #
580
580
  def edge_is_valid_for_target_platform?(edge, target_platform)
581
581
  @edge_validity ||= Hash.new do |hash, edge_and_platform|
@@ -179,7 +179,7 @@ module Pod
179
179
  end
180
180
  end
181
181
 
182
- # @return [Array<Pathname>] The paths of the dynamic xcframework bundles
182
+ # @return [Array<Pathname>] The paths of the static xcframework bundles
183
183
  # that come shipped with the Pod.
184
184
  #
185
185
  def vendored_static_xcframeworks
@@ -188,6 +188,15 @@ module Pod
188
188
  end
189
189
  end
190
190
 
191
+ # @return [Array<Pathname>] The paths of the dynamic xcframework bundles
192
+ # that come shipped with the Pod.
193
+ #
194
+ def vendored_dynamic_xcframeworks
195
+ vendored_xcframeworks.select do |path|
196
+ Xcode::XCFramework.new(spec.name, path).build_type == BuildType.dynamic_framework
197
+ end
198
+ end
199
+
191
200
  # @return [Array<Pathname>] The paths of the static (fake) framework
192
201
  # bundles that come shipped with the Pod.
193
202
  #
@@ -504,7 +513,7 @@ module Pod
504
513
  # @option options [Array<String>] :exclude_patterns
505
514
  # The exclude patterns to pass to the PathList.
506
515
  #
507
- # @option options [Bool] :include_dirs
516
+ # @option options [Boolean] :include_dirs
508
517
  # Whether directories should be also included or just plain
509
518
  # files.
510
519
  #
@@ -164,7 +164,7 @@ module Pod
164
164
 
165
165
  # @!group Private helpers
166
166
 
167
- # @return [Bool] Wether a path is a directory. The result of this method
167
+ # @return [Boolean] Wether a path is a directory. The result of this method
168
168
  # computed without accessing the file system and is case
169
169
  # insensitive.
170
170
  #
@@ -67,6 +67,7 @@ module Pod
67
67
  @root = Pathname.new(root).realpath
68
68
  @public_headers = HeadersStore.new(self, 'Public', :public)
69
69
  @predownloaded_pods = []
70
+ @downloaded_pods = []
70
71
  @checkout_sources = {}
71
72
  @development_pods = {}
72
73
  @pods_with_absolute_path = []
@@ -84,18 +85,17 @@ module Pod
84
85
 
85
86
  # Removes the files of the Pod with the given name from the sandbox.
86
87
  #
88
+ # @param [String] name The name of the pod, which is used to calculate additional paths to clean.
89
+ # @param [String] pod_dir The directory of the pod to clean.
90
+ #
87
91
  # @return [void]
88
92
  #
89
- def clean_pod(name)
90
- root_name = Specification.root_name(name)
91
- unless local?(root_name)
92
- path = pod_dir(name)
93
- path.rmtree if path.exist?
94
- end
93
+ def clean_pod(name, pod_dir)
94
+ pod_dir.rmtree if pod_dir&.exist?
95
95
  podspec_path = specification_path(name)
96
- podspec_path.rmtree if podspec_path
96
+ podspec_path.rmtree if podspec_path&.exist?
97
97
  pod_target_project_path = pod_target_project_path(name)
98
- pod_target_project_path.rmtree if pod_target_project_path.exist?
98
+ pod_target_project_path.rmtree if pod_target_project_path&.exist?
99
99
  end
100
100
 
101
101
  # Prepares the sandbox for a new installation removing any file that will
@@ -192,7 +192,7 @@ module Pod
192
192
  #
193
193
  # @param [String] name
194
194
  #
195
- # @return [Bool] true if originally absolute
195
+ # @return [Boolean] true if originally absolute
196
196
  #
197
197
  def local_path_was_absolute?(name)
198
198
  @pods_with_absolute_path.include? name
@@ -342,7 +342,7 @@ module Pod
342
342
  # @param [String] name
343
343
  # The name of the Pod.
344
344
  #
345
- # @return [Bool] Whether the Pod has been pre-downloaded.
345
+ # @return [Boolean] Whether the Pod has been pre-downloaded.
346
346
  #
347
347
  def predownloaded?(name)
348
348
  root_name = Specification.root_name(name)
@@ -351,6 +351,42 @@ module Pod
351
351
 
352
352
  #--------------------------------------#
353
353
 
354
+ # Marks a Pod as downloaded
355
+ #
356
+ # @param [String] name
357
+ # The name of the Pod.
358
+ #
359
+ # @return [void]
360
+ #
361
+ def store_downloaded_pod(name)
362
+ root_name = Specification.root_name(name)
363
+ downloaded_pods << root_name
364
+ end
365
+
366
+ # Checks if a Pod has been downloaded before the installation
367
+ # process.
368
+ #
369
+ # @param [String] name
370
+ # The name of the Pod.
371
+ #
372
+ # @return [Boolean] Whether the Pod has been downloaded.
373
+ #
374
+ def downloaded?(name)
375
+ root_name = Specification.root_name(name)
376
+ downloaded_pods.include?(root_name)
377
+ end
378
+
379
+ # @return [Array<String>] The names of the pods that have been
380
+ # downloaded before the installation process begins.
381
+ # These are distinct from the pre-downloaded pods in
382
+ # that these do not necessarily come from external
383
+ # sources, and are only downloaded right before
384
+ # installation if the parallel_pod_downloads option is on.
385
+ #
386
+ attr_reader :downloaded_pods
387
+
388
+ #--------------------------------------#
389
+
354
390
  # Stores the local path of a Pod.
355
391
  #
356
392
  # @param [String] name
@@ -406,7 +442,7 @@ module Pod
406
442
  # @param [Pathname, String] path
407
443
  # The path to the local Podspec
408
444
  #
409
- # @param [Bool] was_absolute
445
+ # @param [Boolean] was_absolute
410
446
  # True if the specified local path was absolute.
411
447
  #
412
448
  # @return [void]
@@ -428,7 +464,7 @@ module Pod
428
464
  # @param [String] name
429
465
  # The name of the Pod.
430
466
  #
431
- # @return [Bool] Whether the Pod is locally sourced.
467
+ # @return [Boolean] Whether the Pod is locally sourced.
432
468
  #
433
469
  def local?(name)
434
470
  !local_podspec(name).nil?
@@ -71,19 +71,22 @@ module Pod
71
71
  # The URL of the source.
72
72
  #
73
73
  def cdn_url?(url)
74
- return unless url =~ %r{^https?:\/\/}
74
+ return false unless url =~ %r{^https?:\/\/}
75
75
 
76
76
  uri_options = {}
77
77
 
78
78
  netrc_info = Netrc.read
79
- netrc_host = URI.parse(url).host
79
+ uri = URI.parse(url)
80
+ return false unless uri.userinfo.nil?
81
+
82
+ netrc_host = uri.host
80
83
  credentials = netrc_info[netrc_host]
81
84
  uri_options[:http_basic_authentication] = credentials if credentials
82
85
 
83
86
  response = OpenURI.open_uri(url.chomp('/') + '/CocoaPods-version.yml', uri_options)
84
87
  response_hash = YAML.load(response.read) # rubocop:disable Security/YAMLLoad
85
88
  response_hash.is_a?(Hash) && !Source::Metadata.new(response_hash).latest_cocoapods_version.nil?
86
- rescue ::OpenURI::HTTPError, SocketError
89
+ rescue Psych::SyntaxError, ::OpenURI::HTTPError, SocketError
87
90
  return false
88
91
  rescue => e
89
92
  raise Informative, "Couldn't determine repo type for URL: `#{url}`: #{e}"
@@ -116,7 +119,7 @@ module Pod
116
119
  #
117
120
  # @param [String] source_name
118
121
  #
119
- # @param [Bool] show_output
122
+ # @param [Boolean] show_output
120
123
  #
121
124
  # @return [void]
122
125
  #
@@ -443,7 +443,7 @@ module Pod
443
443
  def merged_xcconfigs(xcconfig_values_by_consumer_by_key, attribute, overriding: {})
444
444
  xcconfig_values_by_consumer_by_key.each_with_object(overriding.dup) do |(key, values_by_consumer), xcconfig|
445
445
  uniq_values = values_by_consumer.values.uniq
446
- values_are_bools = uniq_values.all? { |v| v =~ /\A(yes|no)\z/i }
446
+ values_are_bools = uniq_values.all? { |v| v.is_a?(String) && v =~ /\A(yes|no)\z/i }
447
447
  if values_are_bools
448
448
  # Boolean build settings
449
449
  if uniq_values.count > 1
@@ -602,6 +602,11 @@ module Pod
602
602
  target.pod_target_srcroot
603
603
  end
604
604
 
605
+ # @return [String]
606
+ define_build_settings_method :pods_development_language, :build_setting => true do
607
+ '${DEVELOPMENT_LANGUAGE}'
608
+ end
609
+
605
610
  #-------------------------------------------------------------------------#
606
611
 
607
612
  # @!group Frameworks
@@ -938,6 +943,8 @@ module Pod
938
943
  define_build_settings_method :swift_include_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true do
939
944
  paths = dependent_targets.flat_map { |pt| pt.build_settings[@configuration].swift_include_paths_to_import }
940
945
  paths.concat swift_include_paths_to_import if non_library_xcconfig?
946
+ vendored_static_library_search_paths = dependent_targets.flat_map { |pt| pt.build_settings[@configuration].vendored_static_library_search_paths }
947
+ paths.concat vendored_static_library_search_paths
941
948
  paths.concat ['$(PLATFORM_DIR)/Developer/usr/lib'] if should_apply_xctunwrap_fix?
942
949
  paths
943
950
  end
@@ -1283,7 +1290,7 @@ module Pod
1283
1290
  define_build_settings_method :any_vendored_dynamic_artifacts?, :memoized => true do
1284
1291
  pod_targets.any? do |pt|
1285
1292
  pt.file_accessors.any? do |fa|
1286
- !fa.vendored_dynamic_artifacts.empty?
1293
+ !fa.vendored_dynamic_artifacts.empty? || !fa.vendored_dynamic_xcframeworks.empty?
1287
1294
  end
1288
1295
  end
1289
1296
  end
@@ -285,7 +285,7 @@ module Pod
285
285
  end
286
286
  end
287
287
 
288
- # @return [Bool] Whether or not this target should be built.
288
+ # @return [Boolean] Whether or not this target should be built.
289
289
  #
290
290
  # A target should not be built if it has no source files.
291
291
  #
@@ -947,7 +947,7 @@ module Pod
947
947
 
948
948
  # Checks if warnings should be inhibited for this pod.
949
949
  #
950
- # @return [Bool]
950
+ # @return [Boolean]
951
951
  #
952
952
  def inhibit_warnings?
953
953
  return @inhibit_warnings if defined? @inhibit_warnings
@@ -25,7 +25,7 @@ module Pod
25
25
  #
26
26
  attr_accessor :output_io
27
27
 
28
- # @return [Bool] Whether the wrapping of the strings to the width of the
28
+ # @return [Boolean] Whether the wrapping of the strings to the width of the
29
29
  # terminal should be disabled.
30
30
  #
31
31
  attr_accessor :disable_wrap
@@ -370,7 +370,7 @@ module Pod
370
370
  #
371
371
  # @param [String] message The message to print.
372
372
  # @param [Array] actions The actions that the user should take.
373
- # @param [Bool] verbose_only
373
+ # @param [Boolean] verbose_only
374
374
  # Restrict the appearance of the warning to verbose mode only
375
375
  #
376
376
  # return [void]