class Pod::Installer

Public Instance Methods

alter_specs_for_prebuilt_pods() click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/alter_specs.rb, line 3
def alter_specs_for_prebuilt_pods
  cache = []

  @original_specs = analysis_result.specifications
    .map { |spec| [spec.name, Pod::Specification.from_file(spec.defined_in_file)] }
    .to_h

  analysis_result.specifications
    .select { |spec| should_integrate_prebuilt_pod?(spec.root.name) }
    .group_by(&:root)
    .each do |_, specs|
      first_subspec_or_self = specs.find(&:subspec?) || specs[0]
      specs.each do |spec|
        alterations = {
          :source_files => true,
          :resources => true,
          :license => true,
          :vendored_framework => spec == first_subspec_or_self
        }
        alter_spec(spec, alterations, cache)
      end
    end
end
create_pod_installer(name) click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/patch/source_installation.rb, line 7
def create_pod_installer(name)
  if should_integrate_prebuilt_pod?(name)
    create_prebuilt_source_installer(name)
  else
    create_normal_source_installer(name)
  end
end
original_create_pod_installer(name)

Override the download step to skip download and prepare file in target folder

prebuilt_pod_names() click to toggle source

Returns the names of pod targets detected as prebuilt, including those declared in Podfile and their dependencies

# File lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/installer.rb, line 5
def prebuilt_pod_names
  prebuilt_pod_targets.map(&:name).to_set
end
prebuilt_pod_targets() click to toggle source

Returns the pod targets detected as prebuilt, including those declared in Podfile and their dependencies

# File lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/installer.rb, line 11
def prebuilt_pod_targets
  @prebuilt_pod_targets ||= begin
    explicit_prebuilt_pod_names = aggregate_targets
      .flat_map { |target| target.target_definition.explicit_prebuilt_pod_names }
      .uniq

    targets = pod_targets.select { |target| explicit_prebuilt_pod_names.include?(target.pod_name) }
    dependencies = targets.flat_map(&:recursive_dependent_targets) # Treat dependencies as prebuilt pods
    all = (targets + dependencies).uniq
    all = all.reject { |target| sandbox.local?(target.pod_name) } unless PodPrebuild.config.dev_pods_enabled?
    all
  end
end
validate_every_pod_only_have_one_form() click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/validation.rb, line 3
def validate_every_pod_only_have_one_form
  multi_targets_pods = pod_targets
    .group_by(&:pod_name)
    .select do |_, targets|
      is_multi_targets = targets.map { |t| t.platform.name }.uniq.count > 1
      is_multi_forms = targets.map { |t| prebuilt_pod_targets.include?(t) }.uniq.count > 1
      is_multi_targets && is_multi_forms
    end
  return if multi_targets_pods.empty?

  warnings = "One pod can only be prebuilt or not prebuilt. These pod have different forms in multiple targets:\n"
  warnings += multi_targets_pods
    .map { |name, targets| "         #{name}: #{targets.map { |t| t.platform.name }}" }
    .join("\n")
  raise Informative, warnings
end

Private Instance Methods

add_vendered_framework(spec, platform, added_framework_file_path) click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/alter_specs.rb, line 98
def add_vendered_framework(spec, platform, added_framework_file_path)
  spec.attributes_hash[platform] = {} if spec.attributes_hash[platform].nil?
  vendored_frameworks = spec.attributes_hash[platform]["vendored_frameworks"] || []
  vendored_frameworks = [vendored_frameworks] if vendored_frameworks.is_a?(String)
  vendored_frameworks += [added_framework_file_path]
  spec.attributes_hash[platform]["vendored_frameworks"] = vendored_frameworks
end
alter_spec(spec, alterations, cache) click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/alter_specs.rb, line 29
def alter_spec(spec, alterations, cache)
  targets = Pod.fast_get_targets_for_pod_name(spec.root.name, pod_targets, cache)
  platforms = targets.map { |target| target.platform.name.to_s }.uniq

  if alterations[:vendored_framework]
    targets.each do |target|
      # Use the prebuilt frameworks as vendered frameworks.
      # The framework_file_path rule is decided in `install_for_prebuild`,
      # as to compitable with older version and be less wordy.
      framework_file_path = target.framework_name
      framework_file_path = target.name + "/" + framework_file_path if targets.count > 1
      framework_file_path = PodPrebuild.config.prebuilt_path(path: framework_file_path)
      add_vendered_framework(spec, target.platform.name.to_s, framework_file_path)
    end
  end

  empty_source_files(spec, platforms) if alterations[:source_files]
  tweak_resources_for_xib(spec, platforms) if alterations[:resources]
  tweak_resources_for_resource_bundles(spec, platforms) if alterations[:resources]
  empty_liscence(spec) if alterations[:license]
end
create_normal_source_installer(name) click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/patch/source_installation.rb, line 17
def create_normal_source_installer(name)
  original_create_pod_installer(name)
end
create_prebuilt_source_installer(name) click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/patch/source_installation.rb, line 28
def create_prebuilt_source_installer(name)
  # A source installer needs to install with the original spec (instead of the altered spec).
  # Otherwise, the cache will be corrupted because CocoaPods packs necessary dirs/files from temp dir
  # to the cache dir based on the spec.
  source_installer = PodSourceInstaller.new(sandbox, podfile, original_specs_by_platform(name))
  pod_installer = PrebuiltSourceInstaller.new(
    sandbox,
    podfile,
    specs_for_pod(name),
    source_installer: source_installer
  )
  pod_installers << pod_installer
  pod_installer
end
empty_liscence(spec) click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/alter_specs.rb, line 113
def empty_liscence(spec)
  spec.attributes_hash["license"] = {}
  spec.root.attributes_hash["license"] = {}
end
empty_source_files(spec, platforms) click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/alter_specs.rb, line 106
def empty_source_files(spec, platforms)
  spec.attributes_hash["source_files"] = []
  platforms.each do |platform|
    spec.attributes_hash[platform]["source_files"] = [] unless spec.attributes_hash[platform].nil?
  end
end
original_specs_by_platform(name) click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/patch/source_installation.rb, line 21
def original_specs_by_platform(name)
  specs_for_pod(name).map do |platform, specs|
    specs_ = specs.map { |spec| @original_specs[spec.name] }
    [platform, specs_]
  end.to_h
end
should_integrate_prebuilt_pod?(name) click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/patch/source_installation.rb, line 43
def should_integrate_prebuilt_pod?(name)
  if PodPrebuild.config.prebuild_job? && PodPrebuild.config.targets_to_prebuild_from_cli.empty?
    # In a prebuild job, at the integration stage, all prebuilt frameworks should be
    # ready for integration regardless of whether there was any cache miss or not.
    # Those that are missed were prebuilt in the prebuild stage.
    PodPrebuild.state.cache_validation.include?(name)
  else
    prebuilt = PodPrebuild.state.cache_validation.hit + PodPrebuild.config.targets_to_prebuild_from_cli
    prebuilt.include?(name)
  end
end
tweak_resources_for_resource_bundles(spec, platforms) click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/alter_specs.rb, line 78
def tweak_resources_for_resource_bundles(spec, platforms)
  add_resource_bundles_to_resources = lambda do |attributes|
    return if attributes.nil?

    resource_bundles = attributes["resource_bundles"] || {}
    resource_bundle_names = resource_bundles.keys
    attributes["resource_bundles"] = nil
    attributes["resources"] ||= []
    attributes["resources"] = [attributes["resources"]] if attributes["resources"].is_a?(String)
    attributes["resources"] += resource_bundle_names.map do |name|
      PodPrebuild.config.prebuilt_path(path: "#{name}.bundle")
    end
  end

  add_resource_bundles_to_resources.call(spec.attributes_hash)
  platforms.each do |platform|
    add_resource_bundles_to_resources.call(spec.attributes_hash[platform])
  end
end
tweak_resources_for_xib(spec, platforms) click to toggle source
# File lib/cocoapods-binary-cache/pod-binary/integration/alter_specs.rb, line 51
def tweak_resources_for_xib(spec, platforms)
  # This is a workaround for prebuilt static framework that has `*.xib` files in the resources
  # (declared by `spec.resources = ...`)
  # ---------------------------------------------------------------
  # In the prebuild stage, a XIB file is compiled as a NIB file in the framework.
  # In the integration stage, this file is added to the script `Pods-<Target>-resources.sh`:
  #   - If it's a XIB, it's installed to the target bundle by `ibtool`
  #   - If it's a NIB, it's copied directly to the target bundle
  # Since the one embedded in the prebuilt framework is a NIB (already compiled)
  # --> We need to alter the spec so that this file will be copied to the target bundle
  change_xib_to_nib = ->(path) { path.sub(".xib", ".nib") }
  update_resources = lambda do |resources|
    if resources.is_a?(String)
      change_xib_to_nib.call(resources)
    elsif resources.is_a?(Array)
      resources.map { |item| change_xib_to_nib.call(item) }
    end
  end
  spec.attributes_hash["resources"] = update_resources.call(spec.attributes_hash["resources"])
  platforms.each do |platform|
    next if spec.attributes_hash[platform].nil?

    platform_resources = spec.attributes_hash[platform]["resources"]
    spec.attributes_hash[platform]["resources"] = update_resources.call(platform_resources)
  end
end