# module Chef::Deprecation::Provider::File

## Deprecation::Provider::File¶ ↑

This module contains the deprecated functions of Chef::Provider::File. These functions are refactored to different components. They are frozen and will be removed in Chef 12.

### Public Instance Methods

backup(file=nil) click to toggle source

    # File lib/chef/deprecation/provider/file.rb, line 165
    def backup(file=nil)
      file ||= @new_resource.path
      if @new_resource.backup != false && @new_resource.backup > 0 && ::File.exist?(file)
        time = Time.now
        savetime = time.strftime("%Y%m%d%H%M%S")
        backup_filename = "#{@new_resource.path}.chef-#{savetime}"
        backup_filename = backup_filename.sub(/^([A-Za-z]:)/, "") #strip drive letter on Windows
        # if :file_backup_path is nil, we fallback to the old behavior of
        # keeping the backup in the same directory. We also need to to_s it
        # so we don't get a type error around implicit to_str conversions.
        prefix = Chef::Config[:file_backup_path].to_s
        backup_path = ::File.join(prefix, backup_filename)
        FileUtils.mkdir_p(::File.dirname(backup_path)) if Chef::Config[:file_backup_path]
        FileUtils.cp(file, backup_path, :preserve => true)
        Chef::Log.info("#{@new_resource} backed up to #{backup_path}")

        # Clean up after the number of backups
        slice_number = @new_resource.backup
        backup_files = Dir[::File.join(prefix, ".#{@new_resource.path}.chef-*")].sort { |a,b| b <=> a }
        if backup_files.length >= @new_resource.backup
          remainder = backup_files.slice(slice_number..-1)
          remainder.each do |backup_to_delete|
            FileUtils.rm(backup_to_delete)
            Chef::Log.info("#{@new_resource} removed backup at #{backup_to_delete}")
          end
        end
      end
    end

compare_content() click to toggle source

    # File lib/chef/deprecation/provider/file.rb, line 110
    def compare_content
      checksum(@current_resource.path) == new_resource_content_checksum
    end

deploy_tempfile() { |tempfile| ... } click to toggle source

    # File lib/chef/deprecation/provider/file.rb, line 153
    def deploy_tempfile
      Tempfile.open(::File.basename(@new_resource.name)) do |tempfile|
        yield tempfile

        temp_res = Chef::Resource::CookbookFile.new(@new_resource.name)
        temp_res.path(tempfile.path)
        ac = Chef::FileAccessControl.new(temp_res, @new_resource, self)
        ac.set_all!
        FileUtils.mv(tempfile.path, @new_resource.path)
      end
    end

diff_current(temp_path) click to toggle source

    # File lib/chef/deprecation/provider/file.rb, line 50
    def diff_current(temp_path)
      suppress_resource_reporting = false

      return [ "(diff output suppressed by config)" ] if Chef::Config[:diff_disabled]
      return [ "(no temp file with new content, diff output suppressed)" ] unless ::File.exists?(temp_path)  # should never happen?

      # solaris does not support diff -N, so create tempfile to diff against if we are creating a new file
      target_path = if ::File.exists?(@current_resource.path)
                      @current_resource.path
                    else
                      suppress_resource_reporting = true  # suppress big diffs going to resource reporting service
                      tempfile = Tempfile.new('chef-tempfile')
                      tempfile.path
                    end

      diff_filesize_threshold = Chef::Config[:diff_filesize_threshold]
      diff_output_threshold = Chef::Config[:diff_output_threshold]

      if ::File.size(target_path) > diff_filesize_threshold || ::File.size(temp_path) > diff_filesize_threshold
        return [ "(file sizes exceed #{diff_filesize_threshold} bytes, diff output suppressed)" ]
      end

      # MacOSX(BSD?) diff will *sometimes* happily spit out nasty binary diffs
      return [ "(current file is binary, diff output suppressed)"] if is_binary?(target_path)
      return [ "(new content is binary, diff output suppressed)"] if is_binary?(temp_path)

      begin
        # -u: Unified diff format
        result = shell_out("diff -u #{target_path} #{temp_path}" )
      rescue Exception => e
        # Should *not* receive this, but in some circumstances it seems that
        # an exception can be thrown even using shell_out instead of shell_out!
        return [ "Could not determine diff. Error: #{e.message}" ]
      end

      # diff will set a non-zero return code even when there's
      # valid stdout results, if it encounters something unexpected
      # So as long as we have output, we'll show it.
      if not result.stdout.empty?
        if result.stdout.length > diff_output_threshold
          [ "(long diff of over #{diff_output_threshold} characters, diff output suppressed)" ]
        else
          val = result.stdout.split("\n")
          val.delete("\\ No newline at end of file")
          @new_resource.diff(val.join("\\n")) unless suppress_resource_reporting
          val
        end
      elsif not result.stderr.empty?
        [ "Could not determine diff. Error: #{result.stderr}" ]
      else
        [ "(no diff)" ]
      end
    end

diff_current_from_content(new_content) click to toggle source

    # File lib/chef/deprecation/provider/file.rb, line 31
    def diff_current_from_content(new_content)
      result = nil
      Tempfile.open("chef-diff") do |file|
        file.write new_content
        file.close
        result = diff_current file.path
      end
      result
    end

is_binary?(path) click to toggle source

    # File lib/chef/deprecation/provider/file.rb, line 41
    def is_binary?(path)
      ::File.open(path) do |file|

        buff = file.read(Chef::Config[:diff_filesize_threshold])
        buff = "" if buff.nil?
        return buff !~ /^[\r[:print:]]*$/
      end
    end

set_all_access_controls() click to toggle source

    # File lib/chef/deprecation/provider/file.rb, line 143
    def set_all_access_controls
      if access_controls.requires_changes?
        converge_by(access_controls.describe_changes) do
          access_controls.set_all
          #Update file state with new access values
          update_new_file_state
        end
      end
    end

set_content() click to toggle source

    # File lib/chef/deprecation/provider/file.rb, line 114
    def set_content
      unless compare_content
        description = []
        description << "update content in file #{@new_resource.path} from #{short_cksum(@current_resource.checksum)} to #{short_cksum(new_resource_content_checksum)}"
        description << diff_current_from_content(@new_resource.content)
        converge_by(description) do
          backup @new_resource.path if ::File.exists?(@new_resource.path)
          ::File.open(@new_resource.path, "w") {|f| f.write @new_resource.content }
          Chef::Log.info("#{@new_resource} contents updated")
        end
      end
    end

setup_acl() click to toggle source

    # File lib/chef/deprecation/provider/file.rb, line 104
    def setup_acl
      return if Chef::Platform.windows?
      acl_scanner = ScanAccessControl.new(@new_resource, @current_resource)
      acl_scanner.set_all!
    end

update_new_file_state(path=@new_resource.path) click to toggle source

    # File lib/chef/deprecation/provider/file.rb, line 127
    def update_new_file_state(path=@new_resource.path)
      if !::File.directory?(path)
        @new_resource.checksum(checksum(path))
      end

      if Chef::Platform.windows?
        # TODO: To work around CHEF-3554, add support for Windows
        # equivalent, or implicit resource reporting won't work for
        # Windows.
        return
      end

      acl_scanner = ScanAccessControl.new(@new_resource, @new_resource)
      acl_scanner.set_all!
    end