Class: Pod::Resolver

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

Overview

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

Instance Attribute Summary collapse

Resolution collapse

Instance Method Summary collapse

Constructor Details

#initialize(sandbox, podfile, locked_dependencies, sources) ⇒ 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



35
36
37
38
39
40
41
# File 'lib/cocoapods/resolver.rb', line 35

def initialize(sandbox, podfile, locked_dependencies, sources)
  @sandbox = sandbox
  @podfile = podfile
  @locked_dependencies = locked_dependencies
  @sources = Array(sources)
  @platforms_by_dependency = Hash.new { |h, k| h[k] = [] }
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.



21
22
23
# File 'lib/cocoapods/resolver.rb', line 21

def locked_dependencies
  @locked_dependencies
end

#podfilePodfile (readonly)

Returns the Podfile used by the resolver.

Returns:

  • (Podfile)

    the Podfile used by the resolver.



16
17
18
# File 'lib/cocoapods/resolver.rb', line 16

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.



12
13
14
# File 'lib/cocoapods/resolver.rb', line 12

def sandbox
  @sandbox
end

#sourcesArray<Source>

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.



26
27
28
# File 'lib/cocoapods/resolver.rb', line 26

def sources
  @sources
end

Instance Method Details

#after_resolutionVoid

Called after resolution ends.

Completely silence this, as we show nothing.

Returns:

  • (Void)


251
252
# File 'lib/cocoapods/resolver.rb', line 251

def after_resolution
end

#before_resolutionVoid

Called before resolution starts.

Completely silence this, as we show nothing.

Returns:

  • (Void)


242
243
# File 'lib/cocoapods/resolver.rb', line 242

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`.



129
130
131
132
133
134
135
136
137
# File 'lib/cocoapods/resolver.rb', line 129

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)


260
261
# File 'lib/cocoapods/resolver.rb', line 260

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`.



146
147
148
# File 'lib/cocoapods/resolver.rb', line 146

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.



152
153
154
# File 'lib/cocoapods/resolver.rb', line 152

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.



158
159
160
# File 'lib/cocoapods/resolver.rb', line 158

def name_for_locking_dependency_source
  'Podfile.lock'
end

#outputUserInterface

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

Returns:



232
233
234
# File 'lib/cocoapods/resolver.rb', line 232

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.



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/cocoapods/resolver.rb', line 175

def requirement_satisfied_by?(requirement, activated, spec)
  existing_vertices = activated.vertices.values.select do |v|
    Specification.root_name(v.name) ==  requirement.root_name
  end
  existing = existing_vertices.map(&:payload).compact.first
  requirement_satisfied =
    if existing
      existing.version == spec.version && requirement.requirement.satisfied_by?(spec.version)
    else
      requirement.requirement.satisfied_by? spec.version
    end
  requirement_satisfied && !(
    spec.version.prerelease? &&
    existing_vertices.flat_map(&:requirements).none? { |r| r.prerelease? || r.external_source || r.head? }
  ) && spec_is_platform_compatible?(activated, requirement, spec)
end

#resolveHash{TargetDefinition => Array<Specification>}

Identifies the specifications that should be installed.

Returns:

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

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



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/cocoapods/resolver.rb', line 55

def resolve
  dependencies = podfile.target_definition_list.flat_map do |target|
    target.dependencies.each do |dep|
      @platforms_by_dependency[dep].push(target.platform).uniq!
    end
  end
  @cached_sets = {}
  @activated = Molinillo::Resolver.new(self, self).resolve(dependencies, locked_dependencies)
  specs_by_target.tap do |specs_by_target|
    specs_by_target.values.flatten.each do |spec|
      sandbox.store_head_pod(spec.name) if spec.version.head?
    end
  end
rescue Molinillo::ResolverError => e
  handle_resolver_error(e)
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`.



108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/cocoapods/resolver.rb', line 108

def search_for(dependency)
  @search ||= {}
  @search[dependency] ||= begin
    requirement = Requirement.new(dependency.requirement.as_list << requirement_for_locked_pod_named(dependency.name))
    find_cached_set(dependency).
      all_specifications.
      select { |s| requirement.satisfied_by? s.version }.
      map { |s| s.subspec_by_name(dependency.name, false) }.
      compact.
      reverse
  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.



208
209
210
211
212
213
214
215
216
217
218
# File 'lib/cocoapods/resolver.rb', line 208

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

#specs_by_targetHash{Podfile::TargetDefinition => Array<Specification>}

Note:

The returned specifications can be subspecs.

Returns the resolved specifications grouped by target.

Returns:

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

    returns the resolved specifications grouped by target.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/cocoapods/resolver.rb', line 77

def specs_by_target
  @specs_by_target ||= {}.tap do |specs_by_target|
    podfile.target_definition_list.each do |target|
      specs = target.dependencies.map(&:name).flat_map do |name|
        node = @activated.vertex_named(name)
        valid_dependencies_for_target_from_node(target, node) << node
      end

      specs_by_target[target] = specs.
        map(&:payload).
        uniq.
        sort_by(&:name)
    end
  end
end