Class: Pod::DyResolver

Inherits:
Object
  • Object
show all
Includes:
Molinillo::SpecificationProvider, Molinillo::UI, Installer::InstallationOptions::Mixin
Defined in:
lib/pod/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

Resolution collapse

Instance Method Summary collapse

Constructor Details

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

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/pod/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/pod/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/pod/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/pod/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/pod/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/pod/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)


348
349
# File 'lib/pod/resolver.rb', line 348

def after_resolution
end

#before_resolutionVoid

Called before resolution starts.

Completely silence this, as we show nothing.

Returns:

  • (Void)


339
340
# File 'lib/pod/resolver.rb', line 339

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



213
214
215
216
217
218
219
220
221
# File 'lib/pod/resolver.rb', line 213

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)


357
358
# File 'lib/pod/resolver.rb', line 357

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



230
231
232
# File 'lib/pod/resolver.rb', line 230

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.



236
237
238
# File 'lib/pod/resolver.rb', line 236

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.



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

def name_for_locking_dependency_source
  'Podfile.lock'
end

#outputUserInterface

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

Returns:

  • (UserInterface)

    the normal CocoaPods UI object.



329
330
331
# File 'lib/pod/resolver.rb', line 329

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.



259
260
261
262
263
264
265
266
267
# File 'lib/pod/resolver.rb', line 259

def requirement_satisfied_by?(requirement, activated, spec)
  version = spec.version
  return false unless requirement.requirement.satisfied_by?(version)
  shared_possibility_versions, prerelease_requirement = possibility_versions_for_root_name(requirement, activated)
  return false if !shared_possibility_versions.empty? && !shared_possibility_versions.include?(version)
  return false if version.prerelease? && !prerelease_requirement
  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
128
129
130
131
# File 'lib/pod/resolver.rb', line 115

def resolve
  puts "before resolve...#{Time.now}"
  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
  puts "after flat map...#{Time.now}"
  @platforms_by_dependency.each_value(&:uniq!)
  puts "after each...#{Time.now}"
  @activated = Molinillo::Resolver.new(self, self).resolve(dependencies, locked_dependencies)
  puts "after resolve...#{Time.now}"
  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.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/pod/resolver.rb', line 138

def resolver_specs_by_target
  puts "before resolver_specs_by_target...#{Time.now}"
  @resolver_specs_by_target ||= {}.tap do |resolver_specs_by_target|
    dependencies = {}
    puts "#{resolver_specs_by_target} before each...#{Time.now}"
    @podfile_dependency_cache.target_definition_list.each do |target|
      # 读取 Podfile 中每个 target 的 dependency 信息,每个 pod 对应一个 dep
      specs = @podfile_dependency_cache.target_definition_dependencies(target).flat_map do |dep|
        name = dep.name
        node = @activated.vertex_named(name)
        before = Time.now
        noded = valid_dependencies_for_target_from_node(target, dependencies, node) << node
        # puts "  - [resolver][resolver_specs_by_target][#{name}] dependencies : #{dependencies.count}, valid_dependencies_for_specs : #{noded.count}, node : #{node.name}, outgoing_edges : #{node.outgoing_edges.count}"
        # puts "    - #{noded}"
        # puts "    - #{node.payload}"
        # puts "    - #{dependencies}"
        after_noded = Time.now
        result = noded.map { |s| [s, node.payload.test_specification?] }
        after = Time.now
        if after - before > 1
          puts "  - [resolver][resolver_specs_by_target][#{target}] : #{after - after_noded} : #{after - before} #{name} #{result.count} "
        end
        result
      end

      grouped = specs.
        group_by(&:first)
      # resolver_specs_by_target[target] = specs.
      #   group_by(&:first).
      resolver_specs_by_target[target] = grouped.
        map do |vertex, spec_test_only_tuples|
          # puts "  - #{vertex.name}\t#{spec_test_only_tuples.count}\t#{vertex.recursive_predecessors.count}" if vertex.name == 'SDWebImage/Core'
          test_only = spec_test_only_tuples.all? { |tuple| tuple[1] }
          payload = vertex.payload
          spec_source = payload.respond_to?(:spec_source) && payload.spec_source
          result = ResolverSpecification.new(payload, test_only, spec_source)
          result
        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`.



196
197
198
199
200
201
202
203
204
# File 'lib/pod/resolver.rb', line 196

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.



304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/pod/resolver.rb', line 304

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