<commit_before>
require "chef/cookbook_version"
require "chef/cookbook/chefignore"
require "chef/cookbook/metadata"
require "chef/util/path_helper"

class Chef
  class Cookbook
    class CookbookVersionLoader

      FILETYPES_SUBJECT_TO_IGNORE = [ :attribute_filenames,
                                      :definition_filenames,
                                      :recipe_filenames,
                                      :template_filenames,
                                      :file_filenames,
                                      :library_filenames,
                                      :resource_filenames,
                                      :provider_filenames]

      UPLOADED_COOKBOOK_VERSION_FILE = ".uploaded-cookbook-version.json".freeze

      attr_reader :cookbook_settings
      attr_reader :cookbook_paths
      attr_reader :metadata_filenames
      attr_reader :frozen
      attr_reader :uploaded_cookbook_version_file

      attr_reader :cookbook_path

      # The cookbook's name as inferred from its directory.
      attr_reader :inferred_cookbook_name

      attr_reader :metadata_error

      def initialize(path, chefignore = nil)
        @cookbook_path = File.expand_path( path ) # cookbook_path from which this was loaded
        # We keep a list of all cookbook paths that have been merged in
        @cookbook_paths = [ cookbook_path ]

        @inferred_cookbook_name = File.basename( path )
        @chefignore = chefignore
        @metadata = nil
        @relative_path = /#{Regexp.escape(@cookbook_path)}\/(.+)$/
        @metadata_loaded = false
        @cookbook_settings = {
          :all_files            => {},
          :attribute_filenames  => {},
          :definition_filenames => {},
          :recipe_filenames     => {},
          :template_filenames   => {},
          :file_filenames       => {},
          :library_filenames    => {},
          :resource_filenames   => {},
          :provider_filenames   => {},
          :root_filenames       => {},
        }

        @metadata_filenames = []
        @metadata_error = nil
      end

      # Load the cookbook. Raises an error if the cookbook_path given to the
      # constructor doesn't point to a valid cookbook.
      def load!
        file_paths_map = load

        if empty?
          raise Exceptions::CookbookNotFoundInRepo, "The directory #{cookbook_path} does not contain a cookbook"
        end
        file_paths_map
      end

      # Load the cookbook. Does not raise an error if given a non-cookbook
      # directory as the cookbook_path. This behavior is provided for
      # compatibility, it is recommended to use #load! instead.
      def load
        metadata # force lazy evaluation to occur

        # re-raise any exception that occurred when reading the metadata
        raise_metadata_error!

        load_all_files

        remove_ignored_files

        load_as(:attribute_filenames, "attributes", "*.rb")
        load_as(:definition_filenames, "definitions", "*.rb")
        load_as(:recipe_filenames, "recipes", "*.rb")
        load_recursively_as(:library_filenames, "libraries", "*.rb")
        load_recursively_as(:template_filenames, "templates", "*")
        load_recursively_as(:file_filenames, "files", "*")
        load_recursively_as(:resource_filenames, "resources", "*.rb")
        load_recursively_as(:provider_filenames, "providers", "*.rb")
        load_root_files

        if empty?
          Chef::Log.warn "Found a directory #{cookbook_name} in the cookbook path, but it contains no cookbook files. skipping."
        end
        @cookbook_settings
      end

      alias :load_cookbooks :load

      def metadata_filenames
        return @metadata_filenames unless @metadata_filenames.empty?
        if File.exists?(File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE))
          @uploaded_cookbook_version_file = File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE)
        end

        if File.exists?(File.join(cookbook_path, "metadata.rb"))
          @metadata_filenames << File.join(cookbook_path, "metadata.rb")
        elsif File.exists?(File.join(cookbook_path, "metadata.json"))
          @metadata_filenames << File.join(cookbook_path, "metadata.json")
        elsif @uploaded_cookbook_version_file
          @metadata_filenames << @uploaded_cookbook_version_file
        end

        # Set frozen based on .uploaded-cookbook-version.json
        set_frozen
        @metadata_filenames
      end

      def cookbook_version
        return nil if empty?

        Chef::CookbookVersion.new(cookbook_name, *cookbook_paths).tap do |c|
          c.all_files  = cookbook_settings[:all_files].values
          c.attribute_filenames  = cookbook_settings[:attribute_filenames].values
          c.definition_filenames = cookbook_settings[:definition_filenames].values
          c.recipe_filenames     = cookbook_settings[:recipe_filenames].values
          c.template_filenames   = cookbook_settings[:template_filenames].values
          c.file_filenames       = cookbook_settings[:file_filenames].values
          c.library_filenames    = cookbook_settings[:library_filenames].values
          c.resource_filenames   = cookbook_settings[:resource_filenames].values
          c.provider_filenames   = cookbook_settings[:provider_filenames].values
          c.root_filenames       = cookbook_settings[:root_filenames].values
          c.metadata_filenames   = metadata_filenames
          c.metadata             = metadata

          c.freeze_version if @frozen
        end
      end

      def cookbook_name
        # The `name` attribute is now required in metadata, so
        # inferred_cookbook_name generally should not be used. Per CHEF-2923,<commit_msg>Fix style issue<commit_after>
require "chef/cookbook_version"
require "chef/cookbook/chefignore"
require "chef/cookbook/metadata"
require "chef/util/path_helper"

class Chef
  class Cookbook
    class CookbookVersionLoader

      FILETYPES_SUBJECT_TO_IGNORE = [ :attribute_filenames,
                                      :definition_filenames,
                                      :recipe_filenames,
                                      :template_filenames,
                                      :file_filenames,
                                      :library_filenames,
                                      :resource_filenames,
                                      :provider_filenames]

      UPLOADED_COOKBOOK_VERSION_FILE = ".uploaded-cookbook-version.json".freeze

      attr_reader :cookbook_settings
      attr_reader :cookbook_paths
      attr_reader :metadata_filenames
      attr_reader :frozen
      attr_reader :uploaded_cookbook_version_file

      attr_reader :cookbook_path

      # The cookbook's name as inferred from its directory.
      attr_reader :inferred_cookbook_name

      attr_reader :metadata_error

      def initialize(path, chefignore = nil)
        @cookbook_path = File.expand_path( path ) # cookbook_path from which this was loaded
        # We keep a list of all cookbook paths that have been merged in
        @cookbook_paths = [ cookbook_path ]

        @inferred_cookbook_name = File.basename( path )
        @chefignore = chefignore
        @metadata = nil
        @relative_path = /#{Regexp.escape(@cookbook_path)}\/(.+)$/
        @metadata_loaded = false
        @cookbook_settings = {
          :all_files            => {},
          :attribute_filenames  => {},
          :definition_filenames => {},
          :recipe_filenames     => {},
          :template_filenames   => {},
          :file_filenames       => {},
          :library_filenames    => {},
          :resource_filenames   => {},
          :provider_filenames   => {},
          :root_filenames       => {},
        }

        @metadata_filenames = []
        @metadata_error = nil
      end

      # Load the cookbook. Raises an error if the cookbook_path given to the
      # constructor doesn't point to a valid cookbook.
      def load!
        file_paths_map = load

        if empty?
          raise Exceptions::CookbookNotFoundInRepo, "The directory #{cookbook_path} does not contain a cookbook"
        end
        file_paths_map
      end

      # Load the cookbook. Does not raise an error if given a non-cookbook
      # directory as the cookbook_path. This behavior is provided for
      # compatibility, it is recommended to use #load! instead.
      def load
        metadata # force lazy evaluation to occur

        # re-raise any exception that occurred when reading the metadata
        raise_metadata_error!

        load_all_files

        remove_ignored_files

        load_as(:attribute_filenames, "attributes", "*.rb")
        load_as(:definition_filenames, "definitions", "*.rb")
        load_as(:recipe_filenames, "recipes", "*.rb")
        load_recursively_as(:library_filenames, "libraries", "*.rb")
        load_recursively_as(:template_filenames, "templates", "*")
        load_recursively_as(:file_filenames, "files", "*")
        load_recursively_as(:resource_filenames, "resources", "*.rb")
        load_recursively_as(:provider_filenames, "providers", "*.rb")
        load_root_files

        if empty?
          Chef::Log.warn "Found a directory #{cookbook_name} in the cookbook path, but it contains no cookbook files. skipping."
        end
        @cookbook_settings
      end

      alias :load_cookbooks :load

      def metadata_filenames
        return @metadata_filenames unless @metadata_filenames.empty?
        if File.exists?(File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE))
          @uploaded_cookbook_version_file = File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE)
        end

        if File.exists?(File.join(cookbook_path, "metadata.rb"))
          @metadata_filenames << File.join(cookbook_path, "metadata.rb")
        elsif File.exists?(File.join(cookbook_path, "metadata.json"))
          @metadata_filenames << File.join(cookbook_path, "metadata.json")
        elsif @uploaded_cookbook_version_file
          @metadata_filenames << @uploaded_cookbook_version_file
        end

        # Set frozen based on .uploaded-cookbook-version.json
        set_frozen
        @metadata_filenames
      end

      def cookbook_version
        return nil if empty?

        Chef::CookbookVersion.new(cookbook_name, *cookbook_paths).tap do |c|
          c.all_files            = cookbook_settings[:all_files].values
          c.attribute_filenames  = cookbook_settings[:attribute_filenames].values
          c.definition_filenames = cookbook_settings[:definition_filenames].values
          c.recipe_filenames     = cookbook_settings[:recipe_filenames].values
          c.template_filenames   = cookbook_settings[:template_filenames].values
          c.file_filenames       = cookbook_settings[:file_filenames].values
          c.library_filenames    = cookbook_settings[:library_filenames].values
          c.resource_filenames   = cookbook_settings[:resource_filenames].values
          c.provider_filenames   = cookbook_settings[:provider_filenames].values
          c.root_filenames       = cookbook_settings[:root_filenames].values
          c.metadata_filenames   = metadata_filenames
          c.metadata             = metadata

          c.freeze_version if @frozen
        end
      end

      def cookbook_name
        # The `name` attribute is now required in metadata, so
        # inferred_cookbook_name generally should not be used. Per CHEF-2923,
{'fraction_non_alphanumeric': 0.07959504276488043, 'fraction_numerical': 0.0006982021295164951, 'mean_word_length': 2.3456934306569344, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7239464', 'n_tokens_mistral': 3327, 'n_tokens_neox': 3236, 'n_words': 669}