Class: Pod::Installer::Analyzer

Inherits:
Object
  • Object
show all
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 =
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

Analysis steps collapse

Instance Method Summary collapse

Methods included from Config::Mixin

#config

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
# 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.installation_options
  @podfile_dependency_cache = PodfileDependencyCache.from_podfile(podfile)
  @sources_manager = sources_manager
  @result = nil
end

Instance Attribute Details

#has_dependenciesBool (readonly) Also known as: has_dependencies?

Note:

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_optionsInstallationOptions (readonly)


60
61
62
# File 'lib/cocoapods/installer/analyzer.rb', line 60

def installation_options
  @installation_options
end

#lockfileLockfile (readonly)


40
41
42
# File 'lib/cocoapods/installer/analyzer.rb', line 40

def lockfile
  @lockfile
end

#plugin_sourcesArray<Source> (readonly)


44
45
46
# File 'lib/cocoapods/installer/analyzer.rb', line 44

def plugin_sources
  @plugin_sources
end

#podfilePodfile (readonly)


36
37
38
# File 'lib/cocoapods/installer/analyzer.rb', line 36

def podfile
  @podfile
end

#pods_to_updateHash, ... (readonly)


56
57
58
# File 'lib/cocoapods/installer/analyzer.rb', line 56

def pods_to_update
  @pods_to_update
end

#sandboxSandbox (readonly)


32
33
34
# File 'lib/cocoapods/installer/analyzer.rb', line 32

def sandbox
  @sandbox
end

#sources_managerSource::Manager (readonly)


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


1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
# File 'lib/cocoapods/installer/analyzer.rb', line 1046

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.


101
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
# File 'lib/cocoapods/installer/analyzer.rb', line 101

def analyze(allow_fetches = true)
  return @result if @result
  validate_podfile!
  validate_lockfile_version!
  if installation_options.integrate_targets?
    target_inspections = inspect_targets_to_integrate
  else
    verify_platforms_specified!
    target_inspections = {}
  end
  podfile_state = generate_podfile_state

  store_existing_checkout_options
  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

#sourcesArray<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.


160
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
# File 'lib/cocoapods/installer/analyzer.rb', line 160

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

#update_repositoriesObject

Updates the git source repositories.


142
143
144
145
146
147
148
149
150
151
# File 'lib/cocoapods/installer/analyzer.rb', line 142

def update_repositories
  sources.each do |source|
    if source.updateable?
      sources_manager.update(source.name, true)
    else
      UI.message "Skipping `#{source.name}` update because the repository is not an updateable repository."
    end
  end
  @specs_updated = true
end