зеркало из https://github.com/github/ruby.git
* lib/tempfile.rb: refactoring.
* use warn instead of STDERR.print * remove @tmpname and use @tmpfile.path * introduce @unlinked flag * Remover takes only @tmpfile * mode will be modified just before file reopen git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50682 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
e214058956
Коммит
354c9747e4
|
@ -1,3 +1,12 @@
|
||||||
|
Sat May 30 10:26:09 2015 Masaki Matsushita <glass.saga@gmail.com>
|
||||||
|
|
||||||
|
* lib/tempfile.rb: refactoring.
|
||||||
|
* use warn instead of STDERR.print
|
||||||
|
* remove @tmpname and use @tmpfile.path
|
||||||
|
* introduce @unlinked flag
|
||||||
|
* Remover takes only @tmpfile
|
||||||
|
* mode will be modified just before file reopen
|
||||||
|
|
||||||
Sat May 30 09:02:51 2015 Eric Wong <e@80x24.org>
|
Sat May 30 09:02:51 2015 Eric Wong <e@80x24.org>
|
||||||
|
|
||||||
* include/ruby/intern.h (rb_generic_ivar_table): deprecate
|
* include/ruby/intern.h (rb_generic_ivar_table): deprecate
|
||||||
|
|
|
@ -123,41 +123,29 @@ class Tempfile < DelegateClass(File)
|
||||||
# If Tempfile.new cannot find a unique filename within a limited
|
# If Tempfile.new cannot find a unique filename within a limited
|
||||||
# number of tries, then it will raise an exception.
|
# number of tries, then it will raise an exception.
|
||||||
def initialize(basename="", tmpdir=nil, mode: 0, **options)
|
def initialize(basename="", tmpdir=nil, mode: 0, **options)
|
||||||
if block_given?
|
warn "Tempfile.new doesn't call the given block." if block_given?
|
||||||
warn "Tempfile.new doesn't call the given block."
|
|
||||||
end
|
|
||||||
@data = []
|
|
||||||
@clean_proc = Remover.new(@data)
|
|
||||||
ObjectSpace.define_finalizer(self, @clean_proc)
|
|
||||||
|
|
||||||
|
@mode = mode|File::RDWR|File::CREAT|File::EXCL
|
||||||
::Dir::Tmpname.create(basename, tmpdir, options) do |tmpname, n, opts|
|
::Dir::Tmpname.create(basename, tmpdir, options) do |tmpname, n, opts|
|
||||||
mode |= File::RDWR|File::CREAT|File::EXCL
|
|
||||||
opts[:perm] = 0600
|
opts[:perm] = 0600
|
||||||
@data[1] = @tmpfile = File.open(tmpname, mode, opts)
|
@tmpfile = File.open(tmpname, @mode, opts)
|
||||||
@data[0] = @tmpname = tmpname
|
@opts = opts.freeze
|
||||||
@mode = mode & ~(File::CREAT|File::EXCL)
|
|
||||||
opts.freeze
|
|
||||||
@opts = opts
|
|
||||||
end
|
end
|
||||||
|
ObjectSpace.define_finalizer(self, Remover.new(@tmpfile))
|
||||||
|
|
||||||
super(@tmpfile)
|
super(@tmpfile)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Opens or reopens the file with mode "r+".
|
# Opens or reopens the file with mode "r+".
|
||||||
def open
|
def open
|
||||||
@tmpfile.close if @tmpfile
|
_close
|
||||||
@tmpfile = File.open(@tmpname, @mode, @opts)
|
mode = @mode & ~(File::CREAT|File::EXCL)
|
||||||
@data[1] = @tmpfile
|
@tmpfile = File.open(@tmpfile.path, mode, @opts)
|
||||||
__setobj__(@tmpfile)
|
__setobj__(@tmpfile)
|
||||||
end
|
end
|
||||||
|
|
||||||
def _close # :nodoc:
|
def _close # :nodoc:
|
||||||
begin
|
@tmpfile.close unless @tmpfile.closed?
|
||||||
@tmpfile.close if @tmpfile
|
|
||||||
ensure
|
|
||||||
@tmpfile = nil
|
|
||||||
@data[1] = nil if @data
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
protected :_close
|
protected :_close
|
||||||
|
|
||||||
|
@ -168,18 +156,14 @@ class Tempfile < DelegateClass(File)
|
||||||
# If you don't explicitly unlink the temporary file, the removal
|
# If you don't explicitly unlink the temporary file, the removal
|
||||||
# will be delayed until the object is finalized.
|
# will be delayed until the object is finalized.
|
||||||
def close(unlink_now=false)
|
def close(unlink_now=false)
|
||||||
if unlink_now
|
_close
|
||||||
close!
|
unlink if unlink_now
|
||||||
else
|
|
||||||
_close
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Closes and unlinks (deletes) the file. Has the same effect as called
|
# Closes and unlinks (deletes) the file. Has the same effect as called
|
||||||
# <tt>close(true)</tt>.
|
# <tt>close(true)</tt>.
|
||||||
def close!
|
def close!
|
||||||
_close
|
close(true)
|
||||||
unlink
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Unlinks (deletes) the file from the filesystem. One should always unlink
|
# Unlinks (deletes) the file from the filesystem. One should always unlink
|
||||||
|
@ -216,37 +200,32 @@ class Tempfile < DelegateClass(File)
|
||||||
# # to do so again.
|
# # to do so again.
|
||||||
# end
|
# end
|
||||||
def unlink
|
def unlink
|
||||||
return unless @tmpname
|
return if @unlinked
|
||||||
begin
|
begin
|
||||||
File.unlink(@tmpname)
|
File.unlink(@tmpfile.path)
|
||||||
rescue Errno::ENOENT
|
rescue Errno::ENOENT
|
||||||
rescue Errno::EACCES
|
rescue Errno::EACCES
|
||||||
# may not be able to unlink on Windows; just ignore
|
# may not be able to unlink on Windows; just ignore
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
# remove tmpname from remover
|
|
||||||
@data[0] = @data[1] = nil
|
|
||||||
@tmpname = nil
|
|
||||||
ObjectSpace.undefine_finalizer(self)
|
ObjectSpace.undefine_finalizer(self)
|
||||||
|
@unlinked = true
|
||||||
end
|
end
|
||||||
alias delete unlink
|
alias delete unlink
|
||||||
|
|
||||||
# Returns the full path name of the temporary file.
|
# Returns the full path name of the temporary file.
|
||||||
# This will be nil if #unlink has been called.
|
# This will be nil if #unlink has been called.
|
||||||
def path
|
def path
|
||||||
@tmpname
|
@unlinked ? nil : @tmpfile.path
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the size of the temporary file. As a side effect, the IO
|
# Returns the size of the temporary file. As a side effect, the IO
|
||||||
# buffer is flushed before determining the size.
|
# buffer is flushed before determining the size.
|
||||||
def size
|
def size
|
||||||
if @tmpfile
|
if !@tmpfile.closed?
|
||||||
@tmpfile.flush
|
@tmpfile.size # File#size calls rb_io_flush_raw()
|
||||||
@tmpfile.stat.size
|
|
||||||
elsif @tmpname
|
|
||||||
File.size(@tmpname)
|
|
||||||
else
|
else
|
||||||
0
|
File.size?(@tmpfile.path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
alias length size
|
alias length size
|
||||||
|
@ -261,28 +240,23 @@ class Tempfile < DelegateClass(File)
|
||||||
end
|
end
|
||||||
|
|
||||||
class Remover
|
class Remover
|
||||||
def initialize(data)
|
def initialize(tmpfile)
|
||||||
@pid = $$
|
@pid = Process.pid
|
||||||
@data = data
|
@tmpfile = tmpfile
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(*args)
|
def call(*args)
|
||||||
return if @pid != $$
|
return if @pid != Process.pid
|
||||||
|
|
||||||
path, tmpfile = @data
|
warn "removing #{@tmpfile.path}..." if $DEBUG
|
||||||
|
|
||||||
STDERR.print "removing ", path, "..." if $DEBUG
|
@tmpfile.close if @tmpfile.closed?
|
||||||
|
begin
|
||||||
tmpfile.close if tmpfile
|
File.unlink(@tmpfile.path)
|
||||||
|
rescue Errno::ENOENT
|
||||||
if path
|
|
||||||
begin
|
|
||||||
File.unlink(path)
|
|
||||||
rescue Errno::ENOENT
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
STDERR.print "done\n" if $DEBUG
|
warn "done" if $DEBUG
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче