Class: Pod::Installer::Analyzer
- Inherits:
-
Object
- Object
- Pod::Installer::Analyzer
- Includes:
- Config::Mixin
- Defined in:
- lib/cocoapods/installer/analyzer.rb,
lib/cocoapods/installer/analyzer/pod_variant.rb,
lib/cocoapods/installer/analyzer/specs_state.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/analyzer/podfile_dependency_cache.rb,
lib/cocoapods/installer/analyzer/target_inspection_result.rb,
lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb
Overview
Analyzes the Podfile, the Lockfile, and the sandbox manifest to generate the information relative to a CocoaPods installation.
Defined Under Namespace
Modules: LockingDependencyAnalyzer Classes: AnalysisResult, PodVariant, PodVariantSet, PodfileDependencyCache, SandboxAnalyzer, SpecsState, TargetInspectionResult, TargetInspector
Constant Summary collapse
- IOS_64_BIT_ONLY_VERSION =
Returns The version of iOS which requires binaries with only 64-bit architectures.
Version.new('11.0')
- IOS_64_BIT_ONLY_PROJECT_VERSION =
Xcode 10 will automatically select the correct architectures based on deployment target
50
Instance Attribute Summary collapse
-
#has_dependencies ⇒ Boolean
(also: #has_dependencies?)
readonly
Whether the analysis has dependencies and thus sources must be configured.
-
#installation_options ⇒ InstallationOptions
readonly
The installation options specified by the Podfile.
-
#lockfile ⇒ Lockfile?
readonly
The Lockfile, if available, that stores the information about the Pods previously installed.
-
#plugin_sources ⇒ Array<Source>
readonly
Sources provided by plugins or
nil
. -
#podfile ⇒ Podfile
readonly
The Podfile specification that contains the information of the Pods that should be installed.
-
#pods_to_update ⇒ Hash, ...
readonly
Pods that have been requested to be updated or true if all Pods should be updated.
-
#sandbox ⇒ Sandbox
readonly
The sandbox to use for this analysis.
-
#sources_manager ⇒ Source::Manager
readonly
The sources manager to use when resolving dependencies.
Configuration collapse
- #podfile_dependencies ⇒ Object private
-
#update_mode ⇒ Symbol
private
Whether and how the dependencies in the Podfile should be updated.
-
#update_mode? ⇒ Boolean
private
Whether the version of the dependencies which did not change in the Podfile should be locked.
-
#validate_podfile! ⇒ Object
private
-----------------------------------------------------------------------#.
Analysis steps collapse
-
.requires_64_bit_archs?(platform, object_version) ⇒ Boolean
Whether the platform requires 64-bit architectures.
-
#analyze_host_targets_in_podfile(aggregate_targets, embedded_aggregate_targets) ⇒ Object
private
Raises an error if there are embedded targets in the Podfile, but their host targets have not been declared in the Podfile.
- #checkout_requires_update?(dependency) ⇒ Boolean private
-
#compute_pod_target_dependencies(pod_targets, all_specs) ⇒ Array<PodTarget>
private
Compute the dependencies for the set of pod targets.
-
#create_file_accessors(specs, platform) ⇒ Array<FileAccessor>
private
Creates the file accessors for a given pod.
-
#dependencies_for_specs(specs, platform, all_specs) ⇒ Hash{Symbol => Set<Specification>}
private
Returns the specs upon which the given specs directly depend.
- #dependencies_to_fetch(podfile_state) ⇒ Object private
-
#determine_build_type(spec, target_definition_build_type) ⇒ BuildType
private
Calculates and returns the #BuildType to use for the given spec.
-
#determine_platform(specs, target_definitions, build_type) ⇒ Platform
private
Calculates and returns the platform to use for the given list specs and target definitions.
-
#determine_swift_version(spec, target_definitions) ⇒ String?
private
Determines the Swift version for the given spec within a list of target definitions.
-
#embedded_target_pod_targets_by_host(aggregate_target, embedded_aggregate_targets, libraries_only) ⇒ Hash{String=>Array<PodTarget>}
private
Copies the pod targets of any of the app embedded aggregate targets into their potential host aggregate target, if that potential host aggregate target's user_target hosts any of the app embedded aggregate targets' user_targets.
- #fetch_external_source(dependency, use_lockfile_options) ⇒ Object private
-
#fetch_external_sources(podfile_state) ⇒ void
private
Fetches the podspecs of external sources if modifications to the sandbox are allowed.
- #filter_dependencies(dependencies, pod_targets_by_name, target) ⇒ Object private
-
#filter_pod_targets_for_target_definition(target_definition, pod_targets_by_target_definition, build_configurations) ⇒ Hash{String => Array<PodTarget>}
private
Returns a filtered list of pod targets that should or should not be part of the target definition.
-
#generate_aggregate_target(target_definition, target_inspections, pod_targets_by_target_definition) ⇒ AggregateTarget
private
Setup the aggregate target for a single user target.
-
#generate_pod_target(target_definitions, build_type, target_inspections, specs, scope_suffix: nil, swift_version: nil) ⇒ PodTarget
private
Create a target for each spec group.
-
#generate_pod_targets(resolver_specs_by_target, target_inspections) ⇒ Array<PodTarget>
private
Setup the pod targets for an aggregate target.
-
#generate_podfile_state ⇒ SpecsState, SpecState
private
Compares the Podfile with the Lockfile in order to detect which dependencies should be locked.
-
#generate_sandbox_state(specifications) ⇒ SpecsState
private
Computes the state of the sandbox respect to the resolved specifications.
-
#generate_specifications(resolver_specs_by_target) ⇒ Array<Specification>
private
Returns the list of all the resolved specifications.
-
#generate_targets(resolver_specs_by_target, target_inspections) ⇒ (Array<AggregateTarget>, Array<PodTarget>)
private
Creates the models that represent the targets generated by CocoaPods.
-
#generate_version_locking_dependencies(podfile_state) ⇒ Molinillo::DependencyGraph<Dependency>
private
Generates dependencies that require the specific version of the Pods that haven't changed in the Lockfile.
-
#group_pod_targets_by_target_definition(pod_targets, resolver_specs_by_target) ⇒ Hash{TargetDefinition => Array<PodTarget>}
private
Returns a filtered list of pod targets that should or should not be part of the target definition.
- #pods_to_fetch(podfile_state) ⇒ Object private
-
#resolve_dependencies(locked_dependencies) ⇒ Hash{TargetDefinition => Array<Spec>}
private
Converts the Podfile in a list of specifications grouped by target.
- #store_existing_checkout_options ⇒ Object private
- #validate_lockfile_version! ⇒ Object private
-
#validate_platforms(resolver_specs_by_target) ⇒ Object
private
Warns for any specification that is incompatible with its target.
- #verify_no_pods_with_different_sources! ⇒ Object private
Analysis sub-steps collapse
-
#inspect_targets_to_integrate ⇒ Hash{TargetDefinition => TargetInspectionResult}
private
Precompute information for each target_definition in the Podfile.
-
#verify_platforms_specified! ⇒ void
private
Checks whether the platform is specified if not integrating.
Instance Method Summary collapse
-
#analyze(allow_fetches = true) ⇒ AnalysisResult
Performs the analysis.
-
#initialize(sandbox, podfile, lockfile = nil, plugin_sources = nil, has_dependencies = true, pods_to_update = false, sources_manager = Source::Manager.new(config.repos_dir)) ⇒ Analyzer
constructor
Initialize a new instance.
-
#sources ⇒ Array<Source>
Returns the sources used to query for specifications.
-
#update_repositories ⇒ Object
Updates the git source repositories.
Methods included from Config::Mixin
Constructor Details
#initialize(sandbox, podfile, lockfile = nil, plugin_sources = nil, has_dependencies = true, pods_to_update = false, sources_manager = Source::Manager.new(config.repos_dir)) ⇒ Analyzer
Initialize a new instance
76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/cocoapods/installer/analyzer.rb', line 76 def initialize(sandbox, podfile, lockfile = nil, plugin_sources = nil, has_dependencies = true, pods_to_update = false, sources_manager = Source::Manager.new(config.repos_dir)) @sandbox = sandbox @podfile = podfile @lockfile = lockfile @plugin_sources = plugin_sources @has_dependencies = has_dependencies @pods_to_update = pods_to_update @installation_options = podfile. @podfile_dependency_cache = PodfileDependencyCache.from_podfile(podfile) @sources_manager = sources_manager @path_lists = {} @result = nil end |
Instance Attribute Details
#has_dependencies ⇒ Boolean (readonly) Also known as: has_dependencies?
This is used by the pod lib lint
command to prevent update of specs when not needed.
Returns Whether the analysis has dependencies and thus sources must be configured.
50 51 52 |
# File 'lib/cocoapods/installer/analyzer.rb', line 50 def has_dependencies @has_dependencies end |
#installation_options ⇒ InstallationOptions (readonly)
Returns the installation options specified by the Podfile.
60 61 62 |
# File 'lib/cocoapods/installer/analyzer.rb', line 60 def @installation_options end |
#lockfile ⇒ Lockfile? (readonly)
Returns The Lockfile, if available, that stores the information about the Pods previously installed.
40 41 42 |
# File 'lib/cocoapods/installer/analyzer.rb', line 40 def lockfile @lockfile end |
#plugin_sources ⇒ Array<Source> (readonly)
Returns Sources provided by plugins or nil
.
44 45 46 |
# File 'lib/cocoapods/installer/analyzer.rb', line 44 def plugin_sources @plugin_sources end |
#podfile ⇒ Podfile (readonly)
Returns The Podfile specification that contains the information of the Pods that should be installed.
36 37 38 |
# File 'lib/cocoapods/installer/analyzer.rb', line 36 def podfile @podfile end |
#pods_to_update ⇒ Hash, ... (readonly)
Returns Pods that have been requested to be updated or true if all Pods should be updated. This can be false if no pods should be updated.
56 57 58 |
# File 'lib/cocoapods/installer/analyzer.rb', line 56 def pods_to_update @pods_to_update end |
#sandbox ⇒ Sandbox (readonly)
Returns The sandbox to use for this analysis.
32 33 34 |
# File 'lib/cocoapods/installer/analyzer.rb', line 32 def sandbox @sandbox end |
#sources_manager ⇒ Source::Manager (readonly)
Returns the sources manager to use when resolving dependencies.
64 65 66 |
# File 'lib/cocoapods/installer/analyzer.rb', line 64 def sources_manager @sources_manager end |
Class Method Details
.requires_64_bit_archs?(platform, object_version) ⇒ Boolean
Returns Whether the platform requires 64-bit architectures.
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 |
# File 'lib/cocoapods/installer/analyzer.rb', line 1142 def requires_64_bit_archs?(platform, object_version) return false unless platform case platform.name when :osx true when :ios if (version = object_version) platform.deployment_target >= IOS_64_BIT_ONLY_VERSION && version.to_i < IOS_64_BIT_ONLY_PROJECT_VERSION else platform.deployment_target >= IOS_64_BIT_ONLY_VERSION end when :watchos false when :tvos false end end |
Instance Method Details
#analyze(allow_fetches = true) ⇒ AnalysisResult
Performs the analysis.
The Podfile and the Lockfile provide the information necessary to compute which specification should be installed. The manifest of the sandbox returns which specifications are installed.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/cocoapods/installer/analyzer.rb', line 102 def analyze(allow_fetches = true) return @result if @result validate_podfile! validate_lockfile_version! if .integrate_targets? target_inspections = inspect_targets_to_integrate else verify_platforms_specified! target_inspections = {} end podfile_state = generate_podfile_state if allow_fetches == :outdated # special-cased -- we're only really resolving for outdated, rather than doing a full analysis elsif allow_fetches == true fetch_external_sources(podfile_state) elsif !dependencies_to_fetch(podfile_state).all?(&:local?) raise Informative, 'Cannot analyze without fetching dependencies since the sandbox is not up-to-date. Run `pod install` to ensure all dependencies have been fetched.' \ "\n The missing dependencies are:\n \t#{dependencies_to_fetch(podfile_state).reject(&:local?).join("\n \t")}" end locked_dependencies = generate_version_locking_dependencies(podfile_state) resolver_specs_by_target = resolve_dependencies(locked_dependencies) validate_platforms(resolver_specs_by_target) specifications = generate_specifications(resolver_specs_by_target) aggregate_targets, pod_targets = generate_targets(resolver_specs_by_target, target_inspections) sandbox_state = generate_sandbox_state(specifications) specs_by_target = resolver_specs_by_target.each_with_object({}) do |rspecs_by_target, hash| hash[rspecs_by_target[0]] = rspecs_by_target[1].map(&:spec) end specs_by_source = Hash[resolver_specs_by_target.values.flatten(1).group_by(&:source).map do |source, specs| [source, specs.map(&:spec).uniq] end] sources.each { |s| specs_by_source[s] ||= [] } @result = AnalysisResult.new(podfile_state, specs_by_target, specs_by_source, specifications, sandbox_state, aggregate_targets, pod_targets, @podfile_dependency_cache) end |
#analyze_host_targets_in_podfile(aggregate_targets, embedded_aggregate_targets) ⇒ Object (private)
Raises an error if there are embedded targets in the Podfile, but their host targets have not been declared in the Podfile. As it finds host targets, it collection information on host target types.
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
# File 'lib/cocoapods/installer/analyzer.rb', line 336 def analyze_host_targets_in_podfile(aggregate_targets, ) target_definitions_by_uuid = {} cli_host_with_dynamic_linkage = [] cli_product_type = 'com.apple.product-type.tool' # Collect aggregate target definitions by uuid to later lookup host target # definitions and verify their compatibility with their embedded targets aggregate_targets.each do |target| target.user_targets.each do |user_target| target_definition = target.target_definition target_definitions_by_uuid[user_target.uuid] = target_definition if user_target.product_type == cli_product_type && target_definition.build_type.linkage == :dynamic cli_host_with_dynamic_linkage << user_target end end end aggregate_target_user_projects = aggregate_targets.map(&:user_project) = [] = {} # Search all of the known user projects for each embedded target's hosts .each do |target| host_uuids = aggregate_target_user_projects.product(target.user_targets).flat_map do |user_project, user_target| user_project.(user_target).map(&:uuid) end # For each host, keep track of its embedded target definitions # to later verify each embedded target's compatiblity with its host, # ignoring the hosts that aren't known to CocoaPods (no target # definitions in the Podfile) host_uuids.each do |uuid| ([uuid] ||= []) << target.target_definition if target_definitions_by_uuid.key? uuid end # If none of the hosts are known to CocoaPods (no target definitions # in the Podfile), add it to the list of targets missing hosts << target unless host_uuids.any? do |uuid| target_definitions_by_uuid.key? uuid end end unless cli_host_with_dynamic_linkage.empty? UI.warn "The Podfile contains command line tool target(s) (#{cli_host_with_dynamic_linkage.map(&:name).to_sentence}) which are attempting to integrate dynamic frameworks or libraries." \ "\n" \ 'This may not behave as expected, because command line tools are usually distributed as a single binary and cannot contain their own dynamic dependencies.' end unless .empty? = Set.new .flat_map(&:user_targets).map(&:symbol_type) target_names = .map do |target| target.name.sub('Pods-', '') # Make the target names more recognizable to the user end.join ', ' # If the targets missing hosts are only frameworks, then this is likely # a project for doing framework development. In that case, just warn that # the frameworks that these targets depend on won't be integrated anywhere if .subset?(Set.new([:framework, :static_library])) UI.warn "The Podfile contains framework or static library targets (#{target_names}), for which the Podfile does not contain host targets (targets which embed the framework)." \ "\n" \ 'If this project is for doing framework development, you can ignore this message. Otherwise, add a target to the Podfile that embeds these frameworks to make this message go away (e.g. a test target).' else raise Informative, "Unable to find host target(s) for #{target_names}. Please add the host targets for the embedded targets to the Podfile." \ "\n" \ 'Certain kinds of targets require a host target. A host target is a "parent" target which embeds a "child" target. These are example types of targets that need a host target:' \ "\n- Framework" \ "\n- App Extension" \ "\n- Watch OS 1 Extension" \ "\n- Messages Extension (except when used with a Messages Application)" end end target_mismatches = [] .each do |uuid, target_definitions| host_target_definition = target_definitions_by_uuid[uuid] target_definitions.each do |target_definition| unless host_target_definition.uses_frameworks? == target_definition.uses_frameworks? target_mismatches << "- #{host_target_definition.name} (#{host_target_definition.uses_frameworks?}) and #{target_definition.name} (#{target_definition.uses_frameworks?}) do not both set use_frameworks!." end end end unless target_mismatches.empty? heading = 'Unable to integrate the following embedded targets with their respective host targets (a host target is a "parent" target which embeds a "child" target like a framework or extension):' raise Informative, heading + "\n\n" + target_mismatches.sort.uniq.join("\n") end end |
#checkout_requires_update?(dependency) ⇒ Boolean (private)
1021 1022 1023 1024 1025 1026 |
# File 'lib/cocoapods/installer/analyzer.rb', line 1021 def checkout_requires_update?(dependency) return true unless lockfile && sandbox.manifest = lockfile.(dependency.root_name) = sandbox.manifest.(dependency.root_name) != end |
#compute_pod_target_dependencies(pod_targets, all_specs) ⇒ Array<PodTarget> (private)
Compute the dependencies for the set of pod targets.
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 |
# File 'lib/cocoapods/installer/analyzer.rb', line 679 def compute_pod_target_dependencies(pod_targets, all_specs) pod_targets_by_name = pod_targets.group_by(&:pod_name).each_with_object({}) do |(name, values), hash| # Sort the target by the number of activated subspecs, so that # we prefer a minimal target as transitive dependency. hash[name] = values.sort_by { |pt| pt.specs.count } end pod_targets.each do |target| dependencies_by_config = dependencies_for_specs(target.library_specs, target.platform, all_specs) target.dependent_targets_by_config = Hash[dependencies_by_config.map { |k, v| [k, filter_dependencies(v, pod_targets_by_name, target)] }] target.test_dependent_targets_by_spec_name_by_config = target.test_specs.each_with_object({}) do |test_spec, hash| test_dependencies_by_config = dependencies_for_specs([test_spec], target.platform, all_specs) test_dependencies_by_config.each { |config, deps| deps.delete_if { |k, _| dependencies_by_config[config].key? k } } hash[test_spec.name] = Hash[test_dependencies_by_config.map { |k, v| [k, filter_dependencies(v, pod_targets_by_name, target)] }] end target.app_dependent_targets_by_spec_name_by_config = target.app_specs.each_with_object({}) do |app_spec, hash| app_dependencies_by_config = dependencies_for_specs([app_spec], target.platform, all_specs) app_dependencies_by_config.each { |config, deps| deps.delete_if { |k, _| dependencies_by_config[config].key? k } } hash[app_spec.name] = Hash[app_dependencies_by_config.map { |k, v| [k, filter_dependencies(v, pod_targets_by_name, target)] }] end target.test_app_hosts_by_spec = target.test_specs.each_with_object({}) do |test_spec, hash| next unless app_host_name = test_spec.consumer(target.platform).app_host_name app_host_spec = pod_targets_by_name[Specification.root_name(app_host_name)].flat_map(&:app_specs).find do |pt| pt.name == app_host_name end app_host_dependencies = { app_host_spec.root => [app_host_spec] } hash[test_spec] = [app_host_spec, filter_dependencies(app_host_dependencies, pod_targets_by_name, target).first] end end end |
#create_file_accessors(specs, platform) ⇒ Array<FileAccessor> (private)
Creates the file accessors for a given pod.
831 832 833 834 835 836 837 838 839 840 841 |
# File 'lib/cocoapods/installer/analyzer.rb', line 831 def create_file_accessors(specs, platform) name = specs.first.name pod_root = sandbox.pod_dir(name) path_list = @path_lists.fetch(pod_root) do |root| path_list = Sandbox::PathList.new(root) @path_lists[root] = path_list end specs.map do |spec| Sandbox::FileAccessor.new(path_list, spec.consumer(platform)) end end |
#dependencies_for_specs(specs, platform, all_specs) ⇒ Hash{Symbol => Set<Specification>} (private)
Returns the specs upon which the given specs directly depend.
@note: This is implemented in the analyzer, because we don't have to care about the requirements after dependency resolution.
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 |
# File 'lib/cocoapods/installer/analyzer.rb', line 745 def dependencies_for_specs(specs, platform, all_specs) dependent_specs = { :debug => Set.new, :release => Set.new, } if !specs.empty? && !all_specs.empty? specs.each do |s| s.dependencies(platform).each do |dep| all_specs[dep.name].each do |spec| if spec.non_library_specification? if s.test_specification? && spec.name == s.consumer(platform).app_host_name && spec.app_specification? # This needs to be handled separately, since we _don't_ want to treat this as a "normal" dependency next end raise Informative, "`#{s}` depends upon `#{spec}`, which is a `#{spec.spec_type}` spec." end dependent_specs.each do |config, set| next unless s.dependency_whitelisted_for_configuration?(dep, config) set << spec end end end end end Hash[dependent_specs.map { |k, v| [k, (v - specs).group_by(&:root)] }].freeze end |
#dependencies_to_fetch(podfile_state) ⇒ Object (private)
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 |
# File 'lib/cocoapods/installer/analyzer.rb', line 1000 def dependencies_to_fetch(podfile_state) @deps_to_fetch ||= begin deps_to_fetch = [] deps_with_external_source = podfile_dependencies.select(&:external_source) if update_mode == :all deps_to_fetch = deps_with_external_source else deps_to_fetch = deps_with_external_source.select { |dep| pods_to_fetch(podfile_state).include?(dep.root_name) } deps_to_fetch_if_needed = deps_with_external_source.select { |dep| podfile_state.unchanged.include?(dep.root_name) } deps_to_fetch += deps_to_fetch_if_needed.select do |dep| sandbox.specification_path(dep.root_name).nil? || !dep.external_source[:path].nil? || !sandbox.pod_dir(dep.root_name).directory? || checkout_requires_update?(dep) end end deps_to_fetch.uniq(&:root_name) end end |
#determine_build_type(spec, target_definition_build_type) ⇒ BuildType (private)
Calculates and returns the #BuildType to use for the given spec. If the spec specifies static_framework
then
it is honored as long as the host #BuildType also requires its pods to be integrated as frameworks.
911 912 913 914 915 916 917 918 |
# File 'lib/cocoapods/installer/analyzer.rb', line 911 def determine_build_type(spec, target_definition_build_type) if target_definition_build_type.framework? root_spec = spec.root root_spec.static_framework ? BuildType.static_framework : target_definition_build_type else BuildType.static_library end end |
#determine_platform(specs, target_definitions, build_type) ⇒ Platform (private)
The platform is only determined by all library specs and ignores non library ones. Subspecs are always integrated in the same target as the root spec therefore the max deployment target is always returned across the specs passed.
Calculates and returns the platform to use for the given list specs and target definitions.
860 861 862 863 864 865 866 867 868 869 870 871 872 |
# File 'lib/cocoapods/installer/analyzer.rb', line 860 def determine_platform(specs, target_definitions, build_type) library_specs = specs.select(&:library_specification?) platform_name = target_definitions.first.platform.name default = Podfile::TargetDefinition::PLATFORM_DEFAULTS[platform_name] deployment_target = library_specs.map do |library_spec| Version.new(library_spec.deployment_target(platform_name) || default) end.max if platform_name == :ios && build_type.framework? minimum = Version.new('8.0') deployment_target = [deployment_target, minimum].max end Platform.new(platform_name, deployment_target) end |
#determine_swift_version(spec, target_definitions) ⇒ String? (private)
Determines the Swift version for the given spec within a list of target definitions. If the pod author has provided a set of Swift versions supported by their pod then the max Swift version is chosen, unless the target definitions specify explicit requirements for supported Swift versions. Otherwise the Swift version is derived by the target definitions that integrate this pod.
887 888 889 890 891 892 893 894 895 896 897 |
# File 'lib/cocoapods/installer/analyzer.rb', line 887 def determine_swift_version(spec, target_definitions) if spec.swift_versions.empty? target_definitions.map(&:swift_version).compact.uniq.first else spec.swift_versions.sort.reverse_each.find do |swift_version| target_definitions.all? do |td| td.supports_swift_version?(swift_version) end end.to_s end end |
#embedded_target_pod_targets_by_host(aggregate_target, embedded_aggregate_targets, libraries_only) ⇒ Hash{String=>Array<PodTarget>} (private)
Copies the pod targets of any of the app embedded aggregate targets into their potential host aggregate target, if that potential host aggregate target's user_target hosts any of the app embedded aggregate targets' user_targets
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/cocoapods/installer/analyzer.rb', line 293 def (aggregate_target, , libraries_only) return {} if aggregate_target.requires_host_target? aggregate_user_target_uuids = Set.new(aggregate_target.user_targets.map(&:uuid)) = Hash.new([].freeze) .each do || # Skip non libraries in library-only mode next if libraries_only && !.library? next if aggregate_target.search_paths_aggregate_targets.include?() next unless .user_targets.any? do || # You have to ask the host target's project for the host targets of # the embedded target, as opposed to asking user_project for the # embedded targets of the host target. The latter doesn't work when # the embedded target lives in a sub-project. The lines below get # the host target uuids for the embedded target and checks to see if # those match to any of the user_target uuids in the aggregate_target. host_target_uuids = Set.new(aggregate_target.user_project.().map(&:uuid)) !aggregate_user_target_uuids.intersection(host_target_uuids).empty? end .user_build_configurations.each_key do |configuration_name| pod_target_names = Set.new(aggregate_target.pod_targets_for_build_configuration(configuration_name).map(&:name)) = .pod_targets_for_build_configuration(configuration_name).select do |pod_target| if !pod_target_names.include?(pod_target.name) && aggregate_target.pod_targets.none? { |aggregate_pod_target| (pod_target.specs - aggregate_pod_target.specs).empty? } && (libraries_only || pod_target.build_as_dynamic?) pod_target.name end end [configuration_name] += end end end |
#fetch_external_source(dependency, use_lockfile_options) ⇒ Object (private)
991 992 993 994 995 996 997 998 |
# File 'lib/cocoapods/installer/analyzer.rb', line 991 def fetch_external_source(dependency, ) source = if && lockfile && = lockfile.(dependency.root_name) ExternalSources.from_params(, dependency, podfile.defined_in_file, .clean?) else ExternalSources.from_dependency(dependency, podfile.defined_in_file, .clean?) end source.fetch(sandbox) end |
#fetch_external_sources(podfile_state) ⇒ void (private)
In update mode all the external sources are refreshed while in normal mode they are refreshed only if added or changed in the Podfile. Moreover, in normal specifications for unchanged Pods which are missing or are generated from an local source are fetched as well.
It is possible to perform this step before the resolution process because external sources identify a single specific version (checkout). If the other dependencies are not compatible with the version reported by the podspec of the external source the resolver will raise.
This method returns an undefined value.
Fetches the podspecs of external sources if modifications to the sandbox are allowed.
969 970 971 972 973 974 975 976 977 978 979 |
# File 'lib/cocoapods/installer/analyzer.rb', line 969 def fetch_external_sources(podfile_state) verify_no_pods_with_different_sources! deps = dependencies_to_fetch(podfile_state) pods = pods_to_fetch(podfile_state) return if deps.empty? UI.section 'Fetching external sources' do deps.sort.each do |dependency| fetch_external_source(dependency, !pods.include?(dependency.root_name)) end end end |
#filter_dependencies(dependencies, pod_targets_by_name, target) ⇒ Object (private)
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 |
# File 'lib/cocoapods/installer/analyzer.rb', line 713 def filter_dependencies(dependencies, pod_targets_by_name, target) dependencies.map do |root_spec, deps| pod_targets_by_name[root_spec.name].find do |t| next false if t.platform.symbolic_name != target.platform.symbolic_name || # In the case of variants we must ensure that the platform this target is meant for is the same # as the one we are interested in. t.target_definitions.first.platform != target.target_definitions.first.platform || # rather than target type or requires_frameworks? since we want to group by what was specified in that # _target definition_. t.build_as_framework? != target.build_as_framework? spec_names = t.specs.map(&:name) deps.all? { |dep| spec_names.include?(dep.name) } end end end |
#filter_pod_targets_for_target_definition(target_definition, pod_targets_by_target_definition, build_configurations) ⇒ Hash{String => Array<PodTarget>} (private)
Returns a filtered list of pod targets that should or should not be part of the target definition. Pod targets used by tests only are filtered.
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 |
# File 'lib/cocoapods/installer/analyzer.rb', line 564 def filter_pod_targets_for_target_definition(target_definition, pod_targets_by_target_definition, build_configurations) pod_targets_by_build_config = Hash.new([].freeze) build_configurations.each { |config| pod_targets_by_build_config[config] = [] } dependencies_by_root_name = @podfile_dependency_cache.target_definition_dependencies(target_definition).group_by(&:root_name) pod_targets_by_target_definition[target_definition].each do |pod_target| pod_name = pod_target.pod_name dependencies = dependencies_by_root_name[pod_name] || [] build_configurations.each do |configuration_name| whitelists = dependencies.map do |dependency| target_definition.pod_whitelisted_for_configuration?(dependency.name, configuration_name) end.uniq case whitelists when [], [true] then nil when [false] then next else raise Informative, "The subspecs of `#{pod_name}` are linked to " \ "different build configurations for the `#{target_definition}` " \ 'target. CocoaPods does not currently support subspecs across ' \ 'different build configurations.' end pod_targets_by_build_config[configuration_name] << pod_target end end pod_targets_by_build_config end |
#generate_aggregate_target(target_definition, target_inspections, pod_targets_by_target_definition) ⇒ AggregateTarget (private)
Setup the aggregate target for a single user target
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 |
# File 'lib/cocoapods/installer/analyzer.rb', line 500 def generate_aggregate_target(target_definition, target_inspections, pod_targets_by_target_definition) if .integrate_targets? target_inspection = target_inspections[target_definition] raise "missing inspection for #{target_definition.inspect}" unless target_inspection target_requires_64_bit = Analyzer.requires_64_bit_archs?(target_definition.platform, target_inspection.project.object_version) user_project = target_inspection.project client_root = target_inspection.client_root user_target_uuids = target_inspection.project_target_uuids user_build_configurations = target_inspection.build_configurations archs = target_requires_64_bit ? ['$(ARCHS_STANDARD_64_BIT)'] : target_inspection.archs else target_requires_64_bit = Analyzer.requires_64_bit_archs?(target_definition.platform, nil) user_project = nil client_root = config.installation_root.realpath user_target_uuids = [] user_build_configurations = target_definition.build_configurations || Target::DEFAULT_BUILD_CONFIGURATIONS archs = target_requires_64_bit ? ['$(ARCHS_STANDARD_64_BIT)'] : [] end platform = target_definition.platform build_configurations = user_build_configurations.keys.concat(target_definition.all_whitelisted_configurations).uniq pod_targets_for_build_configuration = filter_pod_targets_for_target_definition(target_definition, pod_targets_by_target_definition, build_configurations) build_type = target_definition.uses_frameworks? ? BuildType.static_framework : BuildType.static_library AggregateTarget.new(sandbox, build_type, user_build_configurations, archs, platform, target_definition, client_root, user_project, user_target_uuids, pod_targets_for_build_configuration) end |
#generate_pod_target(target_definitions, build_type, target_inspections, specs, scope_suffix: nil, swift_version: nil) ⇒ PodTarget (private)
Create a target for each spec group
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 |
# File 'lib/cocoapods/installer/analyzer.rb', line 797 def generate_pod_target(target_definitions, build_type, target_inspections, specs, scope_suffix: nil, swift_version: nil) target_inspections = target_inspections.select { |t, _| target_definitions.include?(t) }.values object_version = target_inspections.map { |ti| ti.project.object_version }.min target_requires_64_bit = target_definitions.all? { |td| Analyzer.requires_64_bit_archs?(td.platform, object_version) } if !target_inspections.empty? user_build_configurations = target_inspections.map(&:build_configurations).reduce({}, &:merge) archs = if target_requires_64_bit ['$(ARCHS_STANDARD_64_BIT)'] else target_inspections.flat_map(&:archs).compact.uniq.sort end else user_build_configurations = Target::DEFAULT_BUILD_CONFIGURATIONS.merge( target_definitions.map { |td| td.build_configurations || {} }.reduce({}, &:merge), ) archs = target_requires_64_bit ? ['$(ARCHS_STANDARD_64_BIT)'] : [] end platform = determine_platform(specs, target_definitions, build_type) file_accessors = create_file_accessors(specs, platform) PodTarget.new(sandbox, build_type, user_build_configurations, archs, platform, specs, target_definitions, file_accessors, scope_suffix, swift_version) end |
#generate_pod_targets(resolver_specs_by_target, target_inspections) ⇒ Array<PodTarget> (private)
Setup the pod targets for an aggregate target. Deduplicates resulting targets by grouping by platform and subspec by their root to create a PodTarget for each spec.
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 |
# File 'lib/cocoapods/installer/analyzer.rb', line 609 def generate_pod_targets(resolver_specs_by_target, target_inspections) if .deduplicate_targets? distinct_targets = resolver_specs_by_target.each_with_object({}) do |dependency, hash| target_definition, dependent_specs = *dependency dependent_specs.group_by(&:root).each do |root_spec, resolver_specs| all_specs = resolver_specs.map(&:spec) all_specs_by_type = all_specs.group_by(&:spec_type) library_specs = all_specs_by_type[:library] || [] test_specs = all_specs_by_type[:test] || [] app_specs = all_specs_by_type[:app] || [] build_type = determine_build_type(root_spec, target_definition.build_type) pod_variant = PodVariant.new(library_specs, test_specs, app_specs, target_definition.platform, build_type) hash[root_spec] ||= {} (hash[root_spec][pod_variant] ||= []) << target_definition pod_variant_spec = hash[root_spec].keys.find { |k| k == pod_variant } pod_variant_spec.test_specs.concat(test_specs).uniq! pod_variant_spec.app_specs.concat(app_specs).uniq! end end # Remap pod variants to a new instance that includes the Swift version since we now have the full set # of target definitions. distinct_targets = Hash[distinct_targets.map do |root, target_definitions_by_variant| variants = Hash[target_definitions_by_variant.map do |variant, target_definitions| swift_version = determine_swift_version(variant.root_spec, target_definitions) [variant.scoped_with_swift_version(swift_version), target_definitions] end] [root, variants] end] pod_targets = distinct_targets.flat_map do |_root, target_definitions_by_variant| target_definitions_by_variant.each_value do |target_definitions| target_definitions.reject!(&:abstract?) unless target_definitions.all?(&:abstract?) end suffixes = PodVariantSet.new(target_definitions_by_variant.keys).scope_suffixes target_definitions_by_variant.map do |variant, target_definitions| all_specs = variant.specs + variant.test_specs + variant.app_specs generate_pod_target(target_definitions, variant.build_type, target_inspections, all_specs, :scope_suffix => suffixes[variant], :swift_version => variant.swift_version) end end all_specs = resolver_specs_by_target.values.flatten.map(&:spec).uniq.group_by(&:name) compute_pod_target_dependencies(pod_targets, all_specs) else dedupe_cache = {} resolver_specs_by_target.flat_map do |target_definition, specs| grouped_specs = specs.group_by(&:root).values.uniq pod_targets = grouped_specs.flat_map do |pod_specs| build_type = determine_build_type(pod_specs.first.spec, target_definition.build_type) swift_version = determine_swift_version(pod_specs.first.spec, [target_definition]) generate_pod_target([target_definition], build_type, target_inspections, pod_specs.map(&:spec), :swift_version => swift_version).scoped(dedupe_cache) end compute_pod_target_dependencies(pod_targets, specs.map(&:spec).group_by(&:name)) end end end |
#generate_podfile_state ⇒ SpecsState, SpecState (private)
As the target definitions share the same sandbox they should have the same version of a Pod. For this reason this method returns the name of the Pod (root name of the dependencies) and doesn't group them by target definition.
Compares the Podfile with the Lockfile in order to detect which dependencies should be locked.
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/cocoapods/installer/analyzer.rb', line 260 def generate_podfile_state if lockfile pods_state = nil UI.section 'Finding Podfile changes' do pods_by_state = lockfile.detect_changes_with_podfile(podfile) pods_state = SpecsState.new(pods_by_state) pods_state.print if config.verbose? end pods_state else state = SpecsState.new state.added.merge(podfile_dependencies.map(&:root_name)) state end end |
#generate_sandbox_state(specifications) ⇒ SpecsState (private)
Computes the state of the sandbox respect to the resolved specifications.
1123 1124 1125 1126 1127 1128 1129 1130 1131 |
# File 'lib/cocoapods/installer/analyzer.rb', line 1123 def generate_sandbox_state(specifications) sandbox_state = nil UI.section 'Comparing resolved specification to the sandbox manifest' do sandbox_analyzer = SandboxAnalyzer.new(sandbox, podfile, specifications, update_mode?) sandbox_state = sandbox_analyzer.analyze sandbox_state.print end sandbox_state end |
#generate_specifications(resolver_specs_by_target) ⇒ Array<Specification> (private)
Returns the list of all the resolved specifications.
1113 1114 1115 |
# File 'lib/cocoapods/installer/analyzer.rb', line 1113 def generate_specifications(resolver_specs_by_target) resolver_specs_by_target.values.flatten.map(&:spec).uniq end |
#generate_targets(resolver_specs_by_target, target_inspections) ⇒ (Array<AggregateTarget>, Array<PodTarget>) (private)
Creates the models that represent the targets generated by CocoaPods.
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 |
# File 'lib/cocoapods/installer/analyzer.rb', line 430 def generate_targets(resolver_specs_by_target, target_inspections) resolver_specs_by_target = resolver_specs_by_target.reject { |td, _| td.abstract? && !td.platform } pod_targets = generate_pod_targets(resolver_specs_by_target, target_inspections) pod_targets_by_target_definition = group_pod_targets_by_target_definition(pod_targets, resolver_specs_by_target) aggregate_targets = resolver_specs_by_target.keys.reject(&:abstract?).map do |target_definition| generate_aggregate_target(target_definition, target_inspections, pod_targets_by_target_definition) end aggregate_targets.each do |target| search_paths_aggregate_targets = aggregate_targets.select do |aggregate_target| target.target_definition.targets_to_inherit_search_paths.include?(aggregate_target.target_definition) end target.search_paths_aggregate_targets.concat(search_paths_aggregate_targets).freeze end aggregate_targets.each do |aggregate_target| is_app_extension = !(aggregate_target.user_targets.map(&:symbol_type) & [:app_extension, :watch_extension, :watch2_extension, :tv_extension, :messages_extension]).empty? is_app_extension ||= aggregate_target.user_targets.any? do |user_target| user_target.common_resolved_build_setting('APPLICATION_EXTENSION_API_ONLY', :resolve_against_xcconfig => true) == 'YES' end if is_app_extension aggregate_target.mark_application_extension_api_only aggregate_target.pod_targets.each(&:mark_application_extension_api_only) end build_library_for_distribution = aggregate_target.user_targets.any? do |user_target| user_target.common_resolved_build_setting('BUILD_LIBRARY_FOR_DISTRIBUTION', :resolve_against_xcconfig => true) == 'YES' end if build_library_for_distribution aggregate_target.mark_build_library_for_distribution aggregate_target.pod_targets.each(&:mark_build_library_for_distribution) end end if .integrate_targets? # Copy embedded target pods that cannot have their pods embedded as frameworks to # their host targets, and ensure we properly link library pods to their host targets = aggregate_targets.select(&:requires_host_target?) analyze_host_targets_in_podfile(aggregate_targets, ) , = .partition(&:build_as_framework?) aggregate_targets = aggregate_targets.map do |aggregate_target| # For targets that require dynamic frameworks, we always have to copy their pods to their # host targets because those frameworks will all be loaded from the host target's bundle = (aggregate_target, , false) # For targets that don't require dynamic frameworks, we only have to consider library-type # targets because their host targets will still need to link their pods .merge!((aggregate_target, , true)) next aggregate_target if .empty? aggregate_target.() end end [aggregate_targets, pod_targets] end |
#generate_version_locking_dependencies(podfile_state) ⇒ Molinillo::DependencyGraph<Dependency> (private)
934 935 936 937 938 939 940 941 942 943 944 945 946 947 |
# File 'lib/cocoapods/installer/analyzer.rb', line 934 def generate_version_locking_dependencies(podfile_state) if update_mode == :all || !lockfile LockingDependencyAnalyzer.unlocked_dependency_graph else deleted_and_changed = podfile_state.changed + podfile_state.deleted deleted_and_changed += pods_to_update[:pods] if update_mode == :selected local_pod_names = podfile_dependencies.select(&:local?).map(&:root_name) pods_to_unlock = local_pod_names.to_set.delete_if do |pod_name| next unless sandbox_specification = sandbox.specification(pod_name) sandbox_specification.checksum == lockfile.checksum(pod_name) end LockingDependencyAnalyzer.generate_version_locking_dependencies(lockfile, deleted_and_changed, pods_to_unlock) end end |
#group_pod_targets_by_target_definition(pod_targets, resolver_specs_by_target) ⇒ Hash{TargetDefinition => Array<PodTarget>} (private)
Returns a filtered list of pod targets that should or should not be part of the target definition. Pod targets used by tests only are filtered.
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 |
# File 'lib/cocoapods/installer/analyzer.rb', line 533 def group_pod_targets_by_target_definition(pod_targets, resolver_specs_by_target) pod_targets_by_target_definition = Hash.new { |h, td| h[td] = [] } pod_targets.each do |pod_target| pod_target.target_definitions.each do |td| pod_targets_by_target_definition[td] << pod_target end end resolver_specs_by_target.each do |td, resolver_specs| specs_by_pod_name = resolver_specs.group_by { |s| s.root.name } specs_by_pod_name.reject! { |_, specs| specs.all?(&:used_by_non_library_targets_only?) } pod_targets_by_target_definition[td].keep_if { |pod_target| specs_by_pod_name.key?(pod_target.pod_name) } end pod_targets_by_target_definition end |
#inspect_targets_to_integrate ⇒ Hash{TargetDefinition => TargetInspectionResult} (private)
The platforms are computed and added to each target_definition because it might be necessary to infer the platform from the user targets.
Precompute information for each target_definition in the Podfile
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 |
# File 'lib/cocoapods/installer/analyzer.rb', line 1186 def inspect_targets_to_integrate inspection_result = {} UI.section 'Inspecting targets to integrate' do inspectors = @podfile_dependency_cache.target_definition_list.map do |target_definition| next if target_definition.abstract? TargetInspector.new(target_definition, config.installation_root) end.compact inspectors.group_by(&:compute_project_path).each do |project_path, target_inspectors| project = Xcodeproj::Project.open(project_path) target_inspectors.each do |inspector| target_definition = inspector.target_definition results = inspector.compute_results(project) inspection_result[target_definition] = results UI.('Using `ARCHS` setting to build architectures of ' \ "target `#{target_definition.label}`: (`#{results.archs.join('`, `')}`)") end end end inspection_result end |
#podfile_dependencies ⇒ Object (private)
217 218 219 |
# File 'lib/cocoapods/installer/analyzer.rb', line 217 def podfile_dependencies @podfile_dependency_cache.podfile_dependencies end |
#pods_to_fetch(podfile_state) ⇒ Object (private)
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 |
# File 'lib/cocoapods/installer/analyzer.rb', line 1028 def pods_to_fetch(podfile_state) @pods_to_fetch ||= begin pods_to_fetch = podfile_state.added + podfile_state.changed if update_mode == :selected pods_to_fetch += pods_to_update[:pods] elsif update_mode == :all pods_to_fetch += podfile_state.unchanged + podfile_state.deleted end pods_to_fetch += podfile_dependencies. select { |dep| Hash(dep.external_source).key?(:podspec) && sandbox.specification_path(dep.root_name).nil? }. map(&:root_name) pods_to_fetch end end |
#resolve_dependencies(locked_dependencies) ⇒ Hash{TargetDefinition => Array<Spec>} (private)
As some dependencies might have external sources the resolver is aware of the Sandbox and interacts with it to download the podspecs of the external sources. This is necessary because the resolver needs their specifications to analyze their dependencies.
The specifications of the external sources which are added, modified or removed need to deleted from the sandbox before the resolution process. Otherwise the resolver might use an incorrect specification instead of pre-downloading it.
In update mode the resolver is set to always update the specs from external sources.
Converts the Podfile in a list of specifications grouped by target.
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 |
# File 'lib/cocoapods/installer/analyzer.rb', line 1071 def resolve_dependencies(locked_dependencies) duplicate_dependencies = podfile_dependencies.group_by(&:name). select { |_name, dependencies| dependencies.count > 1 } duplicate_dependencies.each do |name, dependencies| UI.warn "There are duplicate dependencies on `#{name}` in #{UI.path podfile.defined_in_file}:\n\n" \ "- #{dependencies.map(&:to_s).join("\n- ")}" end resolver_specs_by_target = nil UI.section "Resolving dependencies of #{UI.path(podfile.defined_in_file) || 'Podfile'}" do resolver = Pod::Resolver.new(sandbox, podfile, locked_dependencies, sources, @specs_updated, :sources_manager => sources_manager) resolver_specs_by_target = resolver.resolve resolver_specs_by_target.values.flatten(1).map(&:spec).each(&:validate_cocoapods_version) end resolver_specs_by_target end |
#sources ⇒ Array<Source>
Returns the sources used to query for specifications.
When no explicit Podfile sources or plugin sources are defined, this defaults to the master spec repository.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/cocoapods/installer/analyzer.rb', line 161 def sources @sources ||= begin sources = podfile.sources plugin_sources = @plugin_sources || [] # Add any sources specified using the :source flag on individual dependencies. dependency_sources = podfile_dependencies.map(&:podspec_repo).compact all_dependencies_have_sources = dependency_sources.count == podfile_dependencies.count if all_dependencies_have_sources sources = dependency_sources elsif has_dependencies? && sources.empty? && plugin_sources.empty? sources = [Pod::TrunkSource::TRUNK_REPO_URL] + dependency_sources else sources += dependency_sources end result = sources.uniq.map do |source_url| sources_manager.find_or_create_source_with_url(source_url) end unless plugin_sources.empty? result.insert(0, *plugin_sources) plugin_sources.each do |source| sources_manager.add_source(source) end end result end end |
#store_existing_checkout_options ⇒ Object (private)
1043 1044 1045 1046 1047 1048 1049 1050 |
# File 'lib/cocoapods/installer/analyzer.rb', line 1043 def return unless lockfile podfile_dependencies.select(&:external_source).each do |dep| if = lockfile.(dep.root_name) sandbox.store_checkout_source(dep.root_name, ) end end end |
#update_mode ⇒ Symbol (private)
Returns Whether and how the dependencies in the Podfile should be updated.
207 208 209 210 211 212 213 214 215 |
# File 'lib/cocoapods/installer/analyzer.rb', line 207 def update_mode if !pods_to_update :none elsif pods_to_update == true :all elsif !pods_to_update[:pods].nil? :selected end end |
#update_mode? ⇒ Boolean (private)
Returns Whether the version of the dependencies which did not change in the Podfile should be locked.
200 201 202 |
# File 'lib/cocoapods/installer/analyzer.rb', line 200 def update_mode? pods_to_update != nil end |
#update_repositories ⇒ Object
Updates the git source repositories.
143 144 145 146 147 148 149 150 151 152 |
# File 'lib/cocoapods/installer/analyzer.rb', line 143 def update_repositories sources.each do |source| if source.updateable? sources_manager.update(source.name, true) else UI. "Skipping `#{source.name}` update because the repository is not an updateable repository." end end @specs_updated = true end |
#validate_lockfile_version! ⇒ Object (private)
The warning about the version of the Lockfile doesn't use the
UI.warn
method because it prints the output only at the end
of the installation. At that time CocoaPods could have crashed.
239 240 241 242 243 244 245 246 |
# File 'lib/cocoapods/installer/analyzer.rb', line 239 def validate_lockfile_version! if lockfile && lockfile.cocoapods_version > Version.new(VERSION) STDERR.puts '[!] The version of CocoaPods used to generate ' \ "the lockfile (#{lockfile.cocoapods_version}) is "\ "higher than the version of the current executable (#{VERSION}). " \ 'Incompatibility issues may arise.'.yellow end end |
#validate_platforms(resolver_specs_by_target) ⇒ Object (private)
Warns for any specification that is incompatible with its target.
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 |
# File 'lib/cocoapods/installer/analyzer.rb', line 1093 def validate_platforms(resolver_specs_by_target) resolver_specs_by_target.each do |target, specs| specs.map(&:spec).each do |spec| next unless target_platform = target.platform unless spec.available_platforms.any? { |p| target_platform.supports?(p) } UI.warn "The platform of the target `#{target.name}` " \ "(#{target.platform}) may not be compatible with `#{spec}` which has " \ "a minimum requirement of #{spec.available_platforms.join(' - ')}." end end end end |
#validate_podfile! ⇒ Object (private)
-----------------------------------------------------------------------#
223 224 225 226 227 228 229 230 231 |
# File 'lib/cocoapods/installer/analyzer.rb', line 223 def validate_podfile! validator = Installer::PodfileValidator.new(podfile, @podfile_dependency_cache) validator.validate unless validator.valid? raise Informative, validator. end validator.warnings.uniq.each { |w| UI.warn(w) } end |
#verify_no_pods_with_different_sources! ⇒ Object (private)
981 982 983 984 985 986 987 988 989 |
# File 'lib/cocoapods/installer/analyzer.rb', line 981 def verify_no_pods_with_different_sources! deps_with_different_sources = podfile_dependencies.group_by(&:root_name). select { |_root_name, dependencies| dependencies.map(&:external_source).uniq.count > 1 } deps_with_different_sources.each do |root_name, dependencies| raise Informative, 'There are multiple dependencies with different ' \ "sources for `#{root_name}` in #{UI.path podfile.defined_in_file}:" \ "\n\n- #{dependencies.map(&:to_s).join("\n- ")}" end end |
#verify_platforms_specified! ⇒ void (private)
This method returns an undefined value.
Checks whether the platform is specified if not integrating
1169 1170 1171 1172 1173 1174 1175 1176 |
# File 'lib/cocoapods/installer/analyzer.rb', line 1169 def verify_platforms_specified! return if .integrate_targets? @podfile_dependency_cache.target_definition_list.each do |target_definition| if !target_definition.empty? && target_definition.platform.nil? raise Informative, 'It is necessary to specify the platform in the Podfile if not integrating.' end end end |