<commit_before>require 'active_support/core_ext/string/inflections'

module Pod

  # The Installer is responsible of taking a Podfile and transform it in the
  # Pods libraries. It also integrates the user project so the Pods
  # libraries can be used out of the box.
  #
  # The Installer is capable of doing incremental updates to an existing Pod
  # installation.
  #
  # The Installer gets the information that it needs mainly from 3 files:
  #
  #   - Podfile: The specification written by the user that contains
  #     information about targets and Pods.
  #   - Podfile.lock: Contains information about the pods that were previously
  #     installed and in concert with the Podfile provides information about
  #     which specific version of a Pod should be installed. This file is
  #     ignored in update mode.
  #   - Manifest.lock: A file contained in the Pods folder that keeps track of
  #     the pods installed in the local machine. This files is used once the
  #     exact versions of the Pods has been computed to detect if that version
  #     is already installed. This file is not intended to be kept under source
  #     control and is a copy of the Podfile.lock.
  #
  # The Installer is designed to work in environments where the Podfile folder
  # is under source control and environments where it is not. The rest of the
  # files, like the user project and the workspace are assumed to be under
  # source control.
  #
  class Installer

    autoload :Analyzer,                 'cocoapods/installer/analyzer'
    autoload :FileReferencesInstaller,  'cocoapods/installer/file_references_installer'
    autoload :PodSourceInstaller,       'cocoapods/installer/pod_source_installer'
    autoload :TargetInstaller,          'cocoapods/installer/target_installer'
    autoload :AggregateTargetInstaller, 'cocoapods/installer/target_installer/aggregate_target_installer'
    autoload :PodTargetInstaller,       'cocoapods/installer/target_installer/pod_target_installer'
    autoload :UserProjectIntegrator,    'cocoapods/installer/user_project_integrator'

    include Config::Mixin

    # @return [Sandbox] The sandbox where the Pods should be installed.
    #
    attr_reader :sandbox

    # @return [Podfile] The Podfile specification that contains the information
    #         of the Pods that should be installed.
    #
    attr_reader :podfile

    # @return [Lockfile] The Lockfile that stores the information about the
    #         Pods previously installed on any machine.
    #
    attr_reader :lockfile

    # @param  [Sandbox]  sandbox     @see sandbox
    # @param  [Podfile]  podfile     @see podfile
    # @param  [Lockfile] lockfile    @see lockfile
    #
    def initialize(sandbox, podfile, lockfile = nil)
      @sandbox  = sandbox
      @podfile  = podfile
      @lockfile = lockfile
    end

    # @return [Hash, Boolean, nil] Pods that have been requested to be
    #         updated or true if all Pods should be updated.
    #         If all Pods should been updated the contents of the Lockfile are
    #         not taken into account for deciding what Pods to install.
    #
    attr_accessor :update

    # Installs the Pods.
    #
    # The installation process of is mostly linear with few minor complications
    # to keep in mind:
    #
    # - The stored podspecs need to be cleaned before the resolution step
    #   otherwise the sandbox might return an old podspec and not download
    #   the new one from an external source.
    # - The resolver might trigger the download of Pods from external sources
    #   necessary to retrieve their podspec (unless it is instructed not to
    #   do it).
    #
    # @return [void]
    #
    def install!
      resolve_dependencies
      download_dependencies
      generate_pods_project
      integrate_user_project if config.integrate_targets?
    end

    def resolve_dependencies
      UI.section "Analyzing dependencies" do
        analyze
        prepare_for_legacy_compatibility
        clean_sandbox
      end
    end

    def download_dependencies
      UI.section "Downloading dependencies" do
        create_file_accessors
        install_pod_sources
        run_pre_install_hooks
        clean_pod_sources
      end
    end

    def generate_pods_project
      UI.section "Generating Pods project" do
        prepare_pods_project
        install_file_references
        install_libraries
        set_target_dependencies
        link_aggregate_target
        run_post_install_hooks
        write_pod_project
        write_lockfiles
      end
    end

    #-------------------------------------------------------------------------#

    public

    # @!group Installation results

    # @return [Analyzer] the analyzer which provides the information about what
    #         needs to be installed.
    #
    attr_reader :analysis_result

    # @return [Pod::Project] the `Pods/Pods.xcodeproj` project.
    #
    attr_reader :pods_project

    # @return [Array<String>] The Pods that should be installed.
    #
    attr_reader :names_of_pods_to_install

    # @return [Array<AggregateTarget>] The Podfile targets containing library
    #         dependencies.
    #
    attr_reader :aggregate_targets

    # @return [Array<Specification>] The specifications that where installed.
    #
    attr_accessor :installed_specs

    #-------------------------------------------------------------------------#

    private

    # @!group Installation steps

    # @return [void]
    #
    # @note   The warning about the version of the Lockfile doesn't use the
    #         `UI.warn` method because it prints the output only at the end
    #         of the installation. At that time CocoaPods could have crashed.
    #
    def analyze
      if lockfile && lockfile.cocoapods_version > Version.new(VERSION)
        STDERR.puts '[!] The version of CocoaPods used to generate the lockfile is '\
          'higher than the version of the current executable. Incompatibility ' \
          'issues may arise.'.yellow
      end

      analyzer = Analyzer.new(sandbox, podfile, lockfile)
      analyzer.update = update
      @analysis_result = analyzer.analyze
      @aggregate_targets = analyzer.result.targets
    end

    # Prepares the Pods folder in order to be compatible with the most recent
    # version of CocoaPods.
    #
    # @return [void]
    #
    def prepare_for_legacy_compatibility
      # move_target_support_files_if_needed
      # move_Local_Podspecs_to_Podspecs_if_needed
      # move_pods_to_sources_folder_if_needed
    end

    # @return [void] In this step we clean all the folders that will be
    #         regenerated from scratch and any file which might not be
    #         overwritten.
    #
    # @todo   [#247] Clean the headers of only the pods to install.
    #
    def clean_sandbox
      sandbox.public_headers.implode!
      pod_targets.each do |pod_target|
        pod_target.build_headers.implode!
      end

      unless sandbox_state.deleted.empty?
        title_options = { :verbose_prefix => "-> ".red }
        sandbox_state.deleted.each do |pod_name|
          UI.titled_section("Removing #{pod_name}".red, title_options) do
            sandbox.clean_pod(pod_name)
          end
        end
      end
    end

    # TODO: the file accessor should be initialized by the sandbox as they
    #       created by the Pod source installer as well.
    #
    def create_file_accessors
      aggregate_targets.each do |target|
        target.pod_targets.each do |pod_target|
          pod_root = sandbox.pod_dir(pod_target.root_spec.name)
          path_list = Sandbox::PathList.new(pod_root)
          file_accessors = pod_target.specs.map do |spec|
            Sandbox::FileAccessor.new(path_list, spec.consumer(pod_target.platform))
          end
          pod_target.file_accessors ||= []
          pod_target.file_accessors.concat(file_accessors)
        end
      end
    end

    # Downloads, installs the documentation and cleans the sources of the Pods
    # which need to be installed.
    #
    # @return [void]
    #
    def install_pod_sources
      @installed_specs = []
      pods_to_install = sandbox_state.added | sandbox_state.changed
      title_options = { :verbose_prefix => "-> ".green }
      root_specs.sort_by(&:name).each do |spec|
        if pods_to_install.include?(spec.name) 
          if sandbox_state.changed.include?(spec.name) && sandbox.manifest
            title = "Installing #{spec.name} #{spec.version} (was #{sandbox.manifest.version(spec.name)})"
          else
            title = "Installing #{spec}"
          end
          UI.titled_section(title.green, title_options) do
            install_source_of_pod(spec.name)
          end
        else
          UI.titled_section("Using #{spec}", title_options)
        end
      end
    end

    # Install the Pods. If the resolver indicated that a Pod should be
    # installed and it exits, it is removed an then reinstalled. In any case if
    # the Pod doesn't exits it is installed.
    #
    # @return [void]
    #
    def install_source_of_pod(pod_name)
      specs_by_platform = {}
      pod_targets.each do |pod_target|
        if pod_target.root_spec.name == pod_name
          specs_by_platform[pod_target.platform] ||= []<commit_msg>Trimmed line length<commit_after>require 'active_support/core_ext/string/inflections'

module Pod

  # The Installer is responsible of taking a Podfile and transform it in the
  # Pods libraries. It also integrates the user project so the Pods
  # libraries can be used out of the box.
  #
  # The Installer is capable of doing incremental updates to an existing Pod
  # installation.
  #
  # The Installer gets the information that it needs mainly from 3 files:
  #
  #   - Podfile: The specification written by the user that contains
  #     information about targets and Pods.
  #   - Podfile.lock: Contains information about the pods that were previously
  #     installed and in concert with the Podfile provides information about
  #     which specific version of a Pod should be installed. This file is
  #     ignored in update mode.
  #   - Manifest.lock: A file contained in the Pods folder that keeps track of
  #     the pods installed in the local machine. This files is used once the
  #     exact versions of the Pods has been computed to detect if that version
  #     is already installed. This file is not intended to be kept under source
  #     control and is a copy of the Podfile.lock.
  #
  # The Installer is designed to work in environments where the Podfile folder
  # is under source control and environments where it is not. The rest of the
  # files, like the user project and the workspace are assumed to be under
  # source control.
  #
  class Installer

    autoload :Analyzer,                 'cocoapods/installer/analyzer'
    autoload :FileReferencesInstaller,  'cocoapods/installer/file_references_installer'
    autoload :PodSourceInstaller,       'cocoapods/installer/pod_source_installer'
    autoload :TargetInstaller,          'cocoapods/installer/target_installer'
    autoload :AggregateTargetInstaller, 'cocoapods/installer/target_installer/aggregate_target_installer'
    autoload :PodTargetInstaller,       'cocoapods/installer/target_installer/pod_target_installer'
    autoload :UserProjectIntegrator,    'cocoapods/installer/user_project_integrator'

    include Config::Mixin

    # @return [Sandbox] The sandbox where the Pods should be installed.
    #
    attr_reader :sandbox

    # @return [Podfile] The Podfile specification that contains the information
    #         of the Pods that should be installed.
    #
    attr_reader :podfile

    # @return [Lockfile] The Lockfile that stores the information about the
    #         Pods previously installed on any machine.
    #
    attr_reader :lockfile

    # @param  [Sandbox]  sandbox     @see sandbox
    # @param  [Podfile]  podfile     @see podfile
    # @param  [Lockfile] lockfile    @see lockfile
    #
    def initialize(sandbox, podfile, lockfile = nil)
      @sandbox  = sandbox
      @podfile  = podfile
      @lockfile = lockfile
    end

    # @return [Hash, Boolean, nil] Pods that have been requested to be
    #         updated or true if all Pods should be updated.
    #         If all Pods should been updated the contents of the Lockfile are
    #         not taken into account for deciding what Pods to install.
    #
    attr_accessor :update

    # Installs the Pods.
    #
    # The installation process of is mostly linear with few minor complications
    # to keep in mind:
    #
    # - The stored podspecs need to be cleaned before the resolution step
    #   otherwise the sandbox might return an old podspec and not download
    #   the new one from an external source.
    # - The resolver might trigger the download of Pods from external sources
    #   necessary to retrieve their podspec (unless it is instructed not to
    #   do it).
    #
    # @return [void]
    #
    def install!
      resolve_dependencies
      download_dependencies
      generate_pods_project
      integrate_user_project if config.integrate_targets?
    end

    def resolve_dependencies
      UI.section "Analyzing dependencies" do
        analyze
        prepare_for_legacy_compatibility
        clean_sandbox
      end
    end

    def download_dependencies
      UI.section "Downloading dependencies" do
        create_file_accessors
        install_pod_sources
        run_pre_install_hooks
        clean_pod_sources
      end
    end

    def generate_pods_project
      UI.section "Generating Pods project" do
        prepare_pods_project
        install_file_references
        install_libraries
        set_target_dependencies
        link_aggregate_target
        run_post_install_hooks
        write_pod_project
        write_lockfiles
      end
    end

    #-------------------------------------------------------------------------#

    public

    # @!group Installation results

    # @return [Analyzer] the analyzer which provides the information about what
    #         needs to be installed.
    #
    attr_reader :analysis_result

    # @return [Pod::Project] the `Pods/Pods.xcodeproj` project.
    #
    attr_reader :pods_project

    # @return [Array<String>] The Pods that should be installed.
    #
    attr_reader :names_of_pods_to_install

    # @return [Array<AggregateTarget>] The Podfile targets containing library
    #         dependencies.
    #
    attr_reader :aggregate_targets

    # @return [Array<Specification>] The specifications that where installed.
    #
    attr_accessor :installed_specs

    #-------------------------------------------------------------------------#

    private

    # @!group Installation steps

    # @return [void]
    #
    # @note   The warning about the version of the Lockfile doesn't use the
    #         `UI.warn` method because it prints the output only at the end
    #         of the installation. At that time CocoaPods could have crashed.
    #
    def analyze
      if lockfile && lockfile.cocoapods_version > Version.new(VERSION)
        STDERR.puts '[!] The version of CocoaPods used to generate the lockfile is '\
          'higher than the version of the current executable. Incompatibility ' \
          'issues may arise.'.yellow
      end

      analyzer = Analyzer.new(sandbox, podfile, lockfile)
      analyzer.update = update
      @analysis_result = analyzer.analyze
      @aggregate_targets = analyzer.result.targets
    end

    # Prepares the Pods folder in order to be compatible with the most recent
    # version of CocoaPods.
    #
    # @return [void]
    #
    def prepare_for_legacy_compatibility
      # move_target_support_files_if_needed
      # move_Local_Podspecs_to_Podspecs_if_needed
      # move_pods_to_sources_folder_if_needed
    end

    # @return [void] In this step we clean all the folders that will be
    #         regenerated from scratch and any file which might not be
    #         overwritten.
    #
    # @todo   [#247] Clean the headers of only the pods to install.
    #
    def clean_sandbox
      sandbox.public_headers.implode!
      pod_targets.each do |pod_target|
        pod_target.build_headers.implode!
      end

      unless sandbox_state.deleted.empty?
        title_options = { :verbose_prefix => "-> ".red }
        sandbox_state.deleted.each do |pod_name|
          UI.titled_section("Removing #{pod_name}".red, title_options) do
            sandbox.clean_pod(pod_name)
          end
        end
      end
    end

    # TODO: the file accessor should be initialized by the sandbox as they
    #       created by the Pod source installer as well.
    #
    def create_file_accessors
      aggregate_targets.each do |target|
        target.pod_targets.each do |pod_target|
          pod_root = sandbox.pod_dir(pod_target.root_spec.name)
          path_list = Sandbox::PathList.new(pod_root)
          file_accessors = pod_target.specs.map do |spec|
            Sandbox::FileAccessor.new(path_list, spec.consumer(pod_target.platform))
          end
          pod_target.file_accessors ||= []
          pod_target.file_accessors.concat(file_accessors)
        end
      end
    end

    # Downloads, installs the documentation and cleans the sources of the Pods
    # which need to be installed.
    #
    # @return [void]
    #
    def install_pod_sources
      @installed_specs = []
      pods_to_install = sandbox_state.added | sandbox_state.changed
      title_options = { :verbose_prefix => "-> ".green }
      root_specs.sort_by(&:name).each do |spec|
        if pods_to_install.include?(spec.name)
          if sandbox_state.changed.include?(spec.name) && sandbox.manifest
            previous = sandbox.manifest.version(spec.name)
            title = "Installing #{spec.name} #{spec.version} (was #{previous})"
          else
            title = "Installing #{spec}"
          end
          UI.titled_section(title.green, title_options) do
            install_source_of_pod(spec.name)
          end
        else
          UI.titled_section("Using #{spec}", title_options)
        end
      end
    end

    # Install the Pods. If the resolver indicated that a Pod should be
    # installed and it exits, it is removed an then reinstalled. In any case if
    # the Pod doesn't exits it is installed.
    #
    # @return [void]
    #
    def install_source_of_pod(pod_name)
      specs_by_platform = {}
      pod_targets.each do |pod_target|
        if pod_target.root_spec.name == pod_name
          specs_by_platform[pod_target.platform] ||= []
{'fraction_non_alphanumeric': 0.07591327271749072, 'fraction_numerical': 0.0004304083499219885, 'mean_word_length': 2.4415848916867247, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5800835', 'n_tokens_mistral': 5370, 'n_tokens_neox': 5167, 'n_words': 1690}