Merged updates from trunk into stable branch
[feedcatcher.git] / vendor / rails / activesupport / lib / active_support / core_ext / file / atomic.rb
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