scout-gear 1.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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.vimproject +45 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +63 -0
- data/VERSION +1 -0
- data/bin/scout +0 -0
- data/lib/scout/exceptions.rb +112 -0
- data/lib/scout/indiferent_hash/case_insensitive.rb +30 -0
- data/lib/scout/indiferent_hash/options.rb +132 -0
- data/lib/scout/indiferent_hash.rb +107 -0
- data/lib/scout/log/color.rb +169 -0
- data/lib/scout/log/color_class.rb +269 -0
- data/lib/scout/log/fingerprint.rb +59 -0
- data/lib/scout/log/progress/report.rb +240 -0
- data/lib/scout/log/progress/util.rb +100 -0
- data/lib/scout/log/progress.rb +102 -0
- data/lib/scout/log.rb +362 -0
- data/lib/scout/meta_extension.rb +29 -0
- data/lib/scout/path/find.rb +65 -0
- data/lib/scout/path.rb +62 -0
- data/lib/scout/tmpfile.rb +96 -0
- data/lib/scout-gear.rb +3 -0
- data/scout-gear.gemspec +78 -0
- data/test/scout/indiferent_hash/test_options.rb +36 -0
- data/test/scout/log/test_progress.rb +110 -0
- data/test/scout/path/test_find.rb +34 -0
- data/test/scout/test_indiferent_hash.rb +26 -0
- data/test/scout/test_log.rb +32 -0
- data/test/scout/test_meta_extension.rb +22 -0
- data/test/scout/test_path.rb +36 -0
- data/test/scout/test_tmpfile.rb +53 -0
- data/test/test_helper.rb +27 -0
- metadata +134 -0
data/lib/scout/log.rb
ADDED
@@ -0,0 +1,362 @@
|
|
1
|
+
require_relative 'log/color'
|
2
|
+
require_relative 'log/fingerprint'
|
3
|
+
require_relative 'log/progress'
|
4
|
+
|
5
|
+
require 'io/console'
|
6
|
+
|
7
|
+
module Log
|
8
|
+
SEVERITY_NAMES ||= begin
|
9
|
+
names = %w(DEBUG LOW MEDIUM HIGH INFO WARN ERROR NONE )
|
10
|
+
names.each_with_index do |name,i|
|
11
|
+
eval "#{ name } = #{ i }"
|
12
|
+
end
|
13
|
+
names
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
attr_accessor :logfile, :severity
|
18
|
+
attr_writer :tty_size
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def self.tty_size
|
23
|
+
@tty_size = begin
|
24
|
+
IO.console.winsize.last
|
25
|
+
rescue
|
26
|
+
begin
|
27
|
+
`tput li`
|
28
|
+
rescue
|
29
|
+
80
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def self.last_caller(stack)
|
36
|
+
line = nil
|
37
|
+
pos ||= 0
|
38
|
+
while line.nil? or line =~ /scout\/helper\/log\.rb/ and stack.any?
|
39
|
+
line = stack.shift
|
40
|
+
end
|
41
|
+
line ||= caller.first
|
42
|
+
line.gsub('`', "'")
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.get_level(level)
|
46
|
+
case level
|
47
|
+
when Numeric
|
48
|
+
level.to_i
|
49
|
+
when String
|
50
|
+
begin
|
51
|
+
Log.const_get(level.upcase)
|
52
|
+
rescue
|
53
|
+
Log.exception $!
|
54
|
+
end
|
55
|
+
when Symbol
|
56
|
+
get_level(level.to_s)
|
57
|
+
end || 0
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.with_severity(level)
|
61
|
+
orig = Log.severity
|
62
|
+
begin
|
63
|
+
Log.severity = level
|
64
|
+
yield
|
65
|
+
ensure
|
66
|
+
Log.severity = orig
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.logfile(file=nil)
|
71
|
+
if file.nil?
|
72
|
+
@logfile ||= nil
|
73
|
+
else
|
74
|
+
case file
|
75
|
+
when String
|
76
|
+
@logfile = File.open(file, :mode => 'a')
|
77
|
+
@logfile.sync = true
|
78
|
+
when IO, File
|
79
|
+
@logfile = file
|
80
|
+
else
|
81
|
+
raise "Unkown logfile format: #{file.inspect}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.up_lines(num = 1)
|
87
|
+
nocolor ? "" : "\033[#{num+1}F\033[2K"
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.down_lines(num = 1)
|
91
|
+
nocolor ? "" : "\033[#{num+1}E"
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.return_line
|
95
|
+
nocolor ? "" : "\033[1A"
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.clear_line(out = STDOUT)
|
99
|
+
out.puts Log.return_line << " " * (Log.tty_size || 80) << Log.return_line unless nocolor
|
100
|
+
end
|
101
|
+
|
102
|
+
LAST = "log"
|
103
|
+
def self.logn(message = nil, severity = MEDIUM, &block)
|
104
|
+
return if severity < self.severity
|
105
|
+
message ||= block.call if block_given?
|
106
|
+
return if message.nil?
|
107
|
+
|
108
|
+
time = Time.now.strftime("%m/%d/%y-%H:%M:%S.%L")
|
109
|
+
|
110
|
+
sev_str = severity.to_s
|
111
|
+
|
112
|
+
prefix = time << color(severity) << "[" << sev_str << "]" << color(0)
|
113
|
+
message = "" << highlight << message << color(0) if severity >= INFO
|
114
|
+
str = prefix << " " << message.to_s
|
115
|
+
|
116
|
+
if logfile.nil?
|
117
|
+
STDERR.write str
|
118
|
+
else
|
119
|
+
logfile.write str
|
120
|
+
end
|
121
|
+
Log::LAST.replace "log"
|
122
|
+
nil
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.log(message = nil, severity = MEDIUM, &block)
|
126
|
+
return if severity < self.severity
|
127
|
+
message ||= block.call if block_given?
|
128
|
+
return if message.nil?
|
129
|
+
message = message + "\n" unless message[-1] == "\n"
|
130
|
+
self.logn message, severity, &block
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.log_obj_inspect(obj, level, file = $stdout)
|
134
|
+
stack = caller
|
135
|
+
|
136
|
+
line = Log.last_caller stack
|
137
|
+
|
138
|
+
level = Log.get_level level
|
139
|
+
name = Log::SEVERITY_NAMES[level] + ": "
|
140
|
+
Log.log Log.color(level, name, true) << line, level
|
141
|
+
Log.log "", level
|
142
|
+
Log.log Log.color(level, "=> ", true) << obj.inspect, level
|
143
|
+
Log.log "", level
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.log_obj_fingerprint(obj, level, file = $stdout)
|
147
|
+
stack = caller
|
148
|
+
|
149
|
+
line = Log.last_caller stack
|
150
|
+
|
151
|
+
level = Log.get_level level
|
152
|
+
name = Log::SEVERITY_NAMES[level] + ": "
|
153
|
+
Log.log Log.color(level, name, true) << line, level
|
154
|
+
Log.log "", level
|
155
|
+
Log.log Log.color(level, "=> ", true) << Log.fingerprint(obj), level
|
156
|
+
Log.log "", level
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.debug(message = nil, &block)
|
160
|
+
log(message, DEBUG, &block)
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.low(message = nil, &block)
|
164
|
+
log(message, LOW, &block)
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.medium(message = nil, &block)
|
168
|
+
log(message, MEDIUM, &block)
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.high(message = nil, &block)
|
172
|
+
log(message, HIGH, &block)
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.info(message = nil, &block)
|
176
|
+
log(message, INFO, &block)
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.warn(message = nil, &block)
|
180
|
+
log(message, WARN, &block)
|
181
|
+
end
|
182
|
+
|
183
|
+
def self.error(message = nil, &block)
|
184
|
+
log(message, ERROR, &block)
|
185
|
+
end
|
186
|
+
|
187
|
+
def self.exception(e)
|
188
|
+
stack = caller
|
189
|
+
if ENV["RBBT_ORIGINAL_STACK"] == 'true'
|
190
|
+
error([e.class.to_s, e.message].compact * ": " )
|
191
|
+
error("BACKTRACE [#{Process.pid}]: " << Log.last_caller(stack) << "\n" + color_stack(e.backtrace)*"\n")
|
192
|
+
else
|
193
|
+
error("BACKTRACE [#{Process.pid}]: " << Log.last_caller(stack) << "\n" + color_stack(e.backtrace.reverse)*"\n")
|
194
|
+
error([e.class.to_s, e.message].compact * ": " )
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def self.deprecated(m)
|
199
|
+
stack = caller
|
200
|
+
warn("DEPRECATED: " << Log.last_caller(stack))
|
201
|
+
warn("* " << (m || "").to_s)
|
202
|
+
end
|
203
|
+
|
204
|
+
def self.color_stack(stack)
|
205
|
+
stack.collect do |line|
|
206
|
+
line = line.sub('`',"'")
|
207
|
+
color = :green if line =~ /workflow/
|
208
|
+
color = :blue if line =~ /scout-/
|
209
|
+
Log.color color, line
|
210
|
+
end unless stack.nil?
|
211
|
+
end
|
212
|
+
|
213
|
+
def self.tsv(tsv, example = false)
|
214
|
+
STDERR.puts Log.color :magenta, "TSV log: " << Log.last_caller(caller).gsub('`',"'")
|
215
|
+
STDERR.puts Log.color(:blue, "=> "<< Log.fingerprint(tsv), true)
|
216
|
+
STDERR.puts Log.color(:cyan, "=> " << tsv.summary)
|
217
|
+
if example && ! tsv.empty?
|
218
|
+
key = case example
|
219
|
+
when TrueClass, :first, "first"
|
220
|
+
tsv.keys.first
|
221
|
+
when :random, "random"
|
222
|
+
tsv.keys.shuffle.first
|
223
|
+
else
|
224
|
+
example
|
225
|
+
end
|
226
|
+
|
227
|
+
values = tsv[key]
|
228
|
+
values = [values] if tsv.type == :flat || tsv.type == :single
|
229
|
+
if values.nil?
|
230
|
+
STDERR.puts Log.color(:blue, "Key (#{tsv.key_field}) not present: ") + key
|
231
|
+
else
|
232
|
+
STDERR.puts Log.color(:blue, "Key (#{tsv.key_field}): ") + key
|
233
|
+
tsv.fields.zip(values).each do |field,value|
|
234
|
+
STDERR.puts Log.color(:magenta, field + ": ") + (Array === value ? value * ", " : value.to_s)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def self.stack(stack)
|
241
|
+
if ENV["RBBT_ORIGINAL_STACK"] == 'true'
|
242
|
+
STDERR.puts Log.color :magenta, "Stack trace [#{Process.pid}]: " << Log.last_caller(caller)
|
243
|
+
color_stack(stack).each do |line|
|
244
|
+
STDERR.puts line
|
245
|
+
end
|
246
|
+
else
|
247
|
+
STDERR.puts Log.color :magenta, "Stack trace [#{Process.pid}]: " << Log.last_caller(caller)
|
248
|
+
color_stack(stack.reverse).each do |line|
|
249
|
+
STDERR.puts line
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def self.count_stack
|
255
|
+
if ! $count_stacks
|
256
|
+
Log.debug "Counting stacks at: " << caller.first
|
257
|
+
return
|
258
|
+
end
|
259
|
+
$stack_counts ||= {}
|
260
|
+
head = $count_stacks_head
|
261
|
+
stack = caller[1..head+1]
|
262
|
+
stack.reverse.each do |line,i|
|
263
|
+
$stack_counts[line] ||= 0
|
264
|
+
$stack_counts[line] += 1
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def self.with_stack_counts(head = 10, total = 100)
|
269
|
+
$count_stacks_head = head
|
270
|
+
$count_stacks = true
|
271
|
+
$stack_counts = {}
|
272
|
+
res = yield
|
273
|
+
$count_stacks = false
|
274
|
+
Log.debug "STACK_COUNTS:\n" + $stack_counts.sort_by{|line,c| c}.reverse.collect{|line,c| [c, line] * " - "}[0..total] * "\n"
|
275
|
+
$stack_counts = {}
|
276
|
+
res
|
277
|
+
end
|
278
|
+
|
279
|
+
case ENV['RBBT_LOG']
|
280
|
+
when 'DEBUG'
|
281
|
+
self.severity = DEBUG
|
282
|
+
when 'LOW'
|
283
|
+
self.severity = LOW
|
284
|
+
when 'MEDIUM'
|
285
|
+
self.severity = MEDIUM
|
286
|
+
when 'HIGH'
|
287
|
+
self.severity = HIGH
|
288
|
+
when nil
|
289
|
+
self.severity = INFO
|
290
|
+
else
|
291
|
+
self.severity = ENV['RBBT_LOG'].to_i
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def ppp(message)
|
296
|
+
stack = caller
|
297
|
+
puts "#{Log.color :cyan, "PRINT:"} " << stack.first
|
298
|
+
puts ""
|
299
|
+
if message.length > 200 or message.include? "\n"
|
300
|
+
puts Log.color(:cyan, "=>|") << "\n" << message.to_s
|
301
|
+
else
|
302
|
+
puts Log.color(:cyan, "=> ") << message.to_s
|
303
|
+
end
|
304
|
+
puts ""
|
305
|
+
end
|
306
|
+
|
307
|
+
def fff(object)
|
308
|
+
stack = caller
|
309
|
+
Log.debug{"#{Log.color :cyan, "FINGERPRINT:"} " << stack.first}
|
310
|
+
Log.debug{""}
|
311
|
+
Log.debug{require 'scout/util/misc'; "=> " << Log.fingerprint(object) }
|
312
|
+
Log.debug{""}
|
313
|
+
end
|
314
|
+
|
315
|
+
def ddd(obj, file = $stdout)
|
316
|
+
Log.log_obj_inspect(obj, :debug, file)
|
317
|
+
end
|
318
|
+
|
319
|
+
def lll(obj, file = $stdout)
|
320
|
+
Log.log_obj_inspect(obj, :low, file)
|
321
|
+
end
|
322
|
+
|
323
|
+
def mmm(obj, file = $stdout)
|
324
|
+
Log.log_obj_inspect(obj, :medium, file)
|
325
|
+
end
|
326
|
+
|
327
|
+
def iii(obj=nil, file = $stdout)
|
328
|
+
Log.log_obj_inspect(obj, :info, file)
|
329
|
+
end
|
330
|
+
|
331
|
+
def wwww(obj=nil, file = $stdout)
|
332
|
+
Log.log_obj_inspect(obj, :warn, file)
|
333
|
+
end
|
334
|
+
|
335
|
+
def eee(obj=nil, file = $stdout)
|
336
|
+
Log.log_obj_inspect(obj, :error, file)
|
337
|
+
end
|
338
|
+
|
339
|
+
def ddf(obj=nil, file = $stdout)
|
340
|
+
Log.log_obj_fingerprint(obj, :debug, file)
|
341
|
+
end
|
342
|
+
|
343
|
+
def llf(obj=nil, file = $stdout)
|
344
|
+
Log.log_obj_fingerprint(obj, :low, file)
|
345
|
+
end
|
346
|
+
|
347
|
+
def mmf(obj=nil, file = $stdout)
|
348
|
+
Log.log_obj_fingerprint(obj, :medium, file)
|
349
|
+
end
|
350
|
+
|
351
|
+
def iif(obj=nil, file = $stdout)
|
352
|
+
Log.log_obj_fingerprint(obj, :info, file)
|
353
|
+
end
|
354
|
+
|
355
|
+
def wwwf(obj=nil, file = $stdout)
|
356
|
+
Log.log_obj_fingerprint(obj, :warn, file)
|
357
|
+
end
|
358
|
+
|
359
|
+
def eef(obj=nil, file = $stdout)
|
360
|
+
Log.log_obj_fingerprint(obj, :error, file)
|
361
|
+
end
|
362
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module MetaExtension
|
2
|
+
def self.extended(base)
|
3
|
+
meta = class << base; self; end
|
4
|
+
|
5
|
+
base.class_variable_set("@@extension_attrs", [])
|
6
|
+
|
7
|
+
meta.define_method(:extension_attr) do |*attrs|
|
8
|
+
self.class_variable_get("@@extension_attrs").concat attrs
|
9
|
+
attrs.each do |a|
|
10
|
+
self.attr_accessor a
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
meta.define_method(:setup) do |obj,*rest|
|
15
|
+
obj.extend base
|
16
|
+
self.class_variable_get("@@extension_attrs").zip(rest).each do |name,value|
|
17
|
+
obj.instance_variable_set("@#{name}", value)
|
18
|
+
end
|
19
|
+
obj
|
20
|
+
end
|
21
|
+
|
22
|
+
base.define_method(:annotate) do |other|
|
23
|
+
attr_values = meta.class_variable_get("@@extension_attrs").collect do |a|
|
24
|
+
self.instance_variable_get("@#{a}")
|
25
|
+
end
|
26
|
+
base.setup(other, *attr_values)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Path
|
2
|
+
def _parts
|
3
|
+
@_parts ||= self.split("/")
|
4
|
+
end
|
5
|
+
|
6
|
+
def _subpath
|
7
|
+
@subpath ||= _parts.length > 1 ? _parts[1..-1] * "/" : _parts[0]
|
8
|
+
end
|
9
|
+
|
10
|
+
def _toplevel
|
11
|
+
@toplevel ||= _parts.length > 1 ? _parts[0] : nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.follow(path, map)
|
15
|
+
map.sub('{PKGDIR}', path.pkgdir).
|
16
|
+
sub('{RESOURCE}', path.to_s).
|
17
|
+
sub('{PWD}', FileUtils.pwd).
|
18
|
+
sub('{TOPLEVEL}', path._toplevel).
|
19
|
+
sub('{SUBPATH}', path._subpath).
|
20
|
+
sub('{BASENAME}', File.basename(path)).
|
21
|
+
sub('{PATH}', path).
|
22
|
+
sub('{LIBDIR}', path.libdir).
|
23
|
+
sub('{REMOVE}/', '').
|
24
|
+
sub('{REMOVE}', '').gsub(/\/+/,'/')
|
25
|
+
end
|
26
|
+
|
27
|
+
PATH_MAPS = IndiferentHash.setup({
|
28
|
+
:current => File.join("{PWD}", "{TOPLEVEL}", "{SUBPATH}"),
|
29
|
+
:user => File.join(ENV['HOME'], ".{PKGDIR}", "{TOPLEVEL}", "{SUBPATH}"),
|
30
|
+
:global => File.join('/', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
31
|
+
:usr => File.join('/usr/', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
32
|
+
:local => File.join('/usr/local', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
33
|
+
:fast => File.join('/fast', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
34
|
+
:cache => File.join('/cache', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
35
|
+
:bulk => File.join('/bulk', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
36
|
+
:lib => File.join('{LIBDIR}', "{TOPLEVEL}", "{SUBPATH}"),
|
37
|
+
:base => File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}", "{SUBPATH}"),
|
38
|
+
:default => :user
|
39
|
+
})
|
40
|
+
|
41
|
+
MAP_SEARCH = %w(current workflow user local global lib fast cache bulk)
|
42
|
+
|
43
|
+
def _follow(map_name)
|
44
|
+
map = PATH_MAPS[map_name]
|
45
|
+
while Symbol === map
|
46
|
+
map = PATH_MAPS[map]
|
47
|
+
end
|
48
|
+
Path.follow(self, map)
|
49
|
+
end
|
50
|
+
|
51
|
+
def find(where = nil)
|
52
|
+
return _follow(where) if where
|
53
|
+
|
54
|
+
all_maps = PATH_MAPS.keys
|
55
|
+
search_order = MAP_SEARCH & all_maps + (all_maps - MAP_SEARCH)
|
56
|
+
|
57
|
+
search_order.each do |name|
|
58
|
+
map = PATH_MAPS[name]
|
59
|
+
real_path = _follow(map)
|
60
|
+
return real_path if File.exists?(real_path)
|
61
|
+
end
|
62
|
+
|
63
|
+
return _follow(:default)
|
64
|
+
end
|
65
|
+
end
|
data/lib/scout/path.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require_relative 'meta_extension'
|
2
|
+
|
3
|
+
module Path
|
4
|
+
extend MetaExtension
|
5
|
+
extension_attr :pkgdir, :libdir
|
6
|
+
|
7
|
+
def self.caller_lib_dir(file = nil, relative_to = ['lib', 'bin'])
|
8
|
+
|
9
|
+
if file.nil?
|
10
|
+
caller_dup = caller.dup
|
11
|
+
while file = caller_dup.shift
|
12
|
+
break unless file =~ /scout\/(?:resource\.rb|workflow\.rb)/ or
|
13
|
+
file =~ /scout\/path\.rb/ or
|
14
|
+
file =~ /scout\/persist.rb/
|
15
|
+
end
|
16
|
+
file = file.sub(/\.rb[^\w].*/,'.rb')
|
17
|
+
end
|
18
|
+
|
19
|
+
relative_to = [relative_to] unless Array === relative_to
|
20
|
+
file = File.expand_path(file)
|
21
|
+
return Path.setup(file) if relative_to.select{|d| File.exist? File.join(file, d)}.any?
|
22
|
+
|
23
|
+
while file != '/'
|
24
|
+
dir = File.dirname file
|
25
|
+
|
26
|
+
return dir if relative_to.select{|d| File.exist? File.join(dir, d)}.any?
|
27
|
+
|
28
|
+
file = File.dirname file
|
29
|
+
end
|
30
|
+
|
31
|
+
return nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.setup(path, pkgdir = 'scout', libdir = nil)
|
35
|
+
path.extend Path
|
36
|
+
path.pkgdir = pkgdir
|
37
|
+
path.libdir = libdir || Path.caller_lib_dir
|
38
|
+
path
|
39
|
+
end
|
40
|
+
|
41
|
+
def join(subpath, prevpath = nil)
|
42
|
+
subpath = subpath.to_s if Symbol === subpath
|
43
|
+
prevpath = prevpath.to_s if Symbol === prevpath
|
44
|
+
|
45
|
+
subpath = File.join(prevpath.to_s, subpath) if prevpath
|
46
|
+
new = File.join(self, subpath)
|
47
|
+
self.annotate(new)
|
48
|
+
new
|
49
|
+
end
|
50
|
+
|
51
|
+
alias [] join
|
52
|
+
alias / join
|
53
|
+
|
54
|
+
def method_missing(name, prev = nil, *args, &block)
|
55
|
+
if block_given? || name.to_s.start_with?('to_')
|
56
|
+
super name, prev, *args, &block
|
57
|
+
else
|
58
|
+
join(name, prev)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module TmpFile
|
4
|
+
def self.user_tmp(subdir = nil)
|
5
|
+
if subdir
|
6
|
+
File.join(ENV["HOME"],"/tmp/scout", subdir)
|
7
|
+
else
|
8
|
+
File.join(ENV["HOME"],"/tmp/scout")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.tmpdir=(tmpdir)
|
13
|
+
@tmpdir = tmpdir
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.tmpdir
|
17
|
+
@tmpdir ||= self.user_tmp('tmpfiles')
|
18
|
+
end
|
19
|
+
|
20
|
+
# Creates a random file name, with the given suffix and a random number
|
21
|
+
# up to +max+
|
22
|
+
def self.random_name(prefix = 'tmp-', max = 1_000_000_000)
|
23
|
+
n = rand(max)
|
24
|
+
prefix + n.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
# Creates a random filename in the temporary directory
|
28
|
+
def self.tmp_file(prefix = 'tmp-', max = 1_000_000_000, dir = nil)
|
29
|
+
dir ||= TmpFile.tmpdir
|
30
|
+
File.expand_path(File.join(dir, random_name(prefix, max)))
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.with_file(content = nil, erase = true, options = {})
|
34
|
+
if content.is_a?(Hash)
|
35
|
+
options = content
|
36
|
+
content = nil
|
37
|
+
erase = true
|
38
|
+
end
|
39
|
+
if erase.is_a?(Hash)
|
40
|
+
options = erase
|
41
|
+
erase = true
|
42
|
+
end
|
43
|
+
|
44
|
+
prefix = options[:prefix] || 'tmp-'
|
45
|
+
tmpdir = options[:tmpdir] || TmpFile.tmpdir
|
46
|
+
max = options[:max] || 1_000_000_000
|
47
|
+
tmpfile = tmp_file prefix, max, tmpdir
|
48
|
+
tmpfile += ".#{options[:extension]}" if options[:extension]
|
49
|
+
|
50
|
+
FileUtils.mkdir_p tmpdir
|
51
|
+
if IO === content
|
52
|
+
File.open(tmpfile, 'wb') do |f|
|
53
|
+
begin
|
54
|
+
while c = content.readpartial(1024)
|
55
|
+
f << c
|
56
|
+
end
|
57
|
+
rescue EOFError
|
58
|
+
end
|
59
|
+
end
|
60
|
+
elsif !content.nil?
|
61
|
+
File.open(tmpfile, 'w') { |f| f.write content }
|
62
|
+
end
|
63
|
+
|
64
|
+
result = yield(tmpfile)
|
65
|
+
|
66
|
+
FileUtils.rm_rf tmpfile if File.exist?(tmpfile) && erase
|
67
|
+
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.with_dir(erase = true, options = {})
|
72
|
+
prefix = options[:prefix] || 'tmpdir-'
|
73
|
+
tmpdir = tmp_file prefix
|
74
|
+
|
75
|
+
FileUtils.mkdir_p tmpdir
|
76
|
+
|
77
|
+
result = yield(tmpdir)
|
78
|
+
|
79
|
+
FileUtils.rm_rf tmpdir if File.exist?(tmpdir) && erase
|
80
|
+
|
81
|
+
result
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.in_dir(*args)
|
85
|
+
with_dir(*args) do |dir|
|
86
|
+
old_pwd = FileUtils.pwd
|
87
|
+
begin
|
88
|
+
FileUtils.mkdir_p dir unless File.exist?(dir)
|
89
|
+
FileUtils.cd dir
|
90
|
+
yield dir
|
91
|
+
ensure
|
92
|
+
FileUtils.cd old_pwd
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/scout-gear.rb
ADDED
data/scout-gear.gemspec
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Generated by juwelier
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
# stub: scout-gear 1.1.0 ruby lib
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "scout-gear".freeze
|
9
|
+
s.version = "1.1.0"
|
10
|
+
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib".freeze]
|
13
|
+
s.authors = ["Miguel Vazquez".freeze]
|
14
|
+
s.date = "2023-03-24"
|
15
|
+
s.description = "Temporary files, logs, etc.".freeze
|
16
|
+
s.email = "mikisvaz@gmail.com".freeze
|
17
|
+
s.executables = ["scout".freeze]
|
18
|
+
s.extra_rdoc_files = [
|
19
|
+
"LICENSE.txt",
|
20
|
+
"README.rdoc"
|
21
|
+
]
|
22
|
+
s.files = [
|
23
|
+
".document",
|
24
|
+
".vimproject",
|
25
|
+
"LICENSE.txt",
|
26
|
+
"README.rdoc",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION",
|
29
|
+
"bin/scout",
|
30
|
+
"lib/scout-gear.rb",
|
31
|
+
"lib/scout/exceptions.rb",
|
32
|
+
"lib/scout/indiferent_hash.rb",
|
33
|
+
"lib/scout/indiferent_hash/case_insensitive.rb",
|
34
|
+
"lib/scout/indiferent_hash/options.rb",
|
35
|
+
"lib/scout/log.rb",
|
36
|
+
"lib/scout/log/color.rb",
|
37
|
+
"lib/scout/log/color_class.rb",
|
38
|
+
"lib/scout/log/fingerprint.rb",
|
39
|
+
"lib/scout/log/progress.rb",
|
40
|
+
"lib/scout/log/progress/report.rb",
|
41
|
+
"lib/scout/log/progress/util.rb",
|
42
|
+
"lib/scout/meta_extension.rb",
|
43
|
+
"lib/scout/path.rb",
|
44
|
+
"lib/scout/path/find.rb",
|
45
|
+
"lib/scout/tmpfile.rb",
|
46
|
+
"scout-gear.gemspec",
|
47
|
+
"test/scout/indiferent_hash/test_options.rb",
|
48
|
+
"test/scout/log/test_progress.rb",
|
49
|
+
"test/scout/path/test_find.rb",
|
50
|
+
"test/scout/test_indiferent_hash.rb",
|
51
|
+
"test/scout/test_log.rb",
|
52
|
+
"test/scout/test_meta_extension.rb",
|
53
|
+
"test/scout/test_path.rb",
|
54
|
+
"test/scout/test_tmpfile.rb",
|
55
|
+
"test/test_helper.rb"
|
56
|
+
]
|
57
|
+
s.homepage = "http://github.com/mikisvaz/scout-gear".freeze
|
58
|
+
s.licenses = ["MIT".freeze]
|
59
|
+
s.rubygems_version = "3.2.15".freeze
|
60
|
+
s.summary = "basic gear for scouts".freeze
|
61
|
+
|
62
|
+
if s.respond_to? :specification_version then
|
63
|
+
s.specification_version = 4
|
64
|
+
end
|
65
|
+
|
66
|
+
if s.respond_to? :add_runtime_dependency then
|
67
|
+
s.add_development_dependency(%q<rdoc>.freeze, ["~> 3.12"])
|
68
|
+
s.add_development_dependency(%q<bundler>.freeze, ["~> 1.0"])
|
69
|
+
s.add_development_dependency(%q<juwelier>.freeze, ["~> 2.1.0"])
|
70
|
+
s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
|
71
|
+
else
|
72
|
+
s.add_dependency(%q<rdoc>.freeze, ["~> 3.12"])
|
73
|
+
s.add_dependency(%q<bundler>.freeze, ["~> 1.0"])
|
74
|
+
s.add_dependency(%q<juwelier>.freeze, ["~> 2.1.0"])
|
75
|
+
s.add_dependency(%q<simplecov>.freeze, [">= 0"])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|