# class Chef::ChefFS::FileSystem::CookbookDir

### Constants

COOKBOOK_SEGMENT_INFO
VALID_VERSIONED_COOKBOOK_NAME

  See Erchef code github.com/opscode/chef_objects/blob/968a63344d38fd507f6ace05f73d53e9cd7fb043/src/chef_regex.erl#L94

### Attributes

cookbook_name[R]
version[R]

### Public Class Methods

new(name, parent, options = {}) click to toggle source
Calls superclass method Chef::ChefFS::FileSystem::BaseFSDir.new

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 30
    def initialize(name, parent, options = {})
      super(name, parent)
      @exists = options[:exists]
      # If the name is apache2-1.0.0 and versioned_cookbooks is on, we know
      # the actual cookbook_name and version.
      if Chef::Config[:versioned_cookbooks]
        if name =~ VALID_VERSIONED_COOKBOOK_NAME
          @cookbook_name = $1
          @version = $2
        else
          @exists = false
        end
      else
        @cookbook_name = name
        @version = root.cookbook_version # nil unless --cookbook-version specified in download/diff
      end
    end

### Public Instance Methods

add_child(child) click to toggle source

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 66
    def add_child(child)
      @children << child
    end

api_path() click to toggle source

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 70
    def api_path
      "#{parent.api_path}/#{cookbook_name}/#{version || "_latest"}"
    end

can_have_child?(name, is_dir) click to toggle source

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 86
    def can_have_child?(name, is_dir)
      # A cookbook's root may not have directories unless they are segment directories
      return name != 'root_files' && COOKBOOK_SEGMENT_INFO.keys.include?(name.to_sym) if is_dir
      return true
    end

chef_object() click to toggle source

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 175
    def chef_object
      # We cheat and cache here, because it seems like a good idea to keep
      # the cookbook view consistent with the directory structure.
      return @chef_object if @chef_object

      # The negative (not found) response is cached
      if @could_not_get_chef_object
        raise Chef::ChefFS::FileSystem::NotFoundError.new(self, @could_not_get_chef_object)
      end

      begin
        # We want to fail fast, for now, because of the 500 issue :/
        # This will make things worse for parallelism, a little, because
        # Chef::Config is global and this could affect other requests while
        # this request is going on.  (We're not parallel yet, but we will be.)
        # Chef bug http://tickets.opscode.com/browse/CHEF-3066
        old_retry_count = Chef::Config[:http_retry_count]
        begin
          Chef::Config[:http_retry_count] = 0
          @chef_object ||= Chef::CookbookVersion.json_create(root.get_json(api_path))
        ensure
          Chef::Config[:http_retry_count] = old_retry_count
        end

      rescue Timeout::Error => e
        raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e), "Timeout reading: #{e}"

      rescue Net::HTTPServerException => e
        if e.response.code == "404"
          @could_not_get_chef_object = e
          raise Chef::ChefFS::FileSystem::NotFoundError.new(self, @could_not_get_chef_object)
        else
          raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e), "HTTP error reading: #{e}"
        end

      # Chef bug http://tickets.opscode.com/browse/CHEF-3066 ... instead of 404 we get 500 right now.
      # Remove this when that bug is fixed.
      rescue Net::HTTPFatalError => e
        if e.response.code == "500"
          @could_not_get_chef_object = e
          raise Chef::ChefFS::FileSystem::NotFoundError.new(self, @could_not_get_chef_object)
        else
          raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e), "HTTP error reading: #{e}"
        end
      end
    end

child(name) click to toggle source

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 74
    def child(name)
      # Since we're ignoring the rules and doing a network request here,
      # we need to make sure we don't rethrow the exception.  (child(name)
      # is not supposed to fail.)
      begin
        result = children.select { |child| child.name == name }.first
        return result if result
      rescue Chef::ChefFS::FileSystem::NotFoundError
      end
      return NonexistentFSObject.new(name, self)
    end

children() click to toggle source

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 92
    def children
      if @children.nil?
        @children = []
        manifest = chef_object.manifest
        COOKBOOK_SEGMENT_INFO.each do |segment, segment_info|
          next unless manifest.has_key?(segment)

          # Go through each file in the manifest for the segment, and
          # add cookbook subdirs and files for it.
          manifest[segment].each do |segment_file|
            parts = segment_file[:path].split('/')
            # Get or create the path to the file
            container = self
            parts[0,parts.length-1].each do |part|
              old_container = container
              container = old_container.children.select { |child| part == child.name }.first
              if !container
                container = CookbookSubdir.new(part, old_container, segment_info[:ruby_only], segment_info[:recursive])
                old_container.add_child(container)
              end
            end
            # Create the file itself
            container.add_child(CookbookFile.new(parts[parts.length-1], container, segment_file))
          end
        end
        @children = @children.sort_by { |c| c.name }
      end
      @children
    end

compare_to(other) click to toggle source

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 154
    def compare_to(other)
      if !other.dir?
        return [ !exists?, nil, nil ]
      end
      are_same = true
      Chef::ChefFS::CommandLine::diff_entries(self, other, nil, :name_only).each do |type, old_entry, new_entry|
        if [ :directory_to_file, :file_to_directory, :deleted, :added, :modified ].include?(type)
          are_same = false
        end
      end
      [ are_same, nil, nil ]
    end

copy_from(other, options = {}) click to toggle source

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 167
    def copy_from(other, options = {})
      parent.upload_cookbook_from(other, options)
    end

delete(recurse) click to toggle source

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 126
    def delete(recurse)
      if recurse
        begin
          rest.delete(api_path)
        rescue Timeout::Error => e
          raise Chef::ChefFS::FileSystem::OperationFailedError.new(:delete, self, e), "Timeout deleting: #{e}"
        rescue Net::HTTPServerException
          if $!.response.code == "404"
            raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
          else
            raise Chef::ChefFS::FileSystem::OperationFailedError.new(:delete, self, e), "HTTP error deleting: #{e}"
          end
        end
      else
        raise NotFoundError.new(self) if !exists?
        raise MustDeleteRecursivelyError.new(self), "#{path_for_printing} must be deleted recursively"
      end
    end

dir?() click to toggle source

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 122
    def dir?
      exists?
    end

exists?() click to toggle source

In versioned cookbook mode, actually check if the version exists Probably want to cache this.

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 147
    def exists?
      if @exists.nil?
        @exists = parent.children.any? { |child| child.name == name }
      end
      @exists
    end

rest() click to toggle source

    # File lib/chef/chef_fs/file_system/cookbook_dir.rb, line 171
    def rest
      parent.rest
    end