diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index 92b51f2256..d371229512 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -96,13 +96,35 @@ class Pathname # NOTE always overwrites def atomic_write content - require 'tempfile' - tf = Tempfile.new(self.basename.to_s) + require "tempfile" + tf = Tempfile.new(basename.to_s) tf.write(content) tf.close - FileUtils.mv tf.path, self.to_s + + begin + old_stat = stat + rescue Errno::ENOENT + old_stat = default_stat + end + + FileUtils.mv tf.path, self + + begin + chown(old_stat.uid, old_stat.gid) + chmod(old_stat.mode) + rescue Errno::EPERM + end end + def default_stat + sentinel = parent.join(".brew.#{Process.pid}.#{rand(Time.now.to_i)}") + sentinel.open("w") { } + sentinel.stat + ensure + sentinel.unlink + end + private :default_stat + def cp dst if file? FileUtils.cp to_s, dst diff --git a/Library/Homebrew/test/test_pathname.rb b/Library/Homebrew/test/test_pathname.rb index 03e4df54ca..3bfda1a17d 100644 --- a/Library/Homebrew/test/test_pathname.rb +++ b/Library/Homebrew/test/test_pathname.rb @@ -58,6 +58,19 @@ class PathnameExtensionTests < Test::Unit::TestCase assert_equal 'CONTENT', File.read(@file) end + def test_atomic_write_preserves_permissions + File.open(@file, "w", 0100777) { } + @file.atomic_write("CONTENT") + assert_equal 0100777 & ~File.umask, @file.stat.mode + end + + def test_atomic_write_preserves_default_permissions + @file.atomic_write("CONTENT") + sentinel = @file.parent.join("sentinel") + touch sentinel + assert_equal sentinel.stat.mode, @file.stat.mode + end + def test_cp touch @file mkdir_p @dir