core_ex 0.1.0
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.
- data/AUTHORS +26 -0
- data/NEWS +8 -0
- data/README +1 -0
- data/Rakefile +7 -0
- data/SPEC.dyn.yml +8 -0
- data/SPEC.yml +37 -0
- data/lib/core_ex/attr_once.rb +36 -0
- data/lib/core_ex/dtime.rb +169 -0
- data/lib/core_ex/embedded_tests.rb +33 -0
- data/lib/core_ex/enumerable.rb +173 -0
- data/lib/core_ex/exception.rb +32 -0
- data/lib/core_ex/filelist.rb +464 -0
- data/lib/core_ex/fileutils.rb +44 -0
- data/lib/core_ex/pathname.rb +196 -0
- data/lib/core_ex/require.rb +378 -0
- data/lib/core_ex/string.rb +47 -0
- data/lib/core_ex/temp_path.rb +194 -0
- data/lib/core_ex/test/unit/ui/yaml/testrunner.rb +166 -0
- data/lib/core_ex/time.rb +91 -0
- data/lib/core_ex/version.rb +119 -0
- data/lib/core_ex/yaml.rb +24 -0
- data/lib/core_ex.rb +55 -0
- data/test/check-core_ex.yml +12 -0
- data/test/check-pkg-core_ex.yml +15 -0
- data/test/resources/autoload_tree/A.rb +11 -0
- data/test/resources/autoload_tree/B.rb +10 -0
- data/test/resources/autoload_tree/foo/C.rb +18 -0
- data/test/resources/require/test_require +1 -0
- data/test/resources/require/test_require_rb.rb +1 -0
- data/test/resources/require/test_require_so.so +1 -0
- data/test/resources/use-from-gems.rb +9 -0
- data/test/resources/yaml_testrunner/unit_test.rb +43 -0
- data/test/sanity/multiple-requires.yml +20 -0
- data/test/sanity/single-requires.yml +24 -0
- data/test/sanity-suite.yml +12 -0
- data/test/test-unit-setup.rb +6 -0
- data/test/unit-suite.yml +14 -0
- metadata +113 -0
@@ -0,0 +1,378 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
|
2
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
3
|
+
# License:: Gnu General Public License.
|
4
|
+
# Revision:: $Id: require.rb 252 2005-05-31 23:41:42Z ertai $
|
5
|
+
|
6
|
+
require 'core_ex/pathname'
|
7
|
+
require 'set'
|
8
|
+
|
9
|
+
module Kernel
|
10
|
+
class << self
|
11
|
+
alias :__require__ :require
|
12
|
+
alias :__load__ :load
|
13
|
+
end
|
14
|
+
end # module Kernel
|
15
|
+
|
16
|
+
|
17
|
+
class RequireSystem
|
18
|
+
|
19
|
+
|
20
|
+
EXTENSIONS = %w[ .rb .so .bundle .o .dll ] << ''
|
21
|
+
|
22
|
+
|
23
|
+
attr_reader :include_dirs, :loaded, :required
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@include_dirs = Set.new
|
27
|
+
@loaded = Set.new
|
28
|
+
# @autoloads = {} FIXME AUTOLOAD
|
29
|
+
@required = Set.new
|
30
|
+
self.class.enable
|
31
|
+
Kernel.kernel_require_system = self
|
32
|
+
Module.module_require_system = self
|
33
|
+
$".each do |file|
|
34
|
+
feature = file.to_path.expand_path_with($:, EXTENSIONS)
|
35
|
+
raise "file not found #{file}" if feature.nil?
|
36
|
+
@required << feature
|
37
|
+
end
|
38
|
+
feature = $0.to_path.expand_path_with($:, EXTENSIONS)
|
39
|
+
@required << feature unless feature.nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def check_pathname ( aPathname )
|
44
|
+
unless aPathname.is_a? Pathname
|
45
|
+
raise LoadError, "need a Pathname not a #{aPathname.class}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
protected :check_pathname
|
49
|
+
|
50
|
+
|
51
|
+
def cannot_found ( aPathname )
|
52
|
+
raise LoadError, "CoreEx: Cannot found #{aPathname} in $:"
|
53
|
+
end
|
54
|
+
private :cannot_found
|
55
|
+
|
56
|
+
|
57
|
+
def load ( aPathname )
|
58
|
+
check_pathname(aPathname)
|
59
|
+
abs = aPathname.expand_path_with($:, EXTENSIONS)
|
60
|
+
cannot_found(aPathname) if abs.nil?
|
61
|
+
@loaded << abs
|
62
|
+
Kernel.__load__(abs)
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# FIXME This autoload doesn't work for these reasons:
|
67
|
+
# - |
|
68
|
+
# # file1.rb
|
69
|
+
# module B
|
70
|
+
# class A
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# # file2.rb
|
75
|
+
# class A # where ::A != B::A
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# module B
|
79
|
+
# autoload :A, 'file1'
|
80
|
+
# A # this doesn't work because ::A exists so no const_missing is reached
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# - |
|
84
|
+
# # file1.rb
|
85
|
+
# module B
|
86
|
+
# class A
|
87
|
+
# end
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
# # file2.rb
|
91
|
+
# module B
|
92
|
+
# autoload :A, 'file1'
|
93
|
+
# class ::C
|
94
|
+
# A # this doesn't work because A is search in ::C which is not
|
95
|
+
# # included in B.
|
96
|
+
# end
|
97
|
+
# end
|
98
|
+
# etc.
|
99
|
+
# Const missing was (it's obvious now) a very bad idea to make an autoload.
|
100
|
+
# We need to hook a const_get which is call every time.
|
101
|
+
def autoload ( aModule, aConst, aPathname )
|
102
|
+
raise ArgumentError, "need a module not #{cst}" unless aModule.is_a? Module
|
103
|
+
raise ArgumentError, "need a symbol not #{cst}" unless aConst.is_a? Symbol
|
104
|
+
raise if aConst.to_s =~ /::/
|
105
|
+
abs = aPathname.expand_path_with($:, EXTENSIONS)
|
106
|
+
abs = aPathname if abs.nil? # FIXME
|
107
|
+
# cannot_found(aPathname) if abs.nil?
|
108
|
+
aModule.__autoload__(aConst, abs.to_s)
|
109
|
+
# @autoloads[aModule] ||= {}
|
110
|
+
# @autoloads[aModule][aConst] ||= []
|
111
|
+
# @autoloads[aModule][aConst] << aPathname
|
112
|
+
self
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
# def const_missing ( aModule, aConst )
|
117
|
+
# raise ArgumentError, "need a module not #{cst}" unless aModule.is_a? Module
|
118
|
+
# raise ArgumentError, "need a symbol not #{cst}" unless aConst.is_a? Symbol
|
119
|
+
# raise if aConst.to_s =~ /::/
|
120
|
+
# @autoloads[aModule] ||= {}
|
121
|
+
# if @autoloads[aModule][aConst].nil?
|
122
|
+
# mods = aModule.to_s.split(/::/)
|
123
|
+
# if mods.size == 1
|
124
|
+
# p "CONSTMISSING"
|
125
|
+
# aModule.__const_missing__(aConst)
|
126
|
+
# end
|
127
|
+
# return const_missing(eval(mods[0..-2].join('::')), aConst)
|
128
|
+
# end
|
129
|
+
# @autoloads[aModule][aConst] ||= []
|
130
|
+
# @autoloads[aModule][aConst].each do |req|
|
131
|
+
# req.require
|
132
|
+
# end
|
133
|
+
# @autoloads[aModule].delete aConst
|
134
|
+
# if aModule.const_defined?(aConst)
|
135
|
+
# aModule.const_get(aConst)
|
136
|
+
# else
|
137
|
+
# p "CONSTMISSING"
|
138
|
+
# aModule.__const_missing__(aConst)
|
139
|
+
# end
|
140
|
+
# end
|
141
|
+
|
142
|
+
def require ( aPathname )
|
143
|
+
check_pathname(aPathname)
|
144
|
+
abs = aPathname.expand_path_with($:, EXTENSIONS)
|
145
|
+
cannot_found(aPathname) if abs.nil?
|
146
|
+
feature = aPathname.to_s
|
147
|
+
feature += abs.extname if aPathname.extname.empty?
|
148
|
+
if $".include? feature or @required.include? abs
|
149
|
+
return false
|
150
|
+
else
|
151
|
+
@required << abs
|
152
|
+
if abs.extname =~ /^(\.rb)?$/
|
153
|
+
$" << feature
|
154
|
+
res = Kernel.__load__(abs)
|
155
|
+
else
|
156
|
+
res = Kernel.__require__(abs.extsplit.first.to_s)
|
157
|
+
$" << feature unless $".include? feature
|
158
|
+
end
|
159
|
+
return true
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
def include_dir ( aPathname )
|
165
|
+
unless abs = include_dir?(aPathname)
|
166
|
+
$: << aPathname.to_s
|
167
|
+
$: << abs.to_s
|
168
|
+
@include_dirs << abs
|
169
|
+
end
|
170
|
+
self
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
def include_dir? ( aPathname )
|
175
|
+
check_pathname(aPathname)
|
176
|
+
abs = aPathname.expand_path.cleanpath
|
177
|
+
return ($:.include?(aPathname.to_s) ||
|
178
|
+
$:.include?(abs.to_s) ||
|
179
|
+
@include_dirs.include?(abs))? abs : nil
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
def required? ( aPathname )
|
184
|
+
check_pathname(aPathname)
|
185
|
+
abs = aPathname.expand_path_with($:, EXTENSIONS)
|
186
|
+
cannot_found(aPathname) if abs.nil?
|
187
|
+
feature = aPathname.to_s
|
188
|
+
feature += abs.extname if aPathname.extname.empty?
|
189
|
+
return $".include?(feature) || @required.include?(abs)
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
def self.instance
|
194
|
+
@@instance = new
|
195
|
+
class << self
|
196
|
+
undef :instance
|
197
|
+
def instance
|
198
|
+
@@instance
|
199
|
+
end
|
200
|
+
end
|
201
|
+
@@instance
|
202
|
+
end
|
203
|
+
|
204
|
+
def self.enable
|
205
|
+
class << self
|
206
|
+
module ::Kernel
|
207
|
+
def kernel_require_system= ( arg )
|
208
|
+
@@require_system = arg
|
209
|
+
end
|
210
|
+
alias :__require__ :require
|
211
|
+
def require ( aString )
|
212
|
+
@@require_system.require(aString.to_path)
|
213
|
+
end
|
214
|
+
alias :__load__ :load
|
215
|
+
def load ( aString )
|
216
|
+
@@require_system.load(aString.to_path)
|
217
|
+
end
|
218
|
+
end # module ::Kernel
|
219
|
+
class ::Module
|
220
|
+
def module_require_system= ( arg )
|
221
|
+
@@require_system = arg
|
222
|
+
end
|
223
|
+
alias :__autoload__ :autoload
|
224
|
+
def autoload ( aConst, anObject )
|
225
|
+
@@require_system.autoload(self, aConst, anObject.to_path)
|
226
|
+
end
|
227
|
+
# alias :__const_missing__ :const_missing
|
228
|
+
# def const_missing ( aConst )
|
229
|
+
# @@require_system.const_missing(self, aConst)
|
230
|
+
# end
|
231
|
+
end # module ::Module
|
232
|
+
undef :enable
|
233
|
+
def enable
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
end # class RequireSystem
|
239
|
+
|
240
|
+
|
241
|
+
|
242
|
+
test_section __FILE__ do
|
243
|
+
|
244
|
+
class RequireSystemTest < Test::Unit::TestCase
|
245
|
+
|
246
|
+
class MockRequirable < Pathname
|
247
|
+
@@requires = []
|
248
|
+
def initialize ( name, url )
|
249
|
+
@name, @url = name, url
|
250
|
+
end
|
251
|
+
def require ( *a )
|
252
|
+
@url.require
|
253
|
+
@@requires << @name
|
254
|
+
end
|
255
|
+
def self.requires
|
256
|
+
@@requires
|
257
|
+
end
|
258
|
+
def inspect
|
259
|
+
"#<#{self.class}: url=#@url, name=#@name>"
|
260
|
+
end
|
261
|
+
def self.[] ( name, url )
|
262
|
+
new(name, url)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
@@save_dirs = $:.dup
|
267
|
+
@@save_files = $".dup
|
268
|
+
|
269
|
+
def setup
|
270
|
+
@rs = RequireSystem.new
|
271
|
+
@test = __FILE__.to_path.dirname.parent.parent + 'test'
|
272
|
+
@res = @test + 'resources'
|
273
|
+
@req = @res + 'require'
|
274
|
+
@s = 'test_require'
|
275
|
+
@s_dne = 'test_require_dne'
|
276
|
+
@s_so = 'test_require_so.so'
|
277
|
+
@s_rb = 'test_require_rb.rb'
|
278
|
+
@p = @s.to_path
|
279
|
+
@p_dne = @s_dne.to_path
|
280
|
+
@p_so = @s_so.to_path
|
281
|
+
@p_rb = @s_rb.to_path
|
282
|
+
@ls = [ @s, @s_dne, @s_so, @s_rb ]
|
283
|
+
@lp = [ @p, @p_dne, @p_so, @p_rb ]
|
284
|
+
@l = @ls + @lp
|
285
|
+
$:.replace @@save_dirs.dup
|
286
|
+
$".replace @@save_files.dup
|
287
|
+
@mr = MockRequirable
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_0_initialize
|
291
|
+
%w[
|
292
|
+
load require
|
293
|
+
include_dir include_dirs
|
294
|
+
loaded required
|
295
|
+
].each do |m|
|
296
|
+
assert_respond_to(@rs, m, m)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def assert_search ( inp, ref )
|
301
|
+
assert_nothing_raised do
|
302
|
+
@my = inp.expand_path_with($:, RequireSystem::EXTENSIONS)
|
303
|
+
ref = ref.expand_path.cleanpath unless ref.nil?
|
304
|
+
assert_equal(ref, @my, inp)
|
305
|
+
end
|
306
|
+
unless ref.nil?
|
307
|
+
assert_kind_of(Pathname, @my)
|
308
|
+
assert(@my.exist?)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def test_1_search
|
313
|
+
@ls.each do |x|
|
314
|
+
assert_raise(LoadError) do
|
315
|
+
x.expand_path_with($:, RequireSystem::EXTENSIONS)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
@lp.each { |x| assert_search(x, nil) }
|
319
|
+
end
|
320
|
+
|
321
|
+
def test_2_include_dir
|
322
|
+
assert(! @rs.include_dir?(@test))
|
323
|
+
assert_nothing_raised do
|
324
|
+
assert_equal(@rs, @rs.include_dir(@test))
|
325
|
+
end
|
326
|
+
assert(@rs.include_dir?(@test))
|
327
|
+
$: << @res.to_s
|
328
|
+
assert(@rs.include_dir?(@res))
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_2_search
|
332
|
+
@rs.include_dir(@req)
|
333
|
+
@lp.delete(@p_dne)
|
334
|
+
@lp.each { |x| assert_search(x, @req + x) }
|
335
|
+
@lp.each { |x| assert_search(@req + x, @req + x) }
|
336
|
+
assert_search(@p_dne, nil)
|
337
|
+
end
|
338
|
+
|
339
|
+
def test_load
|
340
|
+
end
|
341
|
+
|
342
|
+
def assert_require ( aPathname, ref_bool, ref_cst )
|
343
|
+
$REQUIRE_SYSTEM_TEST_COUNTER = 0
|
344
|
+
assert_nothing_raised { @my = aPathname.require }
|
345
|
+
assert_equal(ref_bool, @my)
|
346
|
+
assert_equal(ref_cst, $REQUIRE_SYSTEM_TEST_COUNTER)
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_require
|
350
|
+
@lp.each do |x|
|
351
|
+
assert_raise(LoadError) { x.require }
|
352
|
+
end
|
353
|
+
@rs.include_dir(@req)
|
354
|
+
@lp.delete(@p_dne)
|
355
|
+
@lp.each { |x| assert_require(x, true, 1) }
|
356
|
+
assert_raise(LoadError) { @p_dne.require }
|
357
|
+
end
|
358
|
+
|
359
|
+
module ::AutoloadTree
|
360
|
+
end
|
361
|
+
|
362
|
+
def t_e_s_t_autoload # FIXME AUTOLOAD
|
363
|
+
@rs.include_dir(@res + 'autoload_tree')
|
364
|
+
[[:A,'A'], [:B,'B'], [:Foo, 'foo/C']].each do |cst,url|
|
365
|
+
assert_nothing_raised { AutoloadTree.autoload cst, @mr[cst,url] }
|
366
|
+
end
|
367
|
+
assert_nothing_raised do
|
368
|
+
assert(AutoloadTree)
|
369
|
+
assert_equal('AutoloadTree::A', ::AutoloadTree::A.name)
|
370
|
+
assert_equal('AutoloadTree::B', ::AutoloadTree::B.name)
|
371
|
+
assert_equal('AutoloadTree::Foo::C', ::AutoloadTree::Foo::C.name)
|
372
|
+
end
|
373
|
+
assert_equal([:A, :B, :Foo], @mr.requires)
|
374
|
+
end
|
375
|
+
|
376
|
+
end # RequireSystemTest
|
377
|
+
end
|
378
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004, 2005 Nicolas Pouillard. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
# Revision:: $Id$
|
5
|
+
|
6
|
+
class String
|
7
|
+
|
8
|
+
#
|
9
|
+
# Provide an helper to cut strings.
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
#
|
13
|
+
# puts "
|
14
|
+
# | A very complex
|
15
|
+
# | string
|
16
|
+
# | with a specific indentation.
|
17
|
+
# |
|
18
|
+
# |I prefer that instead of a HERE doc
|
19
|
+
# | because I keep my indentation.
|
20
|
+
# |".head_cut!
|
21
|
+
#
|
22
|
+
def head_cut! ( sep='\|' )
|
23
|
+
gsub!(/^\s*#{sep}/, '')
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def require
|
28
|
+
to_path.require
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_path
|
32
|
+
Pathname.new(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
def autoload ( aConst )
|
36
|
+
to_path.autoload(aConst)
|
37
|
+
end
|
38
|
+
|
39
|
+
# XXX
|
40
|
+
# Do not implement to_io.
|
41
|
+
# It breaks File.exists?
|
42
|
+
# def to_io
|
43
|
+
# end
|
44
|
+
# XXX
|
45
|
+
|
46
|
+
end # class String
|
47
|
+
|
@@ -0,0 +1,194 @@
|
|
1
|
+
# Copyright: Copyright (c) 2004 Nicolas Pouillard. All rights reserved.
|
2
|
+
# Author: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
3
|
+
# License: Gnu General Public License.
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: temp_path.rb 252 2005-05-31 23:41:42Z ertai $
|
7
|
+
|
8
|
+
require 'core_ex'
|
9
|
+
require 'tempfile'
|
10
|
+
require 'tmpdir'
|
11
|
+
require 'set'
|
12
|
+
require 'thread'
|
13
|
+
|
14
|
+
class TempPath < Pathname
|
15
|
+
|
16
|
+
@@tmps = Set.new
|
17
|
+
@@mutex = Mutex.new
|
18
|
+
@@progname = Pathname.new($0).basename
|
19
|
+
@@tmpdir = Pathname.new(Dir.tmpdir) + "#{@@progname}.#{$$}"
|
20
|
+
@@tmpdir.freeze
|
21
|
+
@@initialized = false
|
22
|
+
@@clean_planned = false
|
23
|
+
@@auto_clean = true
|
24
|
+
|
25
|
+
# You can use a temporary pathname like that:
|
26
|
+
#
|
27
|
+
# - # No argument are mandatory.
|
28
|
+
# tmp = TempPath.new
|
29
|
+
# tmp.open('w') { |f| f << 'foo' }
|
30
|
+
# tmp.clean
|
31
|
+
#
|
32
|
+
# - # You can choose the basename and an extension.
|
33
|
+
# TmpPath.new('the_base_file_name', 'rb')
|
34
|
+
#
|
35
|
+
# - # You can supply a block (recomended).
|
36
|
+
# TmpPath.new('foo') do |tmp|
|
37
|
+
# tmp.open('w') { |f| << 'foo' }
|
38
|
+
# tmp.exist? == true
|
39
|
+
# $tmp = tmp
|
40
|
+
# end
|
41
|
+
# $tmp.exist? == false
|
42
|
+
#
|
43
|
+
# - # You can make a temporary directory.
|
44
|
+
# TmpPath.new('adirectory') do |tmpdir|
|
45
|
+
# tmpdir.mkpath
|
46
|
+
# $file = tmpdir + 'foo'
|
47
|
+
# $file.open('w') { |f| f << 'foo' }
|
48
|
+
# end
|
49
|
+
# $file.exist? == false
|
50
|
+
#
|
51
|
+
# The file name follow this scheme:
|
52
|
+
#
|
53
|
+
# TempPath.new('foo', 'rb')
|
54
|
+
# => 'foo.111811.432.rb'
|
55
|
+
# TempPath.new('bar')
|
56
|
+
# => 'bar.111811.134'
|
57
|
+
#
|
58
|
+
# which follow this format:
|
59
|
+
# => 'base.pid.uniq.ext
|
60
|
+
#
|
61
|
+
def initialize ( base=@@progname, ext='', &block )
|
62
|
+
if base.to_s =~ /\//
|
63
|
+
raise ArgumentError, "bad basename, you give me a pathname #{base}"
|
64
|
+
end
|
65
|
+
self.class.init
|
66
|
+
ext = ".#{ext}" unless ext.empty? or ext[0] == ?.
|
67
|
+
res = nil
|
68
|
+
@@mutex.synchronize do
|
69
|
+
id_tmp = object_id
|
70
|
+
while (res = @@tmpdir + "#{base}.#{id_tmp}#{ext}").exist? \
|
71
|
+
and not @@tmps.include? res
|
72
|
+
id_tmp += 1
|
73
|
+
end
|
74
|
+
super(res)
|
75
|
+
@@tmps << self
|
76
|
+
end
|
77
|
+
if block_given?
|
78
|
+
begin
|
79
|
+
block[self.dup]
|
80
|
+
ensure
|
81
|
+
clean
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# This method remove your temporary pathname.
|
87
|
+
# You do not need to call this method if you provide
|
88
|
+
# a block when you create a tempfile.
|
89
|
+
def clean
|
90
|
+
if exist?
|
91
|
+
if directory?
|
92
|
+
rmtree
|
93
|
+
else
|
94
|
+
unlink
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def temp?
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.init #:nodoc:
|
104
|
+
return if @@initialized
|
105
|
+
@@mutex.synchronize do
|
106
|
+
return if @@initialized
|
107
|
+
@@tmpdir.mkpath
|
108
|
+
@@initialized = true
|
109
|
+
at_exit { clean if @@auto_clean }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# By default the autoclean is on.
|
114
|
+
# But in some case (if you use your temppaths in at_exit)
|
115
|
+
# You must disable the autoclean.
|
116
|
+
# And manually call TempPath.clean at the very of the program.
|
117
|
+
def self.clean ( &block )
|
118
|
+
@@mutex.synchronize do
|
119
|
+
return if @@clean_planned
|
120
|
+
@@clean_planned = true
|
121
|
+
end
|
122
|
+
begin
|
123
|
+
block[] if block_given?
|
124
|
+
ensure
|
125
|
+
if @@tmpdir.exist?
|
126
|
+
@@tmpdir.rmtree
|
127
|
+
@@initialized = false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.auto_clean= ( aBool )
|
133
|
+
@@auto_clean = aBool
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.tmpdir
|
137
|
+
init
|
138
|
+
@@tmpdir
|
139
|
+
end
|
140
|
+
|
141
|
+
end # class TempPath
|
142
|
+
|
143
|
+
|
144
|
+
class Pathname
|
145
|
+
|
146
|
+
def temp?
|
147
|
+
false
|
148
|
+
end
|
149
|
+
|
150
|
+
end # class Pathname
|
151
|
+
|
152
|
+
|
153
|
+
|
154
|
+
test_section __FILE__ do
|
155
|
+
|
156
|
+
class MkTempTest < Test::Unit::TestCase
|
157
|
+
|
158
|
+
def setup
|
159
|
+
assert_nothing_raised { @foo = TempPath.new('foo') }
|
160
|
+
assert_nothing_raised { @foobar = TempPath.new('foo', 'bar') }
|
161
|
+
@list = []
|
162
|
+
end
|
163
|
+
|
164
|
+
def teardown
|
165
|
+
@list.each { |l| l.clean }
|
166
|
+
[@foo, @foobar].each { |l| l.clean }
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_interface
|
170
|
+
assert_match(/\.#{$$}\/foo\.\d+$/, @foo.to_s)
|
171
|
+
assert_match(/\.#{$$}\/foo\.\d+\.bar$/, @foobar.to_s)
|
172
|
+
assert_nothing_raised { @foo.open('w') { |f| f.puts 'FooFoo' } }
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_many
|
176
|
+
(0 .. 100).each do |i|
|
177
|
+
tmp = TempPath.new('many')
|
178
|
+
tmp.open('w') { |f| f.puts "i: #{i}" }
|
179
|
+
assert(tmp.exist?)
|
180
|
+
assert_equal("i: #{i}\n", tmp.readlines.join)
|
181
|
+
@list << tmp
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_temp?
|
186
|
+
assert(@foo.temp?, 'not tmp.temp?')
|
187
|
+
assert_nothing_raised do
|
188
|
+
assert(!Pathname.new(@foo.to_s).temp?)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
end # class MkTempTest
|
193
|
+
|
194
|
+
end
|