<commit_before>module Pod

  # A {LocalPod} interfaces one or more specifications belonging to one pod
  # (a library) and their concrete instance in the file system.
  #
  # The {LocalPod} is responsible for orchestrating the activated
  # specifications of a single pod. Specifically, it keeps track of the
  # activated specifications and handles issues related to duplicates
  # files.
  # Inheritance logic belongs to the {Specification} class.
  #
  # The activated specifications are used to compute the paths that can be
  # safely cleaned by the pod.
  #
  # @example
  #     pod = LocalPod.new 'RestKit/Networking'
  #     pod.add_specification 'RestKit/UI'
  #
  # @note
  #   Unless otherwise specified in the name of the method the {LocalPod}
  #   returns absolute paths.
  #
  class LocalPod

    # @return [Specification] The specification that describes the pod.
    #
    attr_reader :top_specification

    # @return [Specification] The activated specifications of the pod.
    #
    attr_reader :specifications

    # @return [Sandbox] The sandbox where the pod is installed.
    #
    attr_reader :sandbox

    # @return [Platform] The platform that will be used to build the pod.
    #
    attr_reader :platform

    # @return [Boolean] Wether or not the pod has been downloaded in the
    #                   current install process and still needs its docs
    #                   generated and be cleaned.
    #
    attr_accessor :downloaded
    alias_method :downloaded?, :downloaded

    # @param [Specification] specification  The first activated specification
    #                                       of the pod.
    #
    # @param [Sandbox] sandbox              The sandbox where the files of the
    #                                       pod will be located.
    #
    # @param [Platform] platform            The platform that will be used to
    #                                       build the pod.
    #
    # @todo The local pod should be initialized with all the activated
    #       specifications passed as an array, in order to be able to cache the
    #       computed values. In other words, it should be immutable.
    #
    def initialize(specification, sandbox, platform)
      @top_specification, @sandbox, @platform = specification.top_level_parent, sandbox, platform
      @top_specification.activate_platform(platform)
      @specifications = [] << specification
    end

    # Initializes a local pod from the top specification of a podspec file.
    #
    # @return [LocalPod] A new local pod.
    #
    def self.from_podspec(podspec, sandbox, platform)
      new(Specification.from_file(podspec), sandbox, platform)
    end

    # Activates a specification or subspecs for the pod.
    # Adding specifications is idempotent.
    #
    # @param {Specification} spec The specification to add to the pod.
    #
    # @raise {Informative} If the specification is not part of the same pod.
    #
    def add_specification(spec)
      unless spec.top_level_parent == top_specification
        raise Informative,
          "[Local Pod] Attempt to add a specification from another pod"
      end
      spec.activate_platform(platform)
      @specifications << spec unless @specifications.include?(spec)
    end

    # @return [Pathname] The root directory of the pod
    #
    def root
      @sandbox.root + top_specification.name
    end

    # @return [String] A string representation of the pod which indicates if
    #                  the pods comes from a local source or has a preferred
    #                  dependency.
    #
    def to_s
      s =  top_specification.to_s
      s << " defaulting to #{top_specification.preferred_dependency} subspec" if top_specification.preferred_dependency
      s
    end

    # @return [String] The name of the Pod.
    #
    def name
      top_specification.name
    end

    # @!group Installation

    # Creates the root path of the pod.
    #
    # @return [void]
    #
    def create
      root.mkpath unless exists?
    end

    # Whether the root path of the pod exists.
    #
    def exists?
      root.exist?
    end

    # Executes a block in the root directory of the Pod.
    #
    # @return [void]
    #
    def chdir(&block)
      create
      Dir.chdir(root, &block)
    end

    # Deletes the pod from the file system.
    #
    # @return [void]
    #
    def implode
      root.rmtree if exists?
    end

    def local?
      false
    end

    # @!group Cleaning

    # Deletes any path that is not used by the pod.
    #
    # @return [void]
    #
    def clean!
      clean_paths.each { |path| FileUtils.rm_rf(path) }
      @cleaned = true
    end

    # Finds the absolute paths, including hidden ones, of the files
    # that are not used by the pod and thus can be safely deleted.
    #
    # @return [Array<Strings>] The paths that can be deleted.
    #
    # @note The Paths are downcased to prevent issues. See #568.
    #
    def clean_paths
      used = used_files.map(&:downcase)
      files = Dir.glob(root + "**/*", [File::FNM_DOTMATCH, File::FNM_CASEFOLD])

      files.reject! do |candidate|
        candidate.end_with?('.', '..') || used.any? do |path|
          path.include?(candidate) || candidate.include?(path)
        end
      end
      files
    end

    # @return [Array<String>] The absolute path of the files used by the pod.
    #
    def used_files
      files = [ source_files, resource_files, preserve_files, readme_file, license_file, prefix_header_file ]
      files.compact!
      files.flatten!
      files.map!{ |path| path.to_s }
      files
    end

    # @!group Files

    # @return [Pathname] Returns the relative path from the sandbox.
    #
    # @note If the two abosule paths don't share the same root directory an
    # extra `../` is added to the result of {Pathname#relative_path_from}
    #
    #     path = Pathname.new('/Users/dir')
    #     @sandbox
    #     #=> Pathname('/tmp/CocoaPods/Lint/Pods')
    #<commit_msg>Fixing a bug where `downcase` was being called on the list of used file paths<commit_after>module Pod

  # A {LocalPod} interfaces one or more specifications belonging to one pod
  # (a library) and their concrete instance in the file system.
  #
  # The {LocalPod} is responsible for orchestrating the activated
  # specifications of a single pod. Specifically, it keeps track of the
  # activated specifications and handles issues related to duplicates
  # files.
  # Inheritance logic belongs to the {Specification} class.
  #
  # The activated specifications are used to compute the paths that can be
  # safely cleaned by the pod.
  #
  # @example
  #     pod = LocalPod.new 'RestKit/Networking'
  #     pod.add_specification 'RestKit/UI'
  #
  # @note
  #   Unless otherwise specified in the name of the method the {LocalPod}
  #   returns absolute paths.
  #
  class LocalPod

    # @return [Specification] The specification that describes the pod.
    #
    attr_reader :top_specification

    # @return [Specification] The activated specifications of the pod.
    #
    attr_reader :specifications

    # @return [Sandbox] The sandbox where the pod is installed.
    #
    attr_reader :sandbox

    # @return [Platform] The platform that will be used to build the pod.
    #
    attr_reader :platform

    # @return [Boolean] Wether or not the pod has been downloaded in the
    #                   current install process and still needs its docs
    #                   generated and be cleaned.
    #
    attr_accessor :downloaded
    alias_method :downloaded?, :downloaded

    # @param [Specification] specification  The first activated specification
    #                                       of the pod.
    #
    # @param [Sandbox] sandbox              The sandbox where the files of the
    #                                       pod will be located.
    #
    # @param [Platform] platform            The platform that will be used to
    #                                       build the pod.
    #
    # @todo The local pod should be initialized with all the activated
    #       specifications passed as an array, in order to be able to cache the
    #       computed values. In other words, it should be immutable.
    #
    def initialize(specification, sandbox, platform)
      @top_specification, @sandbox, @platform = specification.top_level_parent, sandbox, platform
      @top_specification.activate_platform(platform)
      @specifications = [] << specification
    end

    # Initializes a local pod from the top specification of a podspec file.
    #
    # @return [LocalPod] A new local pod.
    #
    def self.from_podspec(podspec, sandbox, platform)
      new(Specification.from_file(podspec), sandbox, platform)
    end

    # Activates a specification or subspecs for the pod.
    # Adding specifications is idempotent.
    #
    # @param {Specification} spec The specification to add to the pod.
    #
    # @raise {Informative} If the specification is not part of the same pod.
    #
    def add_specification(spec)
      unless spec.top_level_parent == top_specification
        raise Informative,
          "[Local Pod] Attempt to add a specification from another pod"
      end
      spec.activate_platform(platform)
      @specifications << spec unless @specifications.include?(spec)
    end

    # @return [Pathname] The root directory of the pod
    #
    def root
      @sandbox.root + top_specification.name
    end

    # @return [String] A string representation of the pod which indicates if
    #                  the pods comes from a local source or has a preferred
    #                  dependency.
    #
    def to_s
      s =  top_specification.to_s
      s << " defaulting to #{top_specification.preferred_dependency} subspec" if top_specification.preferred_dependency
      s
    end

    # @return [String] The name of the Pod.
    #
    def name
      top_specification.name
    end

    # @!group Installation

    # Creates the root path of the pod.
    #
    # @return [void]
    #
    def create
      root.mkpath unless exists?
    end

    # Whether the root path of the pod exists.
    #
    def exists?
      root.exist?
    end

    # Executes a block in the root directory of the Pod.
    #
    # @return [void]
    #
    def chdir(&block)
      create
      Dir.chdir(root, &block)
    end

    # Deletes the pod from the file system.
    #
    # @return [void]
    #
    def implode
      root.rmtree if exists?
    end

    def local?
      false
    end

    # @!group Cleaning

    # Deletes any path that is not used by the pod.
    #
    # @return [void]
    #
    def clean!
      clean_paths.each { |path| FileUtils.rm_rf(path) }
      @cleaned = true
    end

    # Finds the absolute paths, including hidden ones, of the files
    # that are not used by the pod and thus can be safely deleted.
    #
    # @return [Array<Strings>] The paths that can be deleted.
    #
    # @note The Paths are downcased to prevent issues. See #568.
    #
    def clean_paths
      used = used_files
      files = Dir.glob(root + "**/*", [File::FNM_DOTMATCH, File::FNM_CASEFOLD])

      files.reject! do |candidate|
        candidate.end_with?('.', '..') || used.any? do |path|
          path.include?(candidate) || candidate.include?(path)
        end
      end
      files
    end

    # @return [Array<String>] The absolute path of the files used by the pod.
    #
    def used_files
      files = [ source_files, resource_files, preserve_files, readme_file, license_file, prefix_header_file ]
      files.compact!
      files.flatten!
      files.map!{ |path| path.to_s }
      files
    end

    # @!group Files

    # @return [Pathname] Returns the relative path from the sandbox.
    #
    # @note If the two abosule paths don't share the same root directory an
    # extra `../` is added to the result of {Pathname#relative_path_from}
    #
    #     path = Pathname.new('/Users/dir')
    #     @sandbox
    #     #=> Pathname('/tmp/CocoaPods/Lint/Pods')
    #
{'fraction_non_alphanumeric': 0.07579034941763726, 'fraction_numerical': 0.0004991680532445924, 'mean_word_length': 2.2577235772357724, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5907605', 'n_tokens_mistral': 3520, 'n_tokens_neox': 3377, 'n_words': 1242}