Class: Pod::Installer

Inherits:
Object
  • Object
show all
Includes:
Config::Mixin
Defined in:
lib/cocoapods/installer.rb,
lib/cocoapods/installer/xcode.rb,
lib/cocoapods/installer/analyzer.rb,
lib/cocoapods/installer/podfile_validator.rb,
lib/cocoapods/installer/pod_source_preparer.rb,
lib/cocoapods/installer/sandbox_dir_cleaner.rb,
lib/cocoapods/installer/analyzer/pod_variant.rb,
lib/cocoapods/installer/analyzer/specs_state.rb,
lib/cocoapods/installer/installation_options.rb,
lib/cocoapods/installer/pod_source_installer.rb,
lib/cocoapods/installer/pod_source_downloader.rb,
lib/cocoapods/installer/target_uuid_generator.rb,
lib/cocoapods/installer/xcode/target_validator.rb,
lib/cocoapods/installer/user_project_integrator.rb,
lib/cocoapods/installer/analyzer/analysis_result.rb,
lib/cocoapods/installer/analyzer/pod_variant_set.rb,
lib/cocoapods/installer/analyzer/sandbox_analyzer.rb,
lib/cocoapods/installer/analyzer/target_inspector.rb,
lib/cocoapods/installer/pre_install_hooks_context.rb,
lib/cocoapods/installer/base_install_hooks_context.rb,
lib/cocoapods/installer/post_install_hooks_context.rb,
lib/cocoapods/installer/pre_integrate_hooks_context.rb,
lib/cocoapods/installer/project_cache/project_cache.rb,
lib/cocoapods/installer/post_integrate_hooks_context.rb,
lib/cocoapods/installer/xcode/pods_project_generator.rb,
lib/cocoapods/installer/project_cache/target_metadata.rb,
lib/cocoapods/installer/source_provider_hooks_context.rb,
lib/cocoapods/installer/project_cache/target_cache_key.rb,
lib/cocoapods/installer/sandbox_header_paths_installer.rb,
lib/cocoapods/installer/analyzer/podfile_dependency_cache.rb,
lib/cocoapods/installer/analyzer/target_inspection_result.rb,
lib/cocoapods/installer/xcode/multi_pods_project_generator.rb,
lib/cocoapods/installer/project_cache/project_cache_version.rb,
lib/cocoapods/installer/xcode/pods_project_generator_result.rb,
lib/cocoapods/installer/xcode/single_pods_project_generator.rb,
lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb,
lib/cocoapods/installer/project_cache/project_cache_analyzer.rb,
lib/cocoapods/installer/project_cache/project_metadata_cache.rb,
lib/cocoapods/installer/project_cache/project_installation_cache.rb,
lib/cocoapods/installer/user_project_integrator/target_integrator.rb,
lib/cocoapods/installer/project_cache/project_cache_analysis_result.rb,
lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb,
lib/cocoapods/installer/xcode/pods_project_generator/project_generator.rb,
lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb,
lib/cocoapods/installer/xcode/pods_project_generator/pods_project_writer.rb,
lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb,
lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb,
lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb,
lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb,
lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb,
lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb,
lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb,
lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb,
lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_dependency_installer.rb

Overview

The Installer is responsible of taking a Podfile and transform it in the Pods libraries. It also integrates the user project so the Pods libraries can be used out of the box.

The Installer is capable of doing incremental updates to an existing Pod installation.

The Installer gets the information that it needs mainly from 3 files:

  • Podfile: The specification written by the user that contains information about targets and Pods.
  • Podfile.lock: Contains information about the pods that were previously installed and in concert with the Podfile provides information about which specific version of a Pod should be installed. This file is ignored in update mode.
  • Manifest.lock: A file contained in the Pods folder that keeps track of the pods installed in the local machine. This files is used once the exact versions of the Pods has been computed to detect if that version is already installed. This file is not intended to be kept under source control and is a copy of the Podfile.lock.

The Installer is designed to work in environments where the Podfile folder is under source control and environments where it is not. The rest of the files, like the user project and the workspace are assumed to be under source control.

Defined Under Namespace

Modules: ProjectCache Classes: Analyzer, BaseInstallHooksContext, InstallationOptions, PodSourceDownloader, PodSourceInstaller, PodSourcePreparer, PodfileValidator, PostInstallHooksContext, PostIntegrateHooksContext, PreInstallHooksContext, PreIntegrateHooksContext, SandboxDirCleaner, SandboxHeaderPathsInstaller, SourceProviderHooksContext, TargetUUIDGenerator, UserProjectIntegrator, Xcode

Installation steps collapse

DEFAULT_PLUGINS =
{}

Constant Summary collapse

MASTER_SPECS_REPO_GIT_URL =
'https://github.com/CocoaPods/Specs.git'.freeze

Installation results collapse

Instance Attribute Summary collapse

Installation steps collapse

Hooks collapse

Private helpers collapse

Convenience Methods collapse

Instance Method Summary collapse

Methods included from Config::Mixin

#config

Constructor Details

#initialize(sandbox, podfile, lockfile = nil) ⇒ Installer

Initialize a new instance

Parameters:

  • sandbox (Sandbox)

    @see #sandbox

  • podfile (Podfile)

    @see #podfile

  • lockfile (Lockfile) (defaults to: nil)

    @see #lockfile


76
77
78
79
80
81
82
83
84
# File 'lib/cocoapods/installer.rb', line 76

def initialize(sandbox, podfile, lockfile = nil)
  @sandbox  = sandbox || raise(ArgumentError, 'Missing required argument `sandbox`')
  @podfile  = podfile || raise(ArgumentError, 'Missing required argument `podfile`')
  @lockfile = lockfile

  @use_default_plugins = true
  @has_dependencies = true
  @pod_installers = []
end

Instance Attribute Details

#aggregate_targetsArray<AggregateTarget> (readonly)

Returns The model representations of an aggregation of pod targets generated for a target definition in the Podfile as result of the analyzer.

Returns:

  • (Array<AggregateTarget>)

    The model representations of an aggregation of pod targets generated for a target definition in the Podfile as result of the analyzer.


386
387
388
# File 'lib/cocoapods/installer.rb', line 386

def aggregate_targets
  @aggregate_targets
end

#analysis_resultAnalyzer::AnalysisResult (readonly)

Returns the result of the analysis performed during installation.

Returns:


367
368
369
# File 'lib/cocoapods/installer.rb', line 367

def analysis_result
  @analysis_result
end

#clean_installBoolean Also known as: clean_install?

when incremental installation is enabled.

Returns:

  • (Boolean)

    Whether installation should ignore the contents of the project cache


118
119
120
# File 'lib/cocoapods/installer.rb', line 118

def clean_install
  @clean_install
end

#deploymentBoolean Also known as: deployment?

Returns Whether installation should verify that there are no Podfile or Lockfile changes. Defaults to false.

Returns:

  • (Boolean)

    Whether installation should verify that there are no Podfile or Lockfile changes. Defaults to false.


112
113
114
# File 'lib/cocoapods/installer.rb', line 112

def deployment
  @deployment
end

#generated_aggregate_targetsArray<AggregateTarget> (readonly)

Returns The list of aggregate targets that were generated from the installation.

Returns:

  • (Array<AggregateTarget>)

    The list of aggregate targets that were generated from the installation.


403
404
405
# File 'lib/cocoapods/installer.rb', line 403

def generated_aggregate_targets
  @generated_aggregate_targets
end

#generated_pod_targetsArray<PodTarget> (readonly)

Returns The list of pod targets that were generated from the installation.

Returns:

  • (Array<PodTarget>)

    The list of pod targets that were generated from the installation.


399
400
401
# File 'lib/cocoapods/installer.rb', line 399

def generated_pod_targets
  @generated_pod_targets
end

#generated_projectsArray<Project> (readonly)

Returns The list of projects generated from the installation.

Returns:

  • (Array<Project>)

    The list of projects generated from the installation.


395
396
397
# File 'lib/cocoapods/installer.rb', line 395

def generated_projects
  @generated_projects
end

#has_dependenciesBoolean Also known as: has_dependencies?

Returns Whether it has dependencies. Defaults to true.

Returns:

  • (Boolean)

    Whether it has dependencies. Defaults to true.


95
96
97
# File 'lib/cocoapods/installer.rb', line 95

def has_dependencies
  @has_dependencies
end

#installation_cacheProjectInstallationCache (readonly, private)

Returns The installation cache stored in Pods/.project_cache/installation_cache.

Returns:

  • (ProjectInstallationCache)

    The installation cache stored in Pods/.project_cache/installation_cache


132
133
134
# File 'lib/cocoapods/installer.rb', line 132

def installation_cache
  @installation_cache
end

#installed_specsArray<Specification>

Returns The specifications that were installed.

Returns:

  • (Array<Specification>)

    The specifications that were installed.


407
408
409
# File 'lib/cocoapods/installer.rb', line 407

def installed_specs
  @installed_specs
end

#lockfileLockfile (readonly)

Returns The Lockfile that stores the information about the Pods previously installed on any machine.

Returns:

  • (Lockfile)

    The Lockfile that stores the information about the Pods previously installed on any machine.


68
69
70
# File 'lib/cocoapods/installer.rb', line 68

def lockfile
  @lockfile
end

#metadata_cacheProjectMetadataCache (readonly, private)

Returns The metadata cache stored in Pods/.project_cache/metadata_cache.

Returns:

  • (ProjectMetadataCache)

    The metadata cache stored in Pods/.project_cache/metadata_cache


136
137
138
# File 'lib/cocoapods/installer.rb', line 136

def 
  @metadata_cache
end

#pod_installersArray<PodSourceInstaller> (readonly, private)

Returns the pod installers created while installing pod targets.

Returns:


128
129
130
# File 'lib/cocoapods/installer.rb', line 128

def pod_installers
  @pod_installers
end

#pod_target_subprojectsArray<Pod::Project> (readonly)

Returns the subprojects nested under pods_project.

Returns:

  • (Array<Pod::Project>)

    the subprojects nested under pods_project.


380
381
382
# File 'lib/cocoapods/installer.rb', line 380

def pod_target_subprojects
  @pod_target_subprojects
end

#pod_targetsArray<PodTarget> (readonly)

Returns The model representations of pod targets generated as result of the analyzer.

Returns:

  • (Array<PodTarget>)

    The model representations of pod targets generated as result of the analyzer.


391
392
393
# File 'lib/cocoapods/installer.rb', line 391

def pod_targets
  @pod_targets
end

#podfilePodfile (readonly)

Returns The Podfile specification that contains the information of the Pods that should be installed.

Returns:

  • (Podfile)

    The Podfile specification that contains the information of the Pods that should be installed.


63
64
65
# File 'lib/cocoapods/installer.rb', line 63

def podfile
  @podfile
end

#pods_projectPod::Project (readonly)

Returns the Pods/Pods.xcodeproj project.

Returns:


376
377
378
# File 'lib/cocoapods/installer.rb', line 376

def pods_project
  @pods_project
end

#project_cache_versionProjectCacheVersion (readonly, private)

Returns The version of the project cache stored in Pods/.project_cache/version.

Returns:

  • (ProjectCacheVersion)

    The version of the project cache stored in Pods/.project_cache/version


140
141
142
# File 'lib/cocoapods/installer.rb', line 140

def project_cache_version
  @project_cache_version
end

#repo_updateBoolean Also known as: repo_update?

Returns Whether the spec repos should be updated.

Returns:

  • (Boolean)

    Whether the spec repos should be updated.


100
101
102
# File 'lib/cocoapods/installer.rb', line 100

def repo_update
  @repo_update
end

#sandboxSandbox (readonly)

Returns The sandbox where the Pods should be installed.

Returns:

  • (Sandbox)

    The sandbox where the Pods should be installed.


58
59
60
# File 'lib/cocoapods/installer.rb', line 58

def sandbox
  @sandbox
end

#target_installation_resultsArray<Hash{String, TargetInstallationResult}> (readonly)

Returns the installation results produced by the pods project generator.

Returns:

  • (Array<Hash{String, TargetInstallationResult}>)

    the installation results produced by the pods project generator


372
373
374
# File 'lib/cocoapods/installer.rb', line 372

def target_installation_results
  @target_installation_results
end

#updateHash, ...

Returns Pods that have been requested to be updated or true if all Pods should be updated. If all Pods should been updated the contents of the Lockfile are not taken into account for deciding what Pods to install.

Returns:

  • (Hash, Boolean, nil)

    Pods that have been requested to be updated or true if all Pods should be updated. If all Pods should been updated the contents of the Lockfile are not taken into account for deciding what Pods to install.


91
92
93
# File 'lib/cocoapods/installer.rb', line 91

def update
  @update
end

#use_default_pluginsBoolean Also known as: use_default_plugins?

Returns Whether default plugins should be used during installation. Defaults to true.

Returns:

  • (Boolean)

    Whether default plugins should be used during installation. Defaults to true.


106
107
108
# File 'lib/cocoapods/installer.rb', line 106

def use_default_plugins
  @use_default_plugins
end

Class Method Details

.targets_from_sandbox(sandbox, podfile, lockfile) ⇒ Object

Raises:


1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
# File 'lib/cocoapods/installer.rb', line 1093

def self.targets_from_sandbox(sandbox, podfile, lockfile)
  raise Informative, 'You must run `pod install` to be able to generate target information' unless lockfile

  new(sandbox, podfile, lockfile).instance_exec do
    plugin_sources = run_source_provider_hooks
    analyzer = create_analyzer(plugin_sources)
    analyze(analyzer)
    if analysis_result.podfile_needs_install?
      raise Pod::Informative, 'The Podfile has changed, you must run `pod install`'
    elsif analysis_result.sandbox_needs_install?
      raise Pod::Informative, 'The `Pods` directory is out-of-date, you must run `pod install`'
    end

    aggregate_targets
  end
end

Instance Method Details

#analyze(analyzer = create_analyzer) ⇒ void (private)

This method returns an undefined value.

Performs the analysis.

Parameters:

  • analyzer (Analyzer) (defaults to: create_analyzer)

    the analyzer to use for analysis


421
422
423
424
425
# File 'lib/cocoapods/installer.rb', line 421

def analyze(analyzer = create_analyzer)
  @analysis_result = analyzer.analyze
  @aggregate_targets = @analysis_result.targets
  @pod_targets = @analysis_result.pod_targets
end

#analyze_project_cacheObject


191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/cocoapods/installer.rb', line 191

def analyze_project_cache
  user_projects = aggregate_targets.map(&:user_project).compact.uniq
  object_version = user_projects.min_by { |p| p.object_version.to_i }.object_version.to_i unless user_projects.empty?

  if !installation_options.incremental_installation
    # Run entire installation.
    ProjectCache::ProjectCacheAnalysisResult.new(pod_targets, aggregate_targets, {},
                                                 analysis_result.all_user_build_configurations, object_version)
  else
    UI.message 'Analyzing Project Cache' do
      @installation_cache = ProjectCache::ProjectInstallationCache.from_file(sandbox, sandbox.project_installation_cache_path)
      @metadata_cache = ProjectCache::ProjectMetadataCache.from_file(sandbox, sandbox.)
      @project_cache_version = ProjectCache::ProjectCacheVersion.from_file(sandbox.project_version_cache_path)

      force_clean_install = clean_install || project_cache_version.version != Version.create(VersionMetadata.project_cache_version)
      cache_result = ProjectCache::ProjectCacheAnalyzer.new(sandbox, installation_cache, analysis_result.all_user_build_configurations,
                                                            object_version, plugins, pod_targets, aggregate_targets, installation_options.to_h, :clean_install => force_clean_install).analyze
      aggregate_targets_to_generate = cache_result.aggregate_targets_to_generate || []
      pod_targets_to_generate = cache_result.pod_targets_to_generate
      (aggregate_targets_to_generate + pod_targets_to_generate).each do |target|
        UI.message "- Regenerating #{target.label}"
      end
      cache_result
    end
  end
end

#any_plugin_post_install_hooks?Boolean (private)

Returns whether there are any plugin post-install hooks to run.

Returns:

  • (Boolean)

    whether there are any plugin post-install hooks to run


741
742
743
# File 'lib/cocoapods/installer.rb', line 741

def any_plugin_post_install_hooks?
  HooksManager.hooks_to_run(:post_install, plugins).any?
end

#any_plugin_post_integrate_hooks?Boolean (private)

Returns whether there are any plugin post-integrate hooks to run.

Returns:

  • (Boolean)

    whether there are any plugin post-integrate hooks to run


747
748
749
# File 'lib/cocoapods/installer.rb', line 747

def any_plugin_post_integrate_hooks?
  HooksManager.hooks_to_run(:post_integrate, plugins).any?
end

#any_plugin_pre_integrate_hooks?Boolean (private)

Returns whether there are any plugin pre-integrate hooks to run.

Returns:

  • (Boolean)

    whether there are any plugin pre-integrate hooks to run


735
736
737
# File 'lib/cocoapods/installer.rb', line 735

def any_plugin_pre_integrate_hooks?
  HooksManager.hooks_to_run(:pre_integrate, plugins).any?
end

#clean_pod_sourcesObject (private)

Cleans the sources of the Pods if the config instructs to do so.


639
640
641
642
643
# File 'lib/cocoapods/installer.rb', line 639

def clean_pod_sources
  return unless installation_options.clean?
  return if installed_specs.empty?
  pod_installers.each(&:clean!)
end

#clean_sandboxvoid (private)

This method returns an undefined value.

Returns Performs a general clean up of the sandbox related to the sandbox state that was calculated. For example, pods that were marked for deletion are removed.


455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
# File 'lib/cocoapods/installer.rb', line 455

def clean_sandbox
  unless sandbox_state.deleted.empty?
    title_options = { :verbose_prefix => '-> '.red }
    sandbox_state.deleted.each do |pod_name|
      UI.titled_section("Removing #{pod_name}".red, title_options) do
        root_name = Specification.root_name(pod_name)
        pod_dir = sandbox.local?(root_name) ? nil : sandbox.pod_dir(root_name)
        sandbox.clean_pod(pod_name, pod_dir)
      end
    end
  end

  # Check any changed pods that became local pods and used to be remote pods and
  # ensure the sandbox is cleaned up.
  unless sandbox_state.changed.empty?
    sandbox_state.changed.each do |pod_name|
      previous_spec_repo = sandbox.manifest.spec_repo(pod_name)
      should_clean = !previous_spec_repo.nil? && sandbox.local?(pod_name)
      sandbox.clean_pod(pod_name, sandbox.sources_root + Specification.root_name(pod_name)) if should_clean
    end
  end
end

#create_analyzer(plugin_sources = nil) ⇒ Object (private)


427
428
429
# File 'lib/cocoapods/installer.rb', line 427

def create_analyzer(plugin_sources = nil)
  Analyzer.new(sandbox, podfile, lockfile, plugin_sources, has_dependencies?, update)
end

#create_and_save_projects(pod_targets_to_generate, aggregate_targets_to_generate, build_configurations, project_object_version) ⇒ Object (private)


314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'lib/cocoapods/installer.rb', line 314

def create_and_save_projects(pod_targets_to_generate, aggregate_targets_to_generate, build_configurations, project_object_version)
  UI.section 'Generating Pods project' do
    generator = create_generator(pod_targets_to_generate, aggregate_targets_to_generate,
                                 build_configurations, project_object_version,
                                 installation_options.generate_multiple_pod_projects)

    pod_project_generation_result = generator.generate!
    @target_installation_results = pod_project_generation_result.target_installation_results
    @pods_project = pod_project_generation_result.project
    # The `pod_target_subprojects` is used for backwards compatibility so that consumers can iterate over
    # all pod targets across projects without needing to open each one.
    @pod_target_subprojects = pod_project_generation_result.projects_by_pod_targets.keys
    @generated_projects = ([pods_project] + pod_target_subprojects || []).compact
    @generated_pod_targets = pod_targets_to_generate
    @generated_aggregate_targets = aggregate_targets_to_generate || []
    projects_by_pod_targets = pod_project_generation_result.projects_by_pod_targets

    predictabilize_uuids(generated_projects) if installation_options.deterministic_uuids?
    stabilize_target_uuids(generated_projects)

    projects_writer = Xcode::PodsProjectWriter.new(sandbox, generated_projects,
                                                   target_installation_results.pod_target_installation_results, installation_options)
    projects_writer.write! do
      run_podfile_post_install_hooks
    end

    pods_project_pod_targets = pod_targets_to_generate - projects_by_pod_targets.values.flatten
    all_projects_by_pod_targets = {}
    pods_project_by_targets = { pods_project => pods_project_pod_targets } if pods_project
    all_projects_by_pod_targets.merge!(pods_project_by_targets) if pods_project_by_targets
    all_projects_by_pod_targets.merge!(projects_by_pod_targets) if projects_by_pod_targets
    all_projects_by_pod_targets.each do |project, pod_targets|
      generator.configure_schemes(project, pod_targets, pod_project_generation_result)
    end
  end
end

#create_generator(pod_targets_to_generate, aggregate_targets_to_generate, build_configurations, project_object_version, generate_multiple_pod_projects = false) ⇒ Object (private)


284
285
286
287
288
289
290
291
# File 'lib/cocoapods/installer.rb', line 284

def create_generator(pod_targets_to_generate, aggregate_targets_to_generate, build_configurations, project_object_version, generate_multiple_pod_projects = false)
  if generate_multiple_pod_projects
    Xcode::MultiPodsProjectGenerator.new(sandbox, aggregate_targets_to_generate, pod_targets_to_generate,
                                         build_configurations, installation_options, config, project_object_version, )
  else
    Xcode::SinglePodsProjectGenerator.new(sandbox, aggregate_targets_to_generate, pod_targets_to_generate, build_configurations, installation_options, config, project_object_version)
  end
end

#create_pod_downloader(pod_name) ⇒ Object (private)


584
585
586
587
588
589
590
591
592
593
594
595
596
# File 'lib/cocoapods/installer.rb', line 584

def create_pod_downloader(pod_name)
  specs_by_platform = specs_for_pod(pod_name)

  if specs_by_platform.empty?
    requiring_targets = pod_targets.select { |pt| pt.recursive_dependent_targets.any? { |dt| dt.pod_name == pod_name } }
    message = "Could not download '#{pod_name}' pod"
    message += ", depended upon by #{requiring_targets.to_sentence}" unless requiring_targets.empty?
    message += '. There is either no platform to build for, or no target to build.'
    raise StandardError, message
  end

  PodSourceDownloader.new(sandbox, podfile, specs_by_platform, :can_cache => installation_options.clean?)
end

#create_pod_installer(pod_name) ⇒ Object (private)


568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
# File 'lib/cocoapods/installer.rb', line 568

def create_pod_installer(pod_name)
  specs_by_platform = specs_for_pod(pod_name)

  if specs_by_platform.empty?
    requiring_targets = pod_targets.select { |pt| pt.recursive_dependent_targets.any? { |dt| dt.pod_name == pod_name } }
    message = "Could not install '#{pod_name}' pod"
    message += ", depended upon by #{requiring_targets.to_sentence}" unless requiring_targets.empty?
    message += '. There is either no platform to build for, or no target to build.'
    raise StandardError, message
  end

  pod_installer = PodSourceInstaller.new(sandbox, podfile, specs_by_platform, :can_cache => installation_options.clean?)
  pod_installers << pod_installer
  pod_installer
end

#deintegrate_if_different_major_versionvoid (private)

This method returns an undefined value.

Run the deintegrator against all projects in the installation root if the current CocoaPods major version part is different than the one in the lockfile.


767
768
769
770
771
772
773
774
775
776
777
778
# File 'lib/cocoapods/installer.rb', line 767

def deintegrate_if_different_major_version
  return unless lockfile
  return if lockfile.cocoapods_version.major == Version.create(VERSION).major
  UI.section('Re-creating CocoaPods due to major version update.') do
    projects = Pathname.glob(config.installation_root + '*.xcodeproj').map { |path| Xcodeproj::Project.open(path) }
    deintegrator = Deintegrator.new
    projects.each do |project|
      config.with_changes(:silent => true) { deintegrator.deintegrate_project(project) }
      project.save if project.dirty?
    end
  end
end

#development_pod_targets(targets = pod_targets) ⇒ Array<PodTarget>

Returns The targets of the development pods generated by the installation process. This can be used as a convenience method for external scripts.

Parameters:

  • targets (Array<PodTarget>) (defaults to: pod_targets)

Returns:

  • (Array<PodTarget>)

    The targets of the development pods generated by the installation process. This can be used as a convenience method for external scripts.


1056
1057
1058
1059
1060
# File 'lib/cocoapods/installer.rb', line 1056

def development_pod_targets(targets = pod_targets)
  targets.select do |pod_target|
    sandbox.local?(pod_target.pod_name)
  end
end

#download_dependenciesObject


256
257
258
259
260
261
262
# File 'lib/cocoapods/installer.rb', line 256

def download_dependencies
  UI.section 'Downloading dependencies' do
    install_pod_sources
    run_podfile_pre_install_hooks
    clean_pod_sources
  end
end

#download_source_of_pod(pod_name) ⇒ void (private)

This method returns an undefined value.

Download the pod unless it is local or has been predownloaded from an external source.


630
631
632
633
634
635
# File 'lib/cocoapods/installer.rb', line 630

def download_source_of_pod(pod_name)
  return if sandbox.local?(pod_name) || sandbox.predownloaded?(pod_name)

  pod_downloader = create_pod_downloader(pod_name)
  pod_downloader.download!
end

#ensure_plugins_are_installed!void (private)

This method returns an undefined value.

Ensures that all plugins specified in the #podfile are loaded.


784
785
786
787
788
789
790
791
792
793
794
# File 'lib/cocoapods/installer.rb', line 784

def ensure_plugins_are_installed!
  require 'claide/command/plugin_manager'

  loaded_plugins = Command::PluginManager.specifications.map(&:name)

  podfile.plugins.keys.each do |plugin|
    unless loaded_plugins.include? plugin
      raise Informative, "Your Podfile requires that the plugin `#{plugin}` be installed. Please install it and try installation again."
    end
  end
end

#generate_lockfileLockfile (private)

Returns The lockfile to write to disk.

Returns:

  • (Lockfile)

    The lockfile to write to disk.


868
869
870
871
872
# File 'lib/cocoapods/installer.rb', line 868

def generate_lockfile
  external_source_pods = analysis_result.podfile_dependency_cache.podfile_dependencies.select(&:external_source).map(&:root_name).uniq
  checkout_options = sandbox.checkout_sources.select { |root_name, _| external_source_pods.include? root_name }
  Lockfile.generate(podfile, analysis_result.specifications, checkout_options, analysis_result.specs_by_source)
end

#generate_pods_projectObject (private)

Generates the Xcode project(s) that go inside the Pods/ directory.


295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/cocoapods/installer.rb', line 295

def generate_pods_project
  stage_sandbox(sandbox, pod_targets)

  cache_analysis_result = analyze_project_cache
  pod_targets_to_generate = cache_analysis_result.pod_targets_to_generate
  aggregate_targets_to_generate = cache_analysis_result.aggregate_targets_to_generate

  pod_targets_to_generate.each do |pod_target|
    pod_target.build_headers.implode_path!(pod_target.headers_sandbox)
    sandbox.public_headers.implode_path!(pod_target.headers_sandbox)
  end

  create_and_save_projects(pod_targets_to_generate, aggregate_targets_to_generate,
                           cache_analysis_result.build_configurations, cache_analysis_result.project_object_version)
  SandboxDirCleaner.new(sandbox, pod_targets, aggregate_targets).clean!

  update_project_cache(cache_analysis_result, target_installation_results)
end

#install!void

This method returns an undefined value.

Installs the Pods.

The installation process is mostly linear with a few minor complications to keep in mind:

  • The stored podspecs need to be cleaned before the resolution step otherwise the sandbox might return an old podspec and not download the new one from an external source.
  • The resolver might trigger the download of Pods from external sources necessary to retrieve their podspec (unless it is instructed not to do it).

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/cocoapods/installer.rb', line 160

def install!
  prepare
  resolve_dependencies
  download_dependencies
  validate_targets
  clean_sandbox
  if installation_options.skip_pods_project_generation?
    show_skip_pods_project_generation_message
    run_podfile_post_install_hooks
  else
    integrate
  end
  write_lockfiles
  perform_post_install_actions
end

#install_pod_sourcesvoid (private)

This method returns an undefined value.

Downloads, installs the documentation and cleans the sources of the Pods which need to be installed.


505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
# File 'lib/cocoapods/installer.rb', line 505

def install_pod_sources
  @downloaded_specs = []
  @installed_specs = []
  pods_to_install = sandbox_state.added | sandbox_state.changed
  title_options = { :verbose_prefix => '-> '.green }

  sorted_root_specs = root_specs.sort_by(&:name)

  # Download pods in parallel before installing if the option is set
  if installation_options.parallel_pod_downloads
    require 'concurrent/executor/fixed_thread_pool'
    thread_pool_size = installation_options.parallel_pod_download_thread_pool_size
    thread_pool = Concurrent::FixedThreadPool.new(thread_pool_size, :idletime => 300)

    sorted_root_specs.each do |spec|
      if pods_to_install.include?(spec.name)
        title = section_title(spec, 'Downloading')
        UI.titled_section(title.green, title_options) do
          thread_pool.post do
            download_source_of_pod(spec.name)
          end
        end
      end
    end

    thread_pool.shutdown
    thread_pool.wait_for_termination
  end

  # Install pods, which includes downloading only if parallel_pod_downloads is set to false
  sorted_root_specs.each do |spec|
    if pods_to_install.include?(spec.name)
      title = section_title(spec, 'Installing')
      UI.titled_section(title.green, title_options) do
        install_source_of_pod(spec.name)
      end
    else
      UI.section("Using #{spec}", title_options[:verbose_prefix]) do
        create_pod_installer(spec.name)
      end
    end
  end
end

#install_source_of_pod(pod_name) ⇒ void (private)

This method returns an undefined value.

Install the Pods. If the resolver indicated that a Pod should be installed and it exits, it is removed and then reinstalled. In any case if the Pod doesn't exits it is installed.


619
620
621
622
623
# File 'lib/cocoapods/installer.rb', line 619

def install_source_of_pod(pod_name)
  pod_installer = create_pod_installer(pod_name)
  pod_installer.install!
  @installed_specs.concat(pod_installer.specs_by_platform.values.flatten.uniq)
end

#installation_optionsInstallationOptions (private)

Returns the installation options to use during install.

Returns:


1083
1084
1085
# File 'lib/cocoapods/installer.rb', line 1083

def installation_options
  podfile.installation_options
end

#integrateObject


181
182
183
184
185
186
187
188
189
# File 'lib/cocoapods/installer.rb', line 181

def integrate
  run_podfile_pre_integrate_hooks
  generate_pods_project
  if installation_options.integrate_targets?
    integrate_user_project
  else
    UI.section 'Skipping User Project Integration'
  end
end

#integrate_user_projectvoid (private)

This method returns an undefined value.

Integrates the user projects adding the dependencies on the CocoaPods libraries, setting them up to use the xcconfigs and performing other actions. This step is also responsible of creating the workspace if needed.


924
925
926
927
928
929
930
931
932
# File 'lib/cocoapods/installer.rb', line 924

def integrate_user_project
  UI.section "Integrating client #{'project'.pluralize(aggregate_targets.map(&:user_project_path).uniq.count)}" do
    installation_root = config.installation_root
    integrator = UserProjectIntegrator.new(podfile, sandbox, installation_root, aggregate_targets, generated_aggregate_targets,
                                           :use_input_output_paths => !installation_options.disable_input_output_paths?)
    integrator.integrate!
    run_podfile_post_integrate_hooks
  end
end

#lock_pod_sourcesObject (private)

Locks the sources of the Pods if the config instructs to do so.


656
657
658
659
660
661
662
# File 'lib/cocoapods/installer.rb', line 656

def lock_pod_sources
  return unless installation_options.lock_pod_sources?
  pod_installers.each do |installer|
    pod_target = pod_targets.find { |target| target.pod_name == installer.name }
    installer.lock_files!(pod_target.file_accessors)
  end
end

#perform_post_install_actionsvoid (private)

This method returns an undefined value.

Performs any post-installation actions


682
683
684
685
686
687
688
# File 'lib/cocoapods/installer.rb', line 682

def perform_post_install_actions
  run_plugins_post_install_hooks
  warn_for_deprecations
  warn_for_installed_script_phases
  warn_for_removing_git_master_specs_repo
  print_post_install_message
end

#pluginsHash<String, Hash> (private)

Returns the plugins that should be run, as indicated by the default plugins and the podfile's plugins

Returns:

  • (Hash<String, Hash>)

    The plugins to be used


803
804
805
806
807
808
809
# File 'lib/cocoapods/installer.rb', line 803

def plugins
  if use_default_plugins?
    DEFAULT_PLUGINS.merge(podfile.plugins)
  else
    podfile.plugins
  end
end

#predictabilize_uuids(projects) ⇒ Object (private)


351
352
353
# File 'lib/cocoapods/installer.rb', line 351

def predictabilize_uuids(projects)
  UI.message('- Generating deterministic UUIDs') { Xcodeproj::Project.predictabilize_uuids(projects) }
end

#prepareObject


218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/cocoapods/installer.rb', line 218

def prepare
  # Raise if pwd is inside Pods
  if Dir.pwd.start_with?(sandbox.root.to_path)
    message = 'Command should be run from a directory outside Pods directory.'
    message << "\n\n\tCurrent directory is #{UI.path(Pathname.pwd)}\n"
    raise Informative, message
  end
  UI.message 'Preparing' do
    deintegrate_if_different_major_version
    sandbox.prepare
    ensure_plugins_are_installed!
    run_plugins_pre_install_hooks
  end
end

#print_post_install_messageObject (private)


690
691
692
693
694
695
696
697
698
699
# File 'lib/cocoapods/installer.rb', line 690

def print_post_install_message
  podfile_dependencies = analysis_result.podfile_dependency_cache.podfile_dependencies.size
  pods_installed = root_specs.size
  title_options = { :verbose_prefix => '-> '.green }
  UI.titled_section('Pod installation complete! ' \
                    "There #{podfile_dependencies == 1 ? 'is' : 'are'} #{podfile_dependencies} " \
                    "#{'dependency'.pluralize(podfile_dependencies)} from the Podfile " \
                    "and #{pods_installed} total #{'pod'.pluralize(pods_installed)} installed.".green,
                    title_options)
end

#resolve_dependenciesAnalyzer

Returns The analyzer used to resolve dependencies.

Returns:

  • (Analyzer)

    The analyzer used to resolve dependencies


235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/cocoapods/installer.rb', line 235

def resolve_dependencies
  plugin_sources = run_source_provider_hooks
  analyzer = create_analyzer(plugin_sources)

  UI.section 'Updating local specs repositories' do
    analyzer.update_repositories
  end if repo_update?

  UI.section 'Analyzing dependencies' do
    analyze(analyzer)
    validate_build_configurations
  end

  UI.section 'Verifying no changes' do
    verify_no_podfile_changes!
    verify_no_lockfile_changes!
  end if deployment?

  analyzer
end

#root_specsArray<Specification> (private)

Returns All the root specifications of the installation.

Returns:

  • (Array<Specification>)

    All the root specifications of the installation.


1071
1072
1073
# File 'lib/cocoapods/installer.rb', line 1071

def root_specs
  analysis_result.specifications.map(&:root).uniq
end

#run_plugins_post_install_hooksObject (private)

Runs the registered callbacks for the plugins post install hooks.


712
713
714
715
716
717
718
719
720
721
722
# File 'lib/cocoapods/installer.rb', line 712

def run_plugins_post_install_hooks
  # This short-circuits because unlocking pod sources is expensive
  if any_plugin_post_install_hooks?
    unlock_pod_sources

    context = PostInstallHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
    HooksManager.run(:post_install, context, plugins)
  end

  lock_pod_sources
end

#run_plugins_post_integrate_hooksObject (private)

Runs the registered callbacks for the plugins post integrate hooks.


726
727
728
729
730
731
# File 'lib/cocoapods/installer.rb', line 726

def run_plugins_post_integrate_hooks
  if any_plugin_post_integrate_hooks?
    context = PostIntegrateHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
    HooksManager.run(:post_integrate, context, plugins)
  end
end

#run_plugins_pre_install_hooksvoid (private)

This method returns an undefined value.

Runs the registered callbacks for the plugins pre install hooks.


673
674
675
676
# File 'lib/cocoapods/installer.rb', line 673

def run_plugins_pre_install_hooks
  context = PreInstallHooksContext.generate(sandbox, podfile, lockfile)
  HooksManager.run(:pre_install, context, plugins)
end

#run_plugins_pre_integrate_hooksObject (private)

Runs the registered callbacks for the plugins pre integrate hooks.


703
704
705
706
707
708
# File 'lib/cocoapods/installer.rb', line 703

def run_plugins_pre_integrate_hooks
  if any_plugin_pre_integrate_hooks?
    context = PreIntegrateHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
    HooksManager.run(:pre_integrate, context, plugins)
  end
end

#run_podfile_post_install_hookBoolean (private)

Runs the post install hook of the Podfile

Returns:

  • (Boolean)

    Whether the hook was run.

Raises:

  • Raises an informative if the hooks raises.


1012
1013
1014
1015
1016
1017
1018
# File 'lib/cocoapods/installer.rb', line 1012

def run_podfile_post_install_hook
  podfile.post_install!(self)
rescue => e
  raise Informative, 'An error occurred while processing the post-install ' \
    'hook of the Podfile.' \
    "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
end

#run_podfile_post_install_hooksvoid (private)

Note:

Post install hooks run before saving of project, so that they can alter it before it is written to the disk.

This method returns an undefined value.

Runs the post install hooks of the installed specs and of the Podfile.


999
1000
1001
1002
1003
1004
# File 'lib/cocoapods/installer.rb', line 999

def run_podfile_post_install_hooks
  UI.message '- Running post install hooks' do
    executed = run_podfile_post_install_hook
    UI.message '- Podfile' if executed
  end
end

#run_podfile_post_integrate_hookBoolean (private)

Runs the post integrate hook of the Podfile.

Returns:

  • (Boolean)

    Whether the hook was run.

Raises:

  • Raises an informative if the hooks raises.


1040
1041
1042
1043
1044
1045
1046
# File 'lib/cocoapods/installer.rb', line 1040

def run_podfile_post_integrate_hook
  podfile.post_integrate!(self)
rescue => e
  raise Informative, 'An error occurred while processing the post-integrate ' \
    'hook of the Podfile.' \
    "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
end

#run_podfile_post_integrate_hooksvoid (private)

Note:

Post integrate hooks run after saving of project, so that they can alter it after it is written to the disk.

This method returns an undefined value.

Runs the post integrate hooks of the installed specs and of the Podfile.


1027
1028
1029
1030
1031
1032
# File 'lib/cocoapods/installer.rb', line 1027

def run_podfile_post_integrate_hooks
  UI.message '- Running post integrate hooks' do
    executed = run_podfile_post_integrate_hook
    UI.message '- Podfile' if executed
  end
end

#run_podfile_pre_install_hookBoolean (private)

Runs the pre install hook of the Podfile

Returns:

  • (Boolean)

    Whether the hook was run.

Raises:

  • Raises an informative if the hooks raises.


957
958
959
960
961
962
963
# File 'lib/cocoapods/installer.rb', line 957

def run_podfile_pre_install_hook
  podfile.pre_install!(self)
rescue => e
  raise Informative, 'An error occurred while processing the pre-install ' \
    'hook of the Podfile.' \
    "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
end

#run_podfile_pre_install_hooksvoid (private)

This method returns an undefined value.

Runs the pre install hooks of the installed specs and of the Podfile.


944
945
946
947
948
949
# File 'lib/cocoapods/installer.rb', line 944

def run_podfile_pre_install_hooks
  UI.message '- Running pre install hooks' do
    executed = run_podfile_pre_install_hook
    UI.message '- Podfile' if executed
  end
end

#run_podfile_pre_integrate_hookBoolean (private)

Runs the pre integrate hook of the Podfile.

Returns:

  • (Boolean)

    Whether the hook was run.

Raises:

  • Raises an informative if the hooks raises.


984
985
986
987
988
989
990
# File 'lib/cocoapods/installer.rb', line 984

def run_podfile_pre_integrate_hook
  podfile.pre_integrate!(self)
rescue => e
  raise Informative, 'An error occurred while processing the pre-integrate ' \
    'hook of the Podfile.' \
    "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
end

#run_podfile_pre_integrate_hooksvoid (private)

Note:

Pre integrate hooks run before generation of the Pods project.

This method returns an undefined value.

Runs the pre integrate hooks of the installed specs and of the Podfile.


971
972
973
974
975
976
# File 'lib/cocoapods/installer.rb', line 971

def run_podfile_pre_integrate_hooks
  UI.message '- Running pre integrate hooks' do
    executed = run_podfile_pre_integrate_hook
    UI.message '- Podfile' if executed
  end
end

#run_source_provider_hooksArray<Pod::Source> (private)

Runs the registered callbacks for the source provider plugin hooks.

Returns:


755
756
757
758
759
# File 'lib/cocoapods/installer.rb', line 755

def run_source_provider_hooks
  context = SourceProviderHooksContext.generate
  HooksManager.run(:source_provider, context, plugins)
  context.sources
end

#sandbox_stateSpecsState (private)

Returns The state of the sandbox returned by the analyzer.

Returns:

  • (SpecsState)

    The state of the sandbox returned by the analyzer.


1077
1078
1079
# File 'lib/cocoapods/installer.rb', line 1077

def sandbox_state
  analysis_result.sandbox_state
end

#section_title(spec, current_action) ⇒ Object (private)


549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
# File 'lib/cocoapods/installer.rb', line 549

def section_title(spec, current_action)
  if sandbox_state.changed.include?(spec.name) && sandbox.manifest
    current_version = spec.version
    previous_version = sandbox.manifest.version(spec.name)
    has_changed_version = current_version != previous_version
    current_repo = analysis_result.specs_by_source.detect { |key, values| break key if values.map(&:name).include?(spec.name) }
    current_repo &&= (Pod::TrunkSource::TRUNK_REPO_NAME if current_repo.name == Pod::TrunkSource::TRUNK_REPO_NAME) || current_repo.url || current_repo.name
    previous_spec_repo = sandbox.manifest.spec_repo(spec.name)
    has_changed_repo = !previous_spec_repo.nil? && current_repo && !current_repo.casecmp(previous_spec_repo).zero?
    title = "#{current_action} #{spec.name} #{spec.version}"
    title << " (was #{previous_version} and source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if has_changed_version && has_changed_repo
    title << " (was #{previous_version})" if has_changed_version && !has_changed_repo
    title << " (source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if !has_changed_version && has_changed_repo
  else
    title = "#{current_action} #{spec}"
  end
  title
end

#show_skip_pods_project_generation_messageObject


176
177
178
179
# File 'lib/cocoapods/installer.rb', line 176

def show_skip_pods_project_generation_message
  UI.section 'Skipping Pods Project Creation'
  UI.section 'Skipping User Project Integration'
end

#specs_for_pod(pod_name) ⇒ Hash{Platform => Array<Specification>} (private)

The specifications matching the specified pod name

Parameters:

  • pod_name (String)

    the name of the pod

Returns:

  • (Hash{Platform => Array<Specification>})

    the specifications grouped by platform


604
605
606
607
608
609
610
611
# File 'lib/cocoapods/installer.rb', line 604

def specs_for_pod(pod_name)
  pod_targets.each_with_object({}) do |pod_target, hash|
    if pod_target.root_spec.name == pod_name
      hash[pod_target.platform] ||= []
      hash[pod_target.platform].concat(pod_target.specs)
    end
  end
end

#stabilize_target_uuids(projects) ⇒ Object (private)


355
356
357
# File 'lib/cocoapods/installer.rb', line 355

def stabilize_target_uuids(projects)
  UI.message('- Stabilizing target UUIDs') { TargetUUIDGenerator.new(projects).generate! }
end

#stage_sandbox(sandbox, pod_targets) ⇒ void

This method returns an undefined value.

Stages the sandbox after analysis.

Parameters:

  • sandbox (Sandbox)

    The sandbox to stage.

  • pod_targets (Array<PodTarget>)

    The list of all pod targets.


274
275
276
# File 'lib/cocoapods/installer.rb', line 274

def stage_sandbox(sandbox, pod_targets)
  SandboxHeaderPathsInstaller.new(sandbox, pod_targets).install!
end

#unlock_pod_sourcesObject (private)

Unlocks the sources of the Pods.


647
648
649
650
651
652
# File 'lib/cocoapods/installer.rb', line 647

def unlock_pod_sources
  pod_installers.each do |installer|
    pod_target = pod_targets.find { |target| target.pod_name == installer.name }
    installer.unlock_files!(pod_target.file_accessors)
  end
end

#update_project_cache(cache_analysis_result, target_installation_results) ⇒ Object (private)

Parameters:

  • cache_analysis_result (ProjectCacheAnalysisResult)

    The cache analysis result for the current installation.

  • target_installation_results (Hash{String => TargetInstallationResult})

    The installation results for pod targets installed.


900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
# File 'lib/cocoapods/installer.rb', line 900

def update_project_cache(cache_analysis_result, target_installation_results)
  return unless installation_cache || 
  installation_cache.update_cache_key_by_target_label!(cache_analysis_result.cache_key_by_target_label)
  installation_cache.update_project_object_version!(cache_analysis_result.project_object_version)
  installation_cache.update_build_configurations!(cache_analysis_result.build_configurations)
  installation_cache.update_podfile_plugins!(plugins)
  installation_cache.update_installation_options!(installation_options.to_h)
  installation_cache.save_as(sandbox.project_installation_cache_path)

  .update_metadata!(target_installation_results.pod_target_installation_results || {},
                                  target_installation_results.aggregate_target_installation_results || {})
  .save_as(sandbox.)

  cache_version = ProjectCache::ProjectCacheVersion.new(VersionMetadata.project_cache_version)
  cache_version.save_as(sandbox.project_version_cache_path)
end

#validate_build_configurationsObject (private)

Ensures that the white-listed build configurations are known to prevent silent typos.

Raises:

  • If an unknown user configuration is found.


436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
# File 'lib/cocoapods/installer.rb', line 436

def validate_build_configurations
  whitelisted_configs = pod_targets.
    flat_map(&:target_definitions).
    flat_map(&:all_whitelisted_configurations).
    map(&:downcase).
    uniq
  all_user_configurations = analysis_result.all_user_build_configurations.keys.map(&:downcase)

  remainder = whitelisted_configs - all_user_configurations
  unless remainder.empty?
    raise Informative,
          "Unknown #{'configuration'.pluralize(remainder.size)} whitelisted: #{remainder.sort.to_sentence}. " \
          "CocoaPods found #{all_user_configurations.sort.to_sentence}, did you mean one of these?"
  end
end

#validate_targetsObject (private)


664
665
666
667
# File 'lib/cocoapods/installer.rb', line 664

def validate_targets
  validator = Xcode::TargetValidator.new(aggregate_targets, pod_targets, installation_options)
  validator.validate!
end

#verify_no_lockfile_changes!Object (private)

Raises:


489
490
491
492
493
494
495
496
497
498
# File 'lib/cocoapods/installer.rb', line 489

def verify_no_lockfile_changes!
  new_lockfile = generate_lockfile
  return if new_lockfile == lockfile

  return unless diff = Xcodeproj::Differ.hash_diff(lockfile.to_hash, new_lockfile.to_hash, :key_1 => 'Old Lockfile', :key_2 => 'New Lockfile')
  pretty_diff = YAMLHelper.convert_hash(diff, Lockfile::HASH_KEY_ORDER, "\n\n")
  pretty_diff.gsub!(':diff:', 'diff:'.yellow)

  raise Informative, "There were changes to the lockfile in deployment mode:\n#{pretty_diff}"
end

#verify_no_podfile_changes!Object (private)

Raises:


480
481
482
483
484
485
# File 'lib/cocoapods/installer.rb', line 480

def verify_no_podfile_changes!
  return unless analysis_result.podfile_needs_install?

  changed_state = analysis_result.podfile_state.to_s(:states => %i(added deleted changed))
  raise Informative, "There were changes to the podfile in deployment mode:\n#{changed_state}"
end

#warn_for_deprecationsvoid (private)

This method returns an undefined value.

Prints a warning for any pods that are deprecated


815
816
817
818
819
820
821
822
823
824
825
826
827
# File 'lib/cocoapods/installer.rb', line 815

def warn_for_deprecations
  deprecated_pods = root_specs.select do |spec|
    spec.deprecated || spec.deprecated_in_favor_of
  end
  deprecated_pods.each do |spec|
    if spec.deprecated_in_favor_of
      UI.warn "#{spec.name} has been deprecated in " \
        "favor of #{spec.deprecated_in_favor_of}"
    else
      UI.warn "#{spec.name} has been deprecated"
    end
  end
end

#warn_for_installed_script_phasesvoid (private)

This method returns an undefined value.

Prints a warning for any pods that included script phases


833
834
835
836
837
838
839
840
841
842
843
844
# File 'lib/cocoapods/installer.rb', line 833

def warn_for_installed_script_phases
  pods_to_install = sandbox_state.added | sandbox_state.changed
  pod_targets.group_by(&:pod_name).each do |name, pod_targets|
    if pods_to_install.include?(name) && !sandbox.local?(name)
      script_phase_count = pod_targets.inject(0) { |sum, target| sum + target.script_phases.count }
      unless script_phase_count.zero?
        UI.warn "#{name} has added #{script_phase_count} #{'script phase'.pluralize(script_phase_count)}. " \
          'Please inspect before executing a build. See `https://guides.cocoapods.org/syntax/podspec.html#script_phases` for more information.'
      end
    end
  end
end

#warn_for_removing_git_master_specs_repovoid (private)

This method returns an undefined value.

Prints a warning if the project is not explicitly using the git based master specs repo.

Helps users to delete the git based master specs repo from the repos directory which reduces --repo-update speed and hopefully reduces Github workload.


853
854
855
856
857
858
859
860
861
862
863
864
# File 'lib/cocoapods/installer.rb', line 853

def warn_for_removing_git_master_specs_repo
  return unless installation_options.warn_for_unused_master_specs_repo?
  plugin_sources = run_source_provider_hooks
  all_sources = podfile.sources + plugin_sources.map(&:url)
  master_source = all_sources.find { |source| source == MASTER_SPECS_REPO_GIT_URL }
  master_repo = config.sources_manager.all.find { |s| s.url == MASTER_SPECS_REPO_GIT_URL }
  if master_source.nil? && !master_repo.nil?
    UI.warn 'Your project does not explicitly specify the CocoaPods master specs repo. Since CDN is now used as the' \
    ' default, you may safely remove it from your repos directory via `pod repo remove master`. To suppress this warning' \
    ' please add `warn_for_unused_master_specs_repo => false` to your Podfile.'
  end
end

#write_lockfilesvoid (private)

This method returns an undefined value.

Writes the Podfile and the lock files.


878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
# File 'lib/cocoapods/installer.rb', line 878

def write_lockfiles
  @lockfile = generate_lockfile

  UI.message "- Writing Lockfile in #{UI.path config.lockfile_path}" do
    # No need to invoke Sandbox#update_changed_file here since this logic already handles checking if the
    # contents of the file are the same.
    @lockfile.write_to_disk(config.lockfile_path)
  end

  UI.message "- Writing Manifest in #{UI.path sandbox.manifest_path}" do
    # No need to invoke Sandbox#update_changed_file here since this logic already handles checking if the
    # contents of the file are the same.
    @lockfile.write_to_disk(sandbox.manifest_path)
  end
end