Class: Pod::Resolver

Inherits:
Object
  • Object
show all
Includes:
Molinillo::SpecificationProvider, Molinillo::UI, Installer::InstallationOptions::Mixin
Defined in:
lib/cocoapods/resolver.rb

Overview

The resolver is responsible of generating a list of specifications grouped by target for a given Podfile.

Defined Under Namespace

Classes: ResolverSpecification

Instance Attribute Summary collapse

Attributes included from Installer::InstallationOptions::Mixin

#installation_options

Resolution collapse

Instance Method Summary collapse

Methods included from Installer::InstallationOptions::Mixin

included

Constructor Details

#initialize(sandbox, podfile, locked_dependencies, sources, specs_updated, podfile_dependency_cache: Installer::Analyzer::PodfileDependencyCache.from_podfile(podfile)) ⇒ Resolver

Init a new Resolver

Parameters:

  • sandbox (Sandbox)

    @see sandbox

  • podfile (Podfile)

    @see podfile

  • locked_dependencies (Array<Dependency>)

    @see locked_dependencies

  • sources (Array<Source>, Source)

    @see sources

  • specs_updated (Boolean)

    @see specs_updated

  • podfile_dependency_cache (PodfileDependencyCache) (defaults to: Installer::Analyzer::PodfileDependencyCache.from_podfile(podfile))

    the podfile dependency cache to use within this Resolver.



91
92
93
94
95
96
97
98
99
100
101
# File 'lib/cocoapods/resolver.rb', line 91

def initialize(sandbox, podfile, locked_dependencies, sources, specs_updated,
               podfile_dependency_cache: Installer::Analyzer::PodfileDependencyCache.from_podfile(podfile))
  @sandbox = sandbox
  @podfile = podfile
  @locked_dependencies = locked_dependencies
  @sources = Array(sources)
  @specs_updated = specs_updated
  @podfile_dependency_cache = podfile_dependency_cache
  @platforms_by_dependency = Hash.new { |h, k| h[k] = [] }
  @cached_sets = {}
end

Instance Attribute Details

#locked_dependenciesArray<Dependency> (readonly)

Returns the list of dependencies locked to a specific version.

Returns:

  • (Array<Dependency>)

    the list of dependencies locked to a specific version.



69
70
71
# File 'lib/cocoapods/resolver.rb', line 69

def locked_dependencies
  @locked_dependencies
end

#podfilePodfile (readonly)

Returns the Podfile used by the resolver.

Returns:

  • (Podfile)

    the Podfile used by the resolver.



64
65
66
# File 'lib/cocoapods/resolver.rb', line 64

def podfile
  @podfile
end

#sandboxSandbox (readonly)

Returns the Sandbox used by the resolver to find external dependencies.

Returns:

  • (Sandbox)

    the Sandbox used by the resolver to find external dependencies.



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

def sandbox
  @sandbox
end

#sourcesArray<Source> (readonly)

Returns The list of the sources which will be used for the resolution.

Returns:

  • (Array<Source>)

    The list of the sources which will be used for the resolution.



74
75
76
# File 'lib/cocoapods/resolver.rb', line 74

def sources
  @sources
end

#specs_updatedBool (readonly) Also known as: specs_updated?

Returns Whether the resolver has sources repositories up-to-date.

Returns:

  • (Bool)

    Whether the resolver has sources repositories up-to-date.



78
79
80
# File 'lib/cocoapods/resolver.rb', line 78

def specs_updated
  @specs_updated
end

Instance Method Details

#after_resolutionVoid

Called after resolution ends.

Completely silence this, as we show nothing.

Returns:

  • (Void)


319
320
# File 'lib/cocoapods/resolver.rb', line 319

def after_resolution
end

#before_resolutionVoid

Called before resolution starts.

Completely silence this, as we show nothing.

Returns:

  • (Void)


310
311
# File 'lib/cocoapods/resolver.rb', line 310

def before_resolution
end

#dependencies_for(specification) ⇒ Array<Specification>

Returns the dependencies of ‘specification`.

Parameters:

  • specification (Specification)

    the specification whose own dependencies are being asked for.

Returns:

  • (Array<Specification>)

    all dependencies of ‘specification`.



186
187
188
189
190
191
192
193
194
# File 'lib/cocoapods/resolver.rb', line 186

def dependencies_for(specification)
  specification.all_dependencies.map do |dependency|
    if dependency.root_name == Specification.root_name(specification.name)
      dependency.dup.tap { |d| d.specific_version = specification.version }
    else
      dependency
    end
  end
end

#indicate_progressVoid

Called during resolution to indicate progress.

Completely silence this, as we show nothing.

Returns:

  • (Void)


328
329
# File 'lib/cocoapods/resolver.rb', line 328

def indicate_progress
end

#name_for(dependency) ⇒ String

Returns the name for the given ‘dependency`.

Parameters:

  • dependency (Dependency)

    the dependency whose name is being queried.

Returns:

  • (String)

    the name for the given ‘dependency`.



203
204
205
# File 'lib/cocoapods/resolver.rb', line 203

def name_for(dependency)
  dependency.name
end

#name_for_explicit_dependency_sourceString

Returns the user-facing name for a Podfile.

Returns:

  • (String)

    the user-facing name for a Podfile.



209
210
211
# File 'lib/cocoapods/resolver.rb', line 209

def name_for_explicit_dependency_source
  'Podfile'
end

#name_for_locking_dependency_sourceString

Returns the user-facing name for a Lockfile.

Returns:

  • (String)

    the user-facing name for a Lockfile.



215
216
217
# File 'lib/cocoapods/resolver.rb', line 215

def name_for_locking_dependency_source
  'Podfile.lock'
end

#outputUserInterface

The UI object the resolver should use for displaying user-facing output.

Returns:



300
301
302
# File 'lib/cocoapods/resolver.rb', line 300

def output
  UI
end

#requirement_satisfied_by?(requirement, activated, spec) ⇒ Boolean

Determines whether the given ‘requirement` is satisfied by the given `spec`, in the context of the current `activated` dependency graph.

Parameters:

  • requirement (Dependency)

    the dependency in question.

  • activated (Molinillo::DependencyGraph)

    the current dependency graph in the resolution process.

  • spec (Specification)

    the specification in question.

Returns:

  • (Boolean)

    whether ‘requirement` is satisfied by `spec` in the context of the current `activated` dependency graph.



232
233
234
235
236
237
238
# File 'lib/cocoapods/resolver.rb', line 232

def requirement_satisfied_by?(requirement, activated, spec)
  version = spec.version
  return false unless requirement.requirement.satisfied_by?(version)
  return false unless valid_possibility_version_for_root_name?(requirement, activated, spec)
  return false unless spec_is_platform_compatible?(activated, requirement, spec)
  true
end

#resolveHash{TargetDefinition => Array<ResolverSpecification>}

Identifies the specifications that should be installed.

Returns:

  • (Hash{TargetDefinition => Array<ResolverSpecification>})

    resolver_specs_by_target the resolved specifications that need to be installed grouped by target definition.



115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/cocoapods/resolver.rb', line 115

def resolve
  dependencies = @podfile_dependency_cache.target_definition_list.flat_map do |target|
    @podfile_dependency_cache.target_definition_dependencies(target).each do |dep|
      next unless target.platform
      @platforms_by_dependency[dep].push(target.platform)
    end
  end
  @platforms_by_dependency.each_value(&:uniq!)
  @activated = Molinillo::Resolver.new(self, self).resolve(dependencies, locked_dependencies)
  resolver_specs_by_target
rescue Molinillo::ResolverError => e
  handle_resolver_error(e)
end

#resolver_specs_by_targetHash{Podfile::TargetDefinition => Array<ResolverSpecification>}

Note:

The returned specifications can be subspecs.

Returns the resolved specifications grouped by target.

Returns:

  • (Hash{Podfile::TargetDefinition => Array<ResolverSpecification>})

    returns the resolved specifications grouped by target.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/cocoapods/resolver.rb', line 134

def resolver_specs_by_target
  @resolver_specs_by_target ||= {}.tap do |resolver_specs_by_target|
    @podfile_dependency_cache.target_definition_list.each do |target|
      # can't use vertex.root? since that considers _all_ targets
      explicit_dependencies = @podfile_dependency_cache.target_definition_dependencies(target).map(&:name).to_set
      vertices = valid_dependencies_for_target(target)

      resolver_specs_by_target[target] = vertices.
        map do |vertex|
          payload = vertex.payload
          test_only = (!explicit_dependencies.include?(vertex.name) || payload.test_specification?) &&
            (vertex.recursive_predecessors & vertices).all? { |v| !explicit_dependencies.include?(v.name) || v.payload.test_specification? }
          spec_source = payload.respond_to?(:spec_source) && payload.spec_source
          ResolverSpecification.new(payload, test_only, spec_source)
        end.
        sort_by(&:name)
    end
  end
end

#search_for(dependency) ⇒ Array<Specification>

Returns (and caches) the specification that satisfy the given dependency.

Parameters:

  • dependency (Dependency)

    the dependency that is being searched for.

Returns:

  • (Array<Specification>)

    the specifications that satisfy the given ‘dependency`.



169
170
171
172
173
174
175
176
177
# File 'lib/cocoapods/resolver.rb', line 169

def search_for(dependency)
  @search ||= {}
  @search[dependency] ||= begin
    locked_requirement = requirement_for_locked_pod_named(dependency.name)
    additional_requirements = Array(locked_requirement)
    specifications_for_dependency(dependency, additional_requirements)
  end
  @search[dependency].dup
end

#sort_dependencies(dependencies, activated, conflicts) ⇒ Array<Dependency>

Sort dependencies so that the ones that are easiest to resolve are first. Easiest to resolve is (usually) defined by:

1) Is this dependency already activated?
2) How relaxed are the requirements?
3) Are there any conflicts for this dependency?
4) How many possibilities are there to satisfy this dependency?

Parameters:

  • dependencies (Array<Dependency>)

    the unsorted dependencies.

  • activated (Molinillo::DependencyGraph)

    the dependency graph of currently activated specs.

  • conflicts ({String => Array<Conflict>})

    the current conflicts.

Returns:

  • (Array<Dependency>)

    the sorted dependencies.



275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/cocoapods/resolver.rb', line 275

def sort_dependencies(dependencies, activated, conflicts)
  dependencies.sort_by do |dependency|
    name = name_for(dependency)
    [
      activated.vertex_named(name).payload ? 0 : 1,
      dependency.external_source ? 0 : 1,
      dependency.prerelease? ? 0 : 1,
      conflicts[name] ? 0 : 1,
      search_for(dependency).count,
    ]
  end
end