File: active_support/core_ext/file/atomic.rb

Overview
Module Structure
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: ActiveSupport#1
  module: CoreExtensions#2
  module: File#3
  module: Atomic#4
has properties
method: atomic_write / 2 #18

Code

   1  module ActiveSupport #:nodoc:
   2    module CoreExtensions #:nodoc:
   3      module File #:nodoc:
   4        module Atomic
   5          # Write to a file atomically.  Useful for situations where you don't
   6          # want other processes or threads to see half-written files.
   7          #
   8          #   File.atomic_write("important.file") do |file|
   9          #     file.write("hello")
  10          #   end
  11          #
  12          # If your temp directory is not on the same filesystem as the file you're 
  13          # trying to write, you can provide a different temporary directory.
  14          # 
  15          #   File.atomic_write("/data/something.important", "/data/tmp") do |f|
  16          #     file.write("hello")
  17          #   end
  18          def atomic_write(file_name, temp_dir = Dir.tmpdir)
  19            require 'tempfile' unless defined?(Tempfile)
  20            require 'fileutils' unless defined?(FileUtils)
  21 
  22            temp_file = Tempfile.new(basename(file_name), temp_dir)
  23            yield temp_file
  24            temp_file.close
  25 
  26            begin
  27              # Get original file permissions
  28              old_stat = stat(file_name)
  29            rescue Errno::ENOENT
  30              # No old permissions, write a temp file to determine the defaults
  31              check_name = join(dirname(file_name), ".permissions_check.#{Thread.current.object_id}.#{Process.pid}.#{rand(1000000)}")
  32              open(check_name, "w") { }
  33              old_stat = stat(check_name)
  34              unlink(check_name)
  35            end
  36 
  37            # Overwrite original file with temp file
  38            FileUtils.mv(temp_file.path, file_name)
  39 
  40            # Set correct permissions on new file
  41            chown(old_stat.uid, old_stat.gid, file_name)
  42            chmod(old_stat.mode, file_name)
  43          end
  44        end
  45      end
  46    end
  47  end