зеркало из https://github.com/github/ruby.git
* lib/tempfile.rb: add documents from Hongli Lai's fork.
cf [ruby-core:25131]. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24672 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
232978b031
Коммит
addd2cb06e
|
@ -1,3 +1,8 @@
|
|||
Wed Aug 26 21:49:23 2009 NARUSE, Yui <naruse@ruby-lang.org>
|
||||
|
||||
* lib/tempfile.rb: add documents from Hongli Lai's fork.
|
||||
cf [ruby-core:25131].
|
||||
|
||||
Wed Aug 26 19:51:13 2009 NARUSE, Yui <naruse@ruby-lang.org>
|
||||
|
||||
* tool/mkconfig.rb (program_transform_name): fix for multiple trans
|
||||
|
|
|
@ -8,27 +8,129 @@ require 'delegate'
|
|||
require 'tmpdir'
|
||||
require 'thread'
|
||||
|
||||
# A class for managing temporary files. This library is written to be
|
||||
# thread safe.
|
||||
# A utility class for managing temporary files. When you create a Tempfile
|
||||
# object, it will create a temporary file with a unique filename. A Tempfile
|
||||
# objects behaves just like a File object, and you can perform all the usual
|
||||
# file operations on it: reading data, writing data, changing its permissions,
|
||||
# etc. So although this class does not explicitly document all instance methods
|
||||
# supported by File, you can in fact call any File instance method on a
|
||||
# Tempfile object.
|
||||
#
|
||||
# == Synopsis
|
||||
#
|
||||
# require 'tempfile'
|
||||
#
|
||||
# file = Tempfile.new('foo')
|
||||
# file.path # => A unique filename in the OS's temp directory,
|
||||
# # e.g.: "/tmp/foo.24722.0"
|
||||
# # This filename contains 'foo' in its basename.
|
||||
# file.write("hello world")
|
||||
# file.rewind
|
||||
# file.read # => "hello world"
|
||||
# file.close
|
||||
# file.unlink # deletes the temp file
|
||||
#
|
||||
# == Good practices
|
||||
#
|
||||
# === Explicit close
|
||||
#
|
||||
# When a Tempfile object is garbage collected, or when the Ruby interpreter
|
||||
# exits, its associated temporary file is automatically deleted. This means
|
||||
# that's it's unnecessary to explicitly delete a Tempfile after use, though
|
||||
# it's good practice to do so: not explicitly deleting unused Tempfiles can
|
||||
# potentially leave behind large amounts of tempfiles on the filesystem
|
||||
# until they're garbage collected. The existance of these temp files can make
|
||||
# it harder to determine a new Tempfile filename.
|
||||
#
|
||||
# Therefore, one should always call #unlink or close in an ensure block, like
|
||||
# this:
|
||||
#
|
||||
# file = Tempfile.new('foo)
|
||||
# begin
|
||||
# ...do something with file...
|
||||
# ensure
|
||||
# file.close
|
||||
# file.unlink # deletes the temp file
|
||||
# end
|
||||
#
|
||||
# === Unlink after creation
|
||||
#
|
||||
# On POSIX systems, it's possible to unlink a file right after creating it,
|
||||
# and before closing it. This removes the filesystem entry without closing
|
||||
# the file handle, so it ensures that only the processes that already had
|
||||
# the file handle open can access the file's contents. It's strongly
|
||||
# recommended that you do this if you do not want any other processes to
|
||||
# be able to read from or write to the Tempfile, and you do not need to
|
||||
# know the Tempfile's filename either.
|
||||
#
|
||||
# For example, a practical use case for unlink-after-creation would be this:
|
||||
# you need a large byte buffer that's too large to comfortably fit in RAM,
|
||||
# e.g. when you're writing a web server and you want to buffer the client's
|
||||
# file upload data.
|
||||
#
|
||||
# Please refer to #unlink for more information and a code example.
|
||||
#
|
||||
# == Minor notes
|
||||
#
|
||||
# Tempfile's filename picking method is both thread-safe and inter-process-safe:
|
||||
# it guarantees that no other threads or processes will pick the same filename.
|
||||
#
|
||||
# Tempfile itself however may not be entirely thread-safe. If you access the
|
||||
# same Tempfile object from multiple threads then you should protect it with a
|
||||
# mutex.
|
||||
class Tempfile < DelegateClass(File)
|
||||
MAX_TRY = 10 # :nodoc:
|
||||
@@cleanlist = []
|
||||
@@lock = Mutex.new
|
||||
|
||||
# Creates a temporary file of mode 0600 in the temporary directory,
|
||||
# opens it with mode "w+", and returns a Tempfile object which
|
||||
# represents the created temporary file. A Tempfile object can be
|
||||
# treated just like a normal File object.
|
||||
# call-seq:
|
||||
# new(basename, [tmpdir = Dir.tmpdir], [options])
|
||||
#
|
||||
# The basename parameter is used to determine the name of a
|
||||
# temporary file. If an Array is given, the first element is used
|
||||
# as prefix string and the second as suffix string, respectively.
|
||||
# Otherwise it is treated as prefix string.
|
||||
# Creates a temporary file with permissions 0600 (= only readable and
|
||||
# writable by the owner) and opens it with mode "w+".
|
||||
#
|
||||
# If tmpdir is omitted, the temporary directory is determined by
|
||||
# Dir::tmpdir provided by 'tmpdir.rb'.
|
||||
# When $SAFE > 0 and the given tmpdir is tainted, it uses
|
||||
# /tmp. (Note that ENV values are tainted by default)
|
||||
# The +basename+ parameter is used to determine the name of the
|
||||
# temporary file. You can either pass a String or an Array with
|
||||
# 2 String elements. In the former form, the temporary file's base
|
||||
# name will begin with the given string. In the latter form,
|
||||
# the temporary file's base name will begin with the array's first
|
||||
# element, and end with the second element. For example:
|
||||
#
|
||||
# file = Tempfile.new('hello')
|
||||
# file.path # => something like: "/tmp/foo2843-8392-92849382--0"
|
||||
#
|
||||
# # Use the Array form to enforce an extension in the filename:
|
||||
# file = Tempfile.new(['hello', '.jpg'])
|
||||
# file.path # => something like: "/tmp/foo2843-8392-92849382--0.jpg"
|
||||
#
|
||||
# The temporary file will be placed in the directory as specified
|
||||
# by the +tmpdir+ parameter. By default, this is +Dir.tmpdir+.
|
||||
# When $SAFE > 0 and the given +tmpdir+ is tainted, it uses
|
||||
# '/tmp' as the temporary directory. Please note that ENV values
|
||||
# are tainted by default, and +Dir.tmpdir+'s return value might
|
||||
# come from environment variables (e.g. <tt>$TMPDIR</tt>).
|
||||
#
|
||||
# file = Tempfile.new('hello', '/home/aisaka')
|
||||
# file.path # => something like: "/home/aisaka/foo2843-8392-92849382--0"
|
||||
#
|
||||
# You can also pass an options hash. Under the hood, Tempfile creates
|
||||
# the temporary file using +File.open+. These options will be passed to
|
||||
# +File.open+. This is mostly useful for specifying encoding
|
||||
# options, e.g.:
|
||||
#
|
||||
# Tempfile.new('hello', '/home/aisaka', :encoding => 'ascii-8bit')
|
||||
#
|
||||
# # You can also omit the 'tmpdir' parameter:
|
||||
# Tempfile.new('hello', :encoding => 'ascii-8bit')
|
||||
#
|
||||
# === Exceptions
|
||||
#
|
||||
# Under rare circumstances, this constructor can raise an instance of
|
||||
# Tempfile::CreationError. This could happen if a large number
|
||||
# of threads or processes are simultaneously trying to create temp files
|
||||
# and stepping on each others' toes. If Tempfile.new cannot find
|
||||
# a unique filename within a limited number of tries, then it will raise
|
||||
# this exception.
|
||||
def initialize(basename, *rest)
|
||||
# I wish keyword argument settled soon.
|
||||
if opts = Hash.try_convert(rest[-1])
|
||||
|
@ -108,8 +210,9 @@ class Tempfile < DelegateClass(File)
|
|||
end
|
||||
protected :_close
|
||||
|
||||
#Closes the file. If the optional flag is true, unlinks the file
|
||||
# after closing.
|
||||
# Closes the file. If +unlink_now+ is true, then the file will be unlinked
|
||||
# (deleted) after closing. Of course, you can choose to later call #unlink
|
||||
# if you do not unlink it now.
|
||||
#
|
||||
# If you don't explicitly unlink the temporary file, the removal
|
||||
# will be delayed until the object is finalized.
|
||||
|
@ -121,18 +224,47 @@ class Tempfile < DelegateClass(File)
|
|||
end
|
||||
end
|
||||
|
||||
# Closes and unlinks the file.
|
||||
# Has the same effect as called <tt>close(true)</tt>.
|
||||
# Closes and unlinks (deletes) the file. Has the same effect as called
|
||||
# <tt>close(true)</tt>.
|
||||
def close!
|
||||
_close
|
||||
unlink
|
||||
ObjectSpace.undefine_finalizer(self)
|
||||
end
|
||||
|
||||
# Unlinks the file. On UNIX-like systems, it is often a good idea
|
||||
# to unlink a temporary file immediately after creating and opening
|
||||
# it, because it leaves other programs zero chance to access the
|
||||
# file.
|
||||
# Unlinks (deletes) the file from the filesystem. One should always unlink
|
||||
# the file after using it, as is explained in the "Explicit close" good
|
||||
# practice section in the Tempfile overview:
|
||||
#
|
||||
# file = Tempfile.new('foo)
|
||||
# begin
|
||||
# ...do something with file...
|
||||
# ensure
|
||||
# file.close
|
||||
# file.unlink # deletes the temp file
|
||||
# end
|
||||
#
|
||||
# === Unlink-before-close
|
||||
#
|
||||
# On POSIX systems it's possible to unlink a file before closing it. This
|
||||
# practice is explained in detail in the Tempfile overview (section
|
||||
# "Unlink after creation"); please refer there for more information.
|
||||
#
|
||||
# However, unlink-before-close may not be supported on non-POSIX operating
|
||||
# systems. Microsoft Windows is the most notable case: unlinking a non-closed
|
||||
# file will result in an error, which this method will silently ignore. If
|
||||
# you want to practice unlink-before-close whenever possible, then you should
|
||||
# write code like this:
|
||||
#
|
||||
# file = Tempfile.new('foo')
|
||||
# file.unlink # On Windows this silently fails.
|
||||
# begin
|
||||
# ... do something with file ...
|
||||
# ensure
|
||||
# file.close! # Closes the file handle. If the file wasn't unlinked
|
||||
# # because #unlink failed, then this method will attempt
|
||||
# # to do so again.
|
||||
# end
|
||||
def unlink
|
||||
# keep this order for thread safeness
|
||||
return unless @tmpname
|
||||
|
@ -190,11 +322,28 @@ class Tempfile < DelegateClass(File)
|
|||
}
|
||||
end
|
||||
|
||||
# If no block is given, this is a synonym for new().
|
||||
# Creates a new Tempfile.
|
||||
#
|
||||
# If a block is given, it will be passed tempfile as an argument,
|
||||
# and the tempfile will automatically be closed when the block
|
||||
# terminates. The call returns the value of the block.
|
||||
# If no block is given, this is a synonym for Tempfile.new.
|
||||
#
|
||||
# If a block is given, then a Tempfile object will be constructed,
|
||||
# and the block is run with said object as argument. The Tempfile
|
||||
# oject will be automatically closed after the block terminates.
|
||||
# The call returns the value of the block.
|
||||
#
|
||||
# In any case, all arguments (+*args+) will be passed to Tempfile.new.
|
||||
#
|
||||
# Tempfile.open('foo', '/home/temp') do |f|
|
||||
# ... do something with f ...
|
||||
# end
|
||||
#
|
||||
# # Equivalent:
|
||||
# f = Tempfile.open('foo', '/home/temp')
|
||||
# begin
|
||||
# ... do something with f ...
|
||||
# ensure
|
||||
# f.close
|
||||
# end
|
||||
def open(*args)
|
||||
tempfile = new(*args)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче