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:



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