tempfile 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.document +3 -0
- data/BSDL +22 -0
- data/COPYING +56 -0
- data/README.md +4 -0
- data/lib/tempfile.rb +227 -52
- metadata +9 -14
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/test.yml +0 -28
- data/.gitignore +0 -8
- data/Gemfile +0 -7
- data/Gemfile.lock +0 -23
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/tempfile.gemspec +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ae21b4105593d2be82c1def49b7c7b433bcf5836b2341889c11bee6aad4ed80
|
4
|
+
data.tar.gz: 4e457b305ce8076c7abfe64f5d95db965a6192292467874e1fdd7b280d8ee4c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc03ae1521c4f7fbecb322604e61fe33ce3177b965c6804a33b73fc525b38a656c2ed52d91b06018178874d0c63ddc67507da4390f1c38f7113ee802fb236a52
|
7
|
+
data.tar.gz: bec509610ce14c88a314c0d2a57eec33ebcc11f7a831da2181440929f7a0cea0f31c6af53f72259ff36e83f7045721777c80a61018f9c6d18bf1cfe96317af4c
|
data/.document
ADDED
data/BSDL
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
13
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
14
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
15
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
16
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
17
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
18
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
19
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
20
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
21
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
22
|
+
SUCH DAMAGE.
|
data/COPYING
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
|
2
|
+
You can redistribute it and/or modify it under either the terms of the
|
3
|
+
2-clause BSDL (see the file BSDL), or the conditions below:
|
4
|
+
|
5
|
+
1. You may make and give away verbatim copies of the source form of the
|
6
|
+
software without restriction, provided that you duplicate all of the
|
7
|
+
original copyright notices and associated disclaimers.
|
8
|
+
|
9
|
+
2. You may modify your copy of the software in any way, provided that
|
10
|
+
you do at least ONE of the following:
|
11
|
+
|
12
|
+
a. place your modifications in the Public Domain or otherwise
|
13
|
+
make them Freely Available, such as by posting said
|
14
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
15
|
+
the author to include your modifications in the software.
|
16
|
+
|
17
|
+
b. use the modified software only within your corporation or
|
18
|
+
organization.
|
19
|
+
|
20
|
+
c. give non-standard binaries non-standard names, with
|
21
|
+
instructions on where to get the original software distribution.
|
22
|
+
|
23
|
+
d. make other distribution arrangements with the author.
|
24
|
+
|
25
|
+
3. You may distribute the software in object code or binary form,
|
26
|
+
provided that you do at least ONE of the following:
|
27
|
+
|
28
|
+
a. distribute the binaries and library files of the software,
|
29
|
+
together with instructions (in the manual page or equivalent)
|
30
|
+
on where to get the original distribution.
|
31
|
+
|
32
|
+
b. accompany the distribution with the machine-readable source of
|
33
|
+
the software.
|
34
|
+
|
35
|
+
c. give non-standard binaries non-standard names, with
|
36
|
+
instructions on where to get the original software distribution.
|
37
|
+
|
38
|
+
d. make other distribution arrangements with the author.
|
39
|
+
|
40
|
+
4. You may modify and include the part of the software into any other
|
41
|
+
software (possibly commercial). But some files in the distribution
|
42
|
+
are not written by the author, so that they are not under these terms.
|
43
|
+
|
44
|
+
For the list of those files and their copying conditions, see the
|
45
|
+
file LEGAL.
|
46
|
+
|
47
|
+
5. The scripts and library files supplied as input to or produced as
|
48
|
+
output from the software do not automatically fall under the
|
49
|
+
copyright of the software, but belong to whomever generated them,
|
50
|
+
and may be sold commercially, and may be aggregated with this
|
51
|
+
software.
|
52
|
+
|
53
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
54
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
55
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
56
|
+
PURPOSE.
|
data/README.md
CHANGED
@@ -40,6 +40,10 @@ file.close
|
|
40
40
|
file.unlink # deletes the temp file
|
41
41
|
```
|
42
42
|
|
43
|
+
## Documentation
|
44
|
+
|
45
|
+
[RDoc](https://docs.ruby-lang.org/en/master/Tempfile.html)
|
46
|
+
|
43
47
|
## Development
|
44
48
|
|
45
49
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/tempfile.rb
CHANGED
@@ -8,18 +8,61 @@
|
|
8
8
|
require 'delegate'
|
9
9
|
require 'tmpdir'
|
10
10
|
|
11
|
-
# A utility class for managing temporary files.
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
11
|
+
# A utility class for managing temporary files.
|
12
|
+
#
|
13
|
+
# There are two kind of methods of creating a temporary file:
|
14
|
+
#
|
15
|
+
# - Tempfile.create (recommended)
|
16
|
+
# - Tempfile.new and Tempfile.open (mostly for backward compatibility, not recommended)
|
17
|
+
#
|
18
|
+
# Tempfile.create creates a usual \File object.
|
19
|
+
# The timing of file deletion is predictable.
|
20
|
+
# Also, it supports open-and-unlink technique which
|
21
|
+
# removes the temporary file immediately after creation.
|
22
|
+
#
|
23
|
+
# Tempfile.new and Tempfile.open creates a \Tempfile object.
|
24
|
+
# The created file is removed by the GC (finalizer).
|
25
|
+
# The timing of file deletion is not predictable.
|
18
26
|
#
|
19
27
|
# == Synopsis
|
20
28
|
#
|
21
29
|
# require 'tempfile'
|
22
30
|
#
|
31
|
+
# # Tempfile.create with a block
|
32
|
+
# # The filename are choosen automatically.
|
33
|
+
# # (You can specify the prefix and suffix of the filename by an optional argument.)
|
34
|
+
# Tempfile.create {|f|
|
35
|
+
# f.puts "foo"
|
36
|
+
# f.rewind
|
37
|
+
# f.read # => "foo\n"
|
38
|
+
# } # The file is removed at block exit.
|
39
|
+
#
|
40
|
+
# # Tempfile.create without a block
|
41
|
+
# # You need to unlink the file in non-block form.
|
42
|
+
# f = Tempfile.create
|
43
|
+
# f.puts "foo"
|
44
|
+
# f.close
|
45
|
+
# File.unlink(f.path) # You need to unlink the file.
|
46
|
+
#
|
47
|
+
# # Tempfile.create(anonymous: true) without a block
|
48
|
+
# f = Tempfile.create(anonymous: true)
|
49
|
+
# # The file is already removed because anonymous.
|
50
|
+
# f.path # => "/tmp/" (no filename since no file)
|
51
|
+
# f.puts "foo"
|
52
|
+
# f.rewind
|
53
|
+
# f.read # => "foo\n"
|
54
|
+
# f.close
|
55
|
+
#
|
56
|
+
# # Tempfile.create(anonymous: true) with a block
|
57
|
+
# Tempfile.create(anonymous: true) {|f|
|
58
|
+
# # The file is already removed because anonymous.
|
59
|
+
# f.path # => "/tmp/" (no filename since no file)
|
60
|
+
# f.puts "foo"
|
61
|
+
# f.rewind
|
62
|
+
# f.read # => "foo\n"
|
63
|
+
# }
|
64
|
+
#
|
65
|
+
# # Not recommended: Tempfile.new without a block
|
23
66
|
# file = Tempfile.new('foo')
|
24
67
|
# file.path # => A unique filename in the OS's temp directory,
|
25
68
|
# # e.g.: "/tmp/foo.24722.0"
|
@@ -30,7 +73,27 @@ require 'tmpdir'
|
|
30
73
|
# file.close
|
31
74
|
# file.unlink # deletes the temp file
|
32
75
|
#
|
33
|
-
# ==
|
76
|
+
# == About Tempfile.new and Tempfile.open
|
77
|
+
#
|
78
|
+
# This section does not apply to Tempfile.create because
|
79
|
+
# it returns a File object (not a Tempfile object).
|
80
|
+
#
|
81
|
+
# When you create a Tempfile object,
|
82
|
+
# it will create a temporary file with a unique filename. A Tempfile
|
83
|
+
# objects behaves just like a File object, and you can perform all the usual
|
84
|
+
# file operations on it: reading data, writing data, changing its permissions,
|
85
|
+
# etc. So although this class does not explicitly document all instance methods
|
86
|
+
# supported by File, you can in fact call any File instance method on a
|
87
|
+
# Tempfile object.
|
88
|
+
#
|
89
|
+
# A Tempfile object has a finalizer to remove the temporary file.
|
90
|
+
# This means that the temporary file is removed via GC.
|
91
|
+
# This can cause several problems:
|
92
|
+
#
|
93
|
+
# - Long GC intervals and conservative GC can accumulate temporary files that are not removed.
|
94
|
+
# - Temporary files are not removed if Ruby exits abnormally (such as SIGKILL, SEGV).
|
95
|
+
#
|
96
|
+
# There are legacy good practices for Tempfile.new and Tempfile.open as follows.
|
34
97
|
#
|
35
98
|
# === Explicit close
|
36
99
|
#
|
@@ -71,12 +134,17 @@ require 'tmpdir'
|
|
71
134
|
# be able to read from or write to the Tempfile, and you do not need to
|
72
135
|
# know the Tempfile's filename either.
|
73
136
|
#
|
137
|
+
# Also, this guarantees the temporary file is removed even if Ruby exits abnormally.
|
138
|
+
# The OS reclaims the storage for the temporary file when the file is closed or
|
139
|
+
# the Ruby process exits (normally or abnormally).
|
140
|
+
#
|
74
141
|
# For example, a practical use case for unlink-after-creation would be this:
|
75
142
|
# you need a large byte buffer that's too large to comfortably fit in RAM,
|
76
143
|
# e.g. when you're writing a web server and you want to buffer the client's
|
77
144
|
# file upload data.
|
78
145
|
#
|
79
|
-
#
|
146
|
+
# `Tempfile.create(anonymous: true)` supports this behavior.
|
147
|
+
# It also works on Windows.
|
80
148
|
#
|
81
149
|
# == Minor notes
|
82
150
|
#
|
@@ -88,7 +156,8 @@ require 'tmpdir'
|
|
88
156
|
# mutex.
|
89
157
|
class Tempfile < DelegateClass(File)
|
90
158
|
|
91
|
-
|
159
|
+
# The version
|
160
|
+
VERSION = "0.3.1"
|
92
161
|
|
93
162
|
# Creates a file in the underlying file system;
|
94
163
|
# returns a new \Tempfile object based on that file.
|
@@ -152,45 +221,47 @@ class Tempfile < DelegateClass(File)
|
|
152
221
|
|
153
222
|
@unlinked = false
|
154
223
|
@mode = mode|File::RDWR|File::CREAT|File::EXCL
|
155
|
-
@finalizer_obj = Object.new
|
156
224
|
tmpfile = nil
|
157
225
|
::Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
|
158
226
|
opts[:perm] = 0600
|
159
227
|
tmpfile = File.open(tmpname, @mode, **opts)
|
160
228
|
@opts = opts.freeze
|
161
229
|
end
|
162
|
-
ObjectSpace.define_finalizer(@finalizer_obj, Remover.new(tmpfile.path))
|
163
|
-
ObjectSpace.define_finalizer(self, Closer.new(tmpfile))
|
164
230
|
|
165
231
|
super(tmpfile)
|
232
|
+
|
233
|
+
@finalizer_manager = FinalizerManager.new(__getobj__.path)
|
234
|
+
@finalizer_manager.register(self, __getobj__)
|
166
235
|
end
|
167
236
|
|
168
|
-
def initialize_dup(other)
|
237
|
+
def initialize_dup(other) # :nodoc:
|
169
238
|
initialize_copy_iv(other)
|
170
239
|
super(other)
|
171
|
-
|
240
|
+
@finalizer_manager.register(self, __getobj__)
|
172
241
|
end
|
173
242
|
|
174
|
-
def initialize_clone(other)
|
243
|
+
def initialize_clone(other) # :nodoc:
|
175
244
|
initialize_copy_iv(other)
|
176
245
|
super(other)
|
177
|
-
|
246
|
+
@finalizer_manager.register(self, __getobj__)
|
178
247
|
end
|
179
248
|
|
180
|
-
private def initialize_copy_iv(other)
|
249
|
+
private def initialize_copy_iv(other) # :nodoc:
|
181
250
|
@unlinked = other.unlinked
|
182
251
|
@mode = other.mode
|
183
252
|
@opts = other.opts
|
184
|
-
@
|
253
|
+
@finalizer_manager = other.finalizer_manager
|
185
254
|
end
|
186
255
|
|
187
256
|
# Opens or reopens the file with mode "r+".
|
188
257
|
def open
|
189
258
|
_close
|
190
|
-
|
259
|
+
|
191
260
|
mode = @mode & ~(File::CREAT|File::EXCL)
|
192
261
|
__setobj__(File.open(__getobj__.path, mode, **@opts))
|
193
|
-
|
262
|
+
|
263
|
+
@finalizer_manager.register(self, __getobj__)
|
264
|
+
|
194
265
|
__getobj__
|
195
266
|
end
|
196
267
|
|
@@ -258,7 +329,9 @@ class Tempfile < DelegateClass(File)
|
|
258
329
|
# may not be able to unlink on Windows; just ignore
|
259
330
|
return
|
260
331
|
end
|
261
|
-
|
332
|
+
|
333
|
+
@finalizer_manager.unlinked = true
|
334
|
+
|
262
335
|
@unlinked = true
|
263
336
|
end
|
264
337
|
alias delete unlink
|
@@ -292,35 +365,35 @@ class Tempfile < DelegateClass(File)
|
|
292
365
|
|
293
366
|
protected
|
294
367
|
|
295
|
-
attr_reader :unlinked, :mode, :opts, :
|
368
|
+
attr_reader :unlinked, :mode, :opts, :finalizer_manager
|
296
369
|
|
297
|
-
class
|
298
|
-
|
299
|
-
@tmpfile = tmpfile
|
300
|
-
end
|
301
|
-
|
302
|
-
def call(*args)
|
303
|
-
@tmpfile.close
|
304
|
-
end
|
305
|
-
end
|
370
|
+
class FinalizerManager # :nodoc:
|
371
|
+
attr_accessor :unlinked
|
306
372
|
|
307
|
-
class Remover # :nodoc:
|
308
373
|
def initialize(path)
|
309
|
-
@
|
374
|
+
@open_files = {}
|
310
375
|
@path = path
|
376
|
+
@pid = Process.pid
|
377
|
+
@unlinked = false
|
311
378
|
end
|
312
379
|
|
313
|
-
def
|
314
|
-
|
380
|
+
def register(obj, file)
|
381
|
+
ObjectSpace.undefine_finalizer(obj)
|
382
|
+
ObjectSpace.define_finalizer(obj, self)
|
383
|
+
@open_files[obj.object_id] = file
|
384
|
+
end
|
315
385
|
|
316
|
-
|
386
|
+
def call(object_id)
|
387
|
+
@open_files.delete(object_id).close
|
317
388
|
|
318
|
-
|
319
|
-
|
320
|
-
|
389
|
+
if @open_files.empty? && !@unlinked && Process.pid == @pid
|
390
|
+
$stderr.puts "removing #{@path}..." if $DEBUG
|
391
|
+
begin
|
392
|
+
File.unlink(@path)
|
393
|
+
rescue Errno::ENOENT
|
394
|
+
end
|
395
|
+
$stderr.puts "done" if $DEBUG
|
321
396
|
end
|
322
|
-
|
323
|
-
$stderr.puts "done" if $DEBUG
|
324
397
|
end
|
325
398
|
end
|
326
399
|
|
@@ -391,8 +464,9 @@ end
|
|
391
464
|
# see {File Permissions}[https://docs.ruby-lang.org/en/master/File.html#label-File+Permissions].
|
392
465
|
# - Mode is <tt>'w+'</tt> (read/write mode, positioned at the end).
|
393
466
|
#
|
394
|
-
#
|
395
|
-
#
|
467
|
+
# The temporary file removal depends on the keyword argument +anonymous+ and
|
468
|
+
# whether a block is given or not.
|
469
|
+
# See the description about the +anonymous+ keyword argument later.
|
396
470
|
#
|
397
471
|
# Example:
|
398
472
|
#
|
@@ -400,11 +474,36 @@ end
|
|
400
474
|
# f.class # => File
|
401
475
|
# f.path # => "/tmp/20220505-9795-17ky6f6"
|
402
476
|
# f.stat.mode.to_s(8) # => "100600"
|
477
|
+
# f.close
|
403
478
|
# File.exist?(f.path) # => true
|
404
479
|
# File.unlink(f.path)
|
405
480
|
# File.exist?(f.path) # => false
|
406
481
|
#
|
407
|
-
#
|
482
|
+
# Tempfile.create {|f|
|
483
|
+
# f.puts "foo"
|
484
|
+
# f.rewind
|
485
|
+
# f.read # => "foo\n"
|
486
|
+
# f.path # => "/tmp/20240524-380207-oma0ny"
|
487
|
+
# File.exist?(f.path) # => true
|
488
|
+
# } # The file is removed at block exit.
|
489
|
+
#
|
490
|
+
# f = Tempfile.create(anonymous: true)
|
491
|
+
# # The file is already removed because anonymous
|
492
|
+
# f.path # => "/tmp/" (no filename since no file)
|
493
|
+
# f.puts "foo"
|
494
|
+
# f.rewind
|
495
|
+
# f.read # => "foo\n"
|
496
|
+
# f.close
|
497
|
+
#
|
498
|
+
# Tempfile.create(anonymous: true) {|f|
|
499
|
+
# # The file is already removed because anonymous
|
500
|
+
# f.path # => "/tmp/" (no filename since no file)
|
501
|
+
# f.puts "foo"
|
502
|
+
# f.rewind
|
503
|
+
# f.read # => "foo\n"
|
504
|
+
# }
|
505
|
+
#
|
506
|
+
# The argument +basename+, if given, may be one of the following:
|
408
507
|
#
|
409
508
|
# - A string: the generated filename begins with +basename+:
|
410
509
|
#
|
@@ -415,27 +514,57 @@ end
|
|
415
514
|
#
|
416
515
|
# Tempfile.create(%w/foo .jpg/) # => #<File:/tmp/foo20220505-17839-tnjchh.jpg>
|
417
516
|
#
|
418
|
-
# With arguments +basename+ and +tmpdir+, the file is created in directory +tmpdir+:
|
517
|
+
# With arguments +basename+ and +tmpdir+, the file is created in the directory +tmpdir+:
|
419
518
|
#
|
420
519
|
# Tempfile.create('foo', '.') # => #<File:./foo20220505-9795-1emu6g8>
|
421
520
|
#
|
422
|
-
# Keyword arguments +mode+ and +options+ are passed directly to method
|
521
|
+
# Keyword arguments +mode+ and +options+ are passed directly to the method
|
423
522
|
# {File.open}[https://docs.ruby-lang.org/en/master/File.html#method-c-open]:
|
424
523
|
#
|
425
|
-
# - The value given
|
524
|
+
# - The value given for +mode+ must be an integer
|
426
525
|
# and may be expressed as the logical OR of constants defined in
|
427
526
|
# {File::Constants}[https://docs.ruby-lang.org/en/master/File/Constants.html].
|
428
527
|
# - For +options+, see {Open Options}[https://docs.ruby-lang.org/en/master/IO.html#class-IO-label-Open+Options].
|
429
528
|
#
|
430
|
-
#
|
431
|
-
#
|
432
|
-
#
|
529
|
+
# The keyword argument +anonymous+ specifies when the file is removed.
|
530
|
+
#
|
531
|
+
# - <tt>anonymous=false</tt> (default) without a block: the file is not removed.
|
532
|
+
# - <tt>anonymous=false</tt> (default) with a block: the file is removed after the block exits.
|
533
|
+
# - <tt>anonymous=true</tt> without a block: the file is removed before returning.
|
534
|
+
# - <tt>anonymous=true</tt> with a block: the file is removed before the block is called.
|
535
|
+
#
|
536
|
+
# In the first case (<tt>anonymous=false</tt> without a block),
|
537
|
+
# the file is not removed automatically.
|
538
|
+
# It should be explicitly closed.
|
539
|
+
# It can be used to rename to the desired filename.
|
540
|
+
# If the file is not needed, it should be explicitly removed.
|
541
|
+
#
|
542
|
+
# The File#path method of the created file object returns the temporary directory with a trailing slash
|
543
|
+
# when +anonymous+ is true.
|
544
|
+
#
|
545
|
+
# When a block is given, it creates the file as described above, passes it to the block,
|
546
|
+
# and returns the block's value.
|
547
|
+
# Before the returning, the file object is closed and the underlying file is removed:
|
433
548
|
#
|
434
549
|
# Tempfile.create {|file| file.path } # => "/tmp/20220505-9795-rkists"
|
435
550
|
#
|
551
|
+
# Implementation note:
|
552
|
+
#
|
553
|
+
# The keyword argument +anonymous=true+ is implemented using FILE_SHARE_DELETE on Windows.
|
554
|
+
# O_TMPFILE is used on Linux.
|
555
|
+
#
|
436
556
|
# Related: Tempfile.new.
|
437
557
|
#
|
438
|
-
def Tempfile.create(basename="", tmpdir=nil, mode: 0, **options)
|
558
|
+
def Tempfile.create(basename="", tmpdir=nil, mode: 0, anonymous: false, **options, &block)
|
559
|
+
if anonymous
|
560
|
+
create_anonymous(basename, tmpdir, mode: mode, **options, &block)
|
561
|
+
else
|
562
|
+
create_with_filename(basename, tmpdir, mode: mode, **options, &block)
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
class << Tempfile
|
567
|
+
private def create_with_filename(basename="", tmpdir=nil, mode: 0, **options)
|
439
568
|
tmpfile = nil
|
440
569
|
Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
|
441
570
|
mode |= File::RDWR|File::CREAT|File::EXCL
|
@@ -463,3 +592,49 @@ def Tempfile.create(basename="", tmpdir=nil, mode: 0, **options)
|
|
463
592
|
tmpfile
|
464
593
|
end
|
465
594
|
end
|
595
|
+
|
596
|
+
if RUBY_VERSION < "3.2"
|
597
|
+
module PathAttr # :nodoc:
|
598
|
+
attr_reader :path
|
599
|
+
|
600
|
+
def self.set_path(file, path)
|
601
|
+
file.extend(self).instance_variable_set(:@path, path)
|
602
|
+
end
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
606
|
+
private def create_anonymous(basename="", tmpdir=nil, mode: 0, **options, &block)
|
607
|
+
tmpfile = nil
|
608
|
+
tmpdir = Dir.tmpdir() if tmpdir.nil?
|
609
|
+
if defined?(File::TMPFILE) # O_TMPFILE since Linux 3.11
|
610
|
+
begin
|
611
|
+
tmpfile = File.open(tmpdir, File::RDWR | File::TMPFILE, 0600)
|
612
|
+
rescue Errno::EISDIR, Errno::ENOENT, Errno::EOPNOTSUPP
|
613
|
+
# kernel or the filesystem does not support O_TMPFILE
|
614
|
+
# fallback to create-and-unlink
|
615
|
+
end
|
616
|
+
end
|
617
|
+
if tmpfile.nil?
|
618
|
+
mode |= File::SHARE_DELETE | File::BINARY # Windows needs them to unlink the opened file.
|
619
|
+
tmpfile = create_with_filename(basename, tmpdir, mode: mode, **options)
|
620
|
+
File.unlink(tmpfile.path)
|
621
|
+
tmppath = tmpfile.path
|
622
|
+
end
|
623
|
+
path = File.join(tmpdir, '')
|
624
|
+
unless tmppath == path
|
625
|
+
# clear path.
|
626
|
+
tmpfile.autoclose = false
|
627
|
+
tmpfile = File.new(tmpfile.fileno, mode: File::RDWR, path: path)
|
628
|
+
PathAttr.set_path(tmpfile, path) if defined?(PathAttr)
|
629
|
+
end
|
630
|
+
if block
|
631
|
+
begin
|
632
|
+
yield tmpfile
|
633
|
+
ensure
|
634
|
+
tmpfile.close
|
635
|
+
end
|
636
|
+
else
|
637
|
+
tmpfile
|
638
|
+
end
|
639
|
+
end
|
640
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tempfile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yukihiro Matsumoto
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A utility class for managing temporary files.
|
14
14
|
email:
|
@@ -17,17 +17,12 @@ executables: []
|
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
-
- ".
|
21
|
-
-
|
22
|
-
-
|
23
|
-
- Gemfile
|
24
|
-
- Gemfile.lock
|
20
|
+
- ".document"
|
21
|
+
- BSDL
|
22
|
+
- COPYING
|
25
23
|
- README.md
|
26
24
|
- Rakefile
|
27
|
-
- bin/console
|
28
|
-
- bin/setup
|
29
25
|
- lib/tempfile.rb
|
30
|
-
- tempfile.gemspec
|
31
26
|
homepage: https://github.com/ruby/tempfile
|
32
27
|
licenses:
|
33
28
|
- Ruby
|
@@ -35,7 +30,7 @@ licenses:
|
|
35
30
|
metadata:
|
36
31
|
homepage_uri: https://github.com/ruby/tempfile
|
37
32
|
source_code_uri: https://github.com/ruby/tempfile
|
38
|
-
post_install_message:
|
33
|
+
post_install_message:
|
39
34
|
rdoc_options: []
|
40
35
|
require_paths:
|
41
36
|
- lib
|
@@ -50,8 +45,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
45
|
- !ruby/object:Gem::Version
|
51
46
|
version: '0'
|
52
47
|
requirements: []
|
53
|
-
rubygems_version: 3.5.
|
54
|
-
signing_key:
|
48
|
+
rubygems_version: 3.5.11
|
49
|
+
signing_key:
|
55
50
|
specification_version: 4
|
56
51
|
summary: A utility class for managing temporary files.
|
57
52
|
test_files: []
|
data/.github/dependabot.yml
DELETED
data/.github/workflows/test.yml
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
name: ubuntu
|
2
|
-
|
3
|
-
on: [push, pull_request]
|
4
|
-
|
5
|
-
jobs:
|
6
|
-
ruby-versions:
|
7
|
-
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
|
8
|
-
with:
|
9
|
-
engine: cruby
|
10
|
-
min_version: 2.5
|
11
|
-
test:
|
12
|
-
needs: ruby-versions
|
13
|
-
name: build (${{ matrix.ruby }} / ${{ matrix.os }})
|
14
|
-
strategy:
|
15
|
-
matrix:
|
16
|
-
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
|
17
|
-
os: [ ubuntu-latest, macos-latest, windows-latest ]
|
18
|
-
runs-on: ${{ matrix.os }}
|
19
|
-
steps:
|
20
|
-
- uses: actions/checkout@v4
|
21
|
-
- name: Set up Ruby
|
22
|
-
uses: ruby/setup-ruby@v1
|
23
|
-
with:
|
24
|
-
ruby-version: ${{ matrix.ruby }}
|
25
|
-
- name: Install dependencies
|
26
|
-
run: bundle install
|
27
|
-
- name: Run test
|
28
|
-
run: rake test
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
tempfile (0.1.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
power_assert (1.1.5)
|
10
|
-
rake (13.0.1)
|
11
|
-
test-unit (3.3.5)
|
12
|
-
power_assert
|
13
|
-
|
14
|
-
PLATFORMS
|
15
|
-
ruby
|
16
|
-
|
17
|
-
DEPENDENCIES
|
18
|
-
rake
|
19
|
-
tempfile!
|
20
|
-
test-unit
|
21
|
-
|
22
|
-
BUNDLED WITH
|
23
|
-
2.1.4
|
data/bin/console
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "tempfile"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
data/bin/setup
DELETED
data/tempfile.gemspec
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
name = File.basename(__FILE__, ".gemspec")
|
2
|
-
version = ["lib", Array.new(name.count("-")+1).join("/")].find do |dir|
|
3
|
-
break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
|
4
|
-
/^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
|
5
|
-
end rescue nil
|
6
|
-
end
|
7
|
-
|
8
|
-
Gem::Specification.new do |spec|
|
9
|
-
spec.name = name
|
10
|
-
spec.version = version
|
11
|
-
spec.authors = ["Yukihiro Matsumoto"]
|
12
|
-
spec.email = ["matz@ruby-lang.org"]
|
13
|
-
|
14
|
-
spec.summary = %q{A utility class for managing temporary files.}
|
15
|
-
spec.description = %q{A utility class for managing temporary files.}
|
16
|
-
spec.homepage = "https://github.com/ruby/tempfile"
|
17
|
-
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
18
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
19
|
-
|
20
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
21
|
-
spec.metadata["source_code_uri"] = spec.homepage
|
22
|
-
|
23
|
-
# Specify which files should be added to the gem when it is released.
|
24
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
-
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
26
|
-
`git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
|
-
end
|
28
|
-
spec.require_paths = ["lib"]
|
29
|
-
end
|