tempfile 0.2.1 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|