~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/activesupport/lib/active_support/core_ext/file/atomic.rb

  • Committer: Michael Forrest
  • Date: 2010-10-15 16:28:50 UTC
  • Revision ID: michael.forrest@canonical.com-20101015162850-tj2vchanv0kr0dun
refrozeĀ gems

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
21
          temp_file = Tempfile.new(basename(file_name), temp_dir)
 
22
          yield temp_file
 
23
          temp_file.close
 
24
 
 
25
          begin
 
26
            # Get original file permissions
 
27
            old_stat = stat(file_name)
 
28
          rescue Errno::ENOENT
 
29
            # No old permissions, write a temp file to determine the defaults
 
30
            check_name = join(dirname(file_name), ".permissions_check.#{Thread.current.object_id}.#{Process.pid}.#{rand(1000000)}")
 
31
            open(check_name, "w") { }
 
32
            old_stat = stat(check_name)
 
33
            unlink(check_name)
 
34
          end
 
35
 
 
36
          # Overwrite original file with temp file
 
37
          rename(temp_file.path, file_name)
 
38
 
 
39
          # Set correct permissions on new file
 
40
          chown(old_stat.uid, old_stat.gid, file_name)
 
41
          chmod(old_stat.mode, file_name)
 
42
        end
 
43
      end
 
44
    end
 
45
  end
 
46
end