scout-essentials 1.0.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.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.vimproject +78 -0
  4. data/Gemfile +14 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +18 -0
  7. data/Rakefile +47 -0
  8. data/VERSION +1 -0
  9. data/lib/scout/cmd.rb +348 -0
  10. data/lib/scout/concurrent_stream.rb +284 -0
  11. data/lib/scout/config.rb +168 -0
  12. data/lib/scout/exceptions.rb +77 -0
  13. data/lib/scout/indiferent_hash/case_insensitive.rb +30 -0
  14. data/lib/scout/indiferent_hash/options.rb +115 -0
  15. data/lib/scout/indiferent_hash.rb +96 -0
  16. data/lib/scout/log/color.rb +224 -0
  17. data/lib/scout/log/color_class.rb +269 -0
  18. data/lib/scout/log/fingerprint.rb +69 -0
  19. data/lib/scout/log/progress/report.rb +244 -0
  20. data/lib/scout/log/progress/util.rb +173 -0
  21. data/lib/scout/log/progress.rb +106 -0
  22. data/lib/scout/log/trap.rb +107 -0
  23. data/lib/scout/log.rb +441 -0
  24. data/lib/scout/meta_extension.rb +100 -0
  25. data/lib/scout/misc/digest.rb +63 -0
  26. data/lib/scout/misc/filesystem.rb +25 -0
  27. data/lib/scout/misc/format.rb +255 -0
  28. data/lib/scout/misc/helper.rb +31 -0
  29. data/lib/scout/misc/insist.rb +56 -0
  30. data/lib/scout/misc/monitor.rb +66 -0
  31. data/lib/scout/misc/system.rb +73 -0
  32. data/lib/scout/misc.rb +10 -0
  33. data/lib/scout/named_array.rb +138 -0
  34. data/lib/scout/open/lock/lockfile.rb +587 -0
  35. data/lib/scout/open/lock.rb +68 -0
  36. data/lib/scout/open/remote.rb +135 -0
  37. data/lib/scout/open/stream.rb +491 -0
  38. data/lib/scout/open/util.rb +244 -0
  39. data/lib/scout/open.rb +170 -0
  40. data/lib/scout/path/find.rb +204 -0
  41. data/lib/scout/path/tmpfile.rb +8 -0
  42. data/lib/scout/path/util.rb +127 -0
  43. data/lib/scout/path.rb +51 -0
  44. data/lib/scout/persist/open.rb +17 -0
  45. data/lib/scout/persist/path.rb +15 -0
  46. data/lib/scout/persist/serialize.rb +157 -0
  47. data/lib/scout/persist.rb +104 -0
  48. data/lib/scout/resource/open.rb +8 -0
  49. data/lib/scout/resource/path.rb +80 -0
  50. data/lib/scout/resource/produce/rake.rb +69 -0
  51. data/lib/scout/resource/produce.rb +151 -0
  52. data/lib/scout/resource/scout.rb +3 -0
  53. data/lib/scout/resource/software.rb +178 -0
  54. data/lib/scout/resource/util.rb +59 -0
  55. data/lib/scout/resource.rb +40 -0
  56. data/lib/scout/simple_opt/accessor.rb +54 -0
  57. data/lib/scout/simple_opt/doc.rb +126 -0
  58. data/lib/scout/simple_opt/get.rb +57 -0
  59. data/lib/scout/simple_opt/parse.rb +67 -0
  60. data/lib/scout/simple_opt/setup.rb +26 -0
  61. data/lib/scout/simple_opt.rb +5 -0
  62. data/lib/scout/tmpfile.rb +129 -0
  63. data/lib/scout-essentials.rb +10 -0
  64. data/scout-essentials.gemspec +143 -0
  65. data/share/color/color_names +507 -0
  66. data/share/color/diverging_colors.hex +12 -0
  67. data/share/software/install_helpers +523 -0
  68. data/test/scout/indiferent_hash/test_case_insensitive.rb +16 -0
  69. data/test/scout/indiferent_hash/test_options.rb +46 -0
  70. data/test/scout/log/test_color.rb +0 -0
  71. data/test/scout/log/test_progress.rb +108 -0
  72. data/test/scout/misc/test_digest.rb +30 -0
  73. data/test/scout/misc/test_filesystem.rb +30 -0
  74. data/test/scout/misc/test_insist.rb +13 -0
  75. data/test/scout/misc/test_system.rb +21 -0
  76. data/test/scout/open/test_lock.rb +52 -0
  77. data/test/scout/open/test_remote.rb +25 -0
  78. data/test/scout/open/test_stream.rb +676 -0
  79. data/test/scout/open/test_util.rb +73 -0
  80. data/test/scout/path/test_find.rb +110 -0
  81. data/test/scout/path/test_util.rb +22 -0
  82. data/test/scout/persist/test_open.rb +37 -0
  83. data/test/scout/persist/test_path.rb +37 -0
  84. data/test/scout/persist/test_serialize.rb +114 -0
  85. data/test/scout/resource/test_path.rb +58 -0
  86. data/test/scout/resource/test_produce.rb +94 -0
  87. data/test/scout/resource/test_software.rb +24 -0
  88. data/test/scout/resource/test_util.rb +38 -0
  89. data/test/scout/simple_opt/test_doc.rb +16 -0
  90. data/test/scout/simple_opt/test_get.rb +11 -0
  91. data/test/scout/simple_opt/test_parse.rb +10 -0
  92. data/test/scout/simple_opt/test_setup.rb +77 -0
  93. data/test/scout/test_cmd.rb +85 -0
  94. data/test/scout/test_concurrent_stream.rb +29 -0
  95. data/test/scout/test_config.rb +66 -0
  96. data/test/scout/test_indiferent_hash.rb +26 -0
  97. data/test/scout/test_log.rb +32 -0
  98. data/test/scout/test_meta_extension.rb +80 -0
  99. data/test/scout/test_misc.rb +6 -0
  100. data/test/scout/test_named_array.rb +43 -0
  101. data/test/scout/test_open.rb +146 -0
  102. data/test/scout/test_path.rb +54 -0
  103. data/test/scout/test_persist.rb +186 -0
  104. data/test/scout/test_resource.rb +26 -0
  105. data/test/scout/test_tmpfile.rb +53 -0
  106. data/test/test_helper.rb +50 -0
  107. metadata +247 -0
@@ -0,0 +1,244 @@
1
+ require 'yaml'
2
+ module Log
3
+ class ProgressBar
4
+ def print(io, str)
5
+ return if self.severity && self.severity < Log.severity
6
+ return if Log.no_bar
7
+ Log.log_write str
8
+ Log::LAST.replace "progress"
9
+ end
10
+
11
+ attr_accessor :history, :mean_max, :max_history
12
+ def thr_msg
13
+ if @history.nil?
14
+ @history ||= [[0, @start], [@ticks, Time.now] ]
15
+ elsif @last_ticks != @ticks
16
+ @history << [@ticks, Time.now]
17
+ max_history ||= begin
18
+ max_history = case
19
+ when @ticks > 20
20
+ count = @ticks - @last_count
21
+ count = 1 if count == 0
22
+ if @max
23
+ times = @max / count
24
+ num = times / 20
25
+ num = 2 if num < 2
26
+ else
27
+ num = 10
28
+ end
29
+ count * num
30
+ else
31
+ 20
32
+ end
33
+ max_history = 30 if max_history > 30
34
+ max_history
35
+ end
36
+ @history.shift if @history.length > max_history
37
+ end
38
+
39
+ @last_ticks = @ticks
40
+
41
+ @mean_max ||= 0
42
+ if @history.length > 3
43
+
44
+ sticks, stime = @history.first
45
+ ssticks, sstime = @history[-3]
46
+ lticks, ltime = @history.last
47
+
48
+
49
+ mean = @mean = (lticks - sticks).to_f / (ltime - stime)
50
+ short_mean = (lticks - ssticks).to_f / (ltime - sstime)
51
+
52
+ @mean_max = mean if mean > @mean_max
53
+ end
54
+
55
+ if short_mean
56
+ thr = short_mean
57
+ else
58
+ thr = begin
59
+ d = Time.now - @start
60
+ if d == 0
61
+ 1
62
+ else
63
+ (@ticks || 1) / d
64
+ end
65
+ end
66
+ end
67
+
68
+ thr = 0.0000001 if thr == 0
69
+
70
+ if mean.nil? or mean.to_i > 2
71
+ str = "#{ Log.color :blue, thr.to_i.to_s } per sec."
72
+ #str << " #{ Log.color :yellow, mean.to_i.to_s } avg. #{Log.color :yellow, @mean_max.to_i.to_s} max." if @mean_max > 0
73
+ else
74
+ if 1.0/thr < 1
75
+ str = "#{ Log.color :blue, (1.0/thr).round(2).to_s } secs each"
76
+ elsif 1.0/thr < 2
77
+ str = "#{ Log.color :blue, (1.0/thr).round(1).to_s } secs each"
78
+ else
79
+ str = "#{ Log.color :blue, (1/thr).ceil.to_s } secs each"
80
+ end
81
+ #str << " #{ Log.color :yellow, (1/mean).ceil.to_s } avg. #{Log.color :yellow, (1/@mean_max).ceil.to_s} min." if @mean_max > 0
82
+ end
83
+
84
+ str
85
+ end
86
+
87
+
88
+ def eta_msg
89
+ percent = self.percent
90
+ time = Time.now
91
+
92
+ indicator = ""
93
+ 10.times{|i|
94
+ if i < percent / 10 then
95
+ indicator << Log.color(:yellow, ".")
96
+ else
97
+ indicator << " "
98
+ end
99
+ }
100
+
101
+ indicator << " #{Log.color(:blue, percent.to_s << "%")}"
102
+
103
+ used = time - @start
104
+ if @mean_max and @mean_max > 0 and @mean > 0
105
+ eta = (@max - @ticks) / @mean
106
+ else
107
+ eta = (@max - @ticks) / (@ticks/used)
108
+ end
109
+
110
+ used = Misc.format_seconds(used)
111
+ eta = [eta/3600, eta/60 % 60, eta % 60].map{|t| "%02i" % t }.join(':')
112
+
113
+ #indicator << " #{Log.color :yellow, used} used #{Log.color :yellow, eta} left - #{Log.color :yellow, ticks.to_s} of #{Log.color :yellow, @max.to_s} #{bytes ? 'bytes' : 'items'}"
114
+ indicator << " #{Log.color :yellow, eta} => #{Log.color :yellow, used} - #{Log.color :yellow, ticks.to_s} of #{Log.color :yellow, @max.to_s} #{bytes ? 'bytes' : 'items'}"
115
+
116
+ indicator
117
+ end
118
+
119
+ def report_msg
120
+ str = Log.color(:magenta, "·")
121
+ if @ticks == 0
122
+ if @max
123
+ return str << " " << Log.color(:magenta, "waiting on #{@max} #{bytes ? 'bytes' : 'items'}") << Log.color(:magenta, " · " << desc)
124
+ else
125
+ return str << " " << Log.color(:magenta, "waiting - PID: #{Process.pid}") << Log.color(:magenta, " · " << desc)
126
+ end
127
+ end
128
+ str << " " << thr_msg
129
+ if max
130
+ str << Log.color(:blue, " -- ") << eta_msg
131
+ else
132
+ str << Log.color(:blue, " -- ") << ticks.to_s << " #{bytes ? 'bytes' : 'items'}"
133
+ end
134
+ str << Log.color(:magenta, " · " << desc)
135
+ str
136
+ end
137
+
138
+ def load(info)
139
+ info.each do |key, value|
140
+ case key.to_sym
141
+ when :start
142
+ @start = value
143
+ when :last_time
144
+ @last_time = value
145
+ when :last_count
146
+ @last_count = value
147
+ when :last_percent
148
+ @last_percent = value
149
+ when :desc
150
+ @desc = value
151
+ when :ticks
152
+ @ticks = value
153
+ when :max
154
+ @max = value
155
+ when :mean
156
+ @mean = value
157
+ end
158
+ end
159
+ end
160
+
161
+ def save
162
+ info = {:start => @start, :last_time => @last_time, :last_count => @last_count, :last_percent => @last_percent, :desc => @desc, :ticks => @ticks, :max => @max, :mean => @mean}
163
+ info.delete_if{|k,v| v.nil?}
164
+ FileUtils.mkdir_p File.dirname(file) unless File.exist?(File.dirname(file))
165
+ File.write(file, info.to_yaml)
166
+ end
167
+
168
+ def report(io = STDERR)
169
+ if Log::LAST != "progress"
170
+ bars = BARS
171
+ if Log::LAST == "new_bar"
172
+ Log::LAST.replace "progress"
173
+ bar = bars.sort_by{|b| b.depth }.first
174
+ print(io, Log.color(:magenta ,bar.report_msg) << "\n")
175
+ else
176
+ print(io, Log.color(:magenta, "···Progress\n"))
177
+ bars.sort_by{|b| b.depth }.reverse.each do |bar|
178
+ if SILENCED.include? bar
179
+ print(io, Log.color(:magenta, "·\n"))
180
+ else
181
+ print(io, Log.color(:magenta ,bar.report_msg) << "\n")
182
+ end
183
+ end
184
+ end
185
+ else
186
+ bars = BARS
187
+ end
188
+ bars << self unless BARS.include? self
189
+
190
+ print(io, Log.up_lines(bars.length) << Log.color(:magenta, "···Progress\n") << Log.down_lines(bars.length+1)) if Log::ProgressBar.offset == 0
191
+ print(io, Log.up_lines(@depth) << report_msg << "\n" << Log.down_lines(@depth - 1))
192
+ @last_time = Time.now
193
+ @last_count = ticks
194
+ @last_percent = percent if max and max > 0
195
+ Log::LAST.replace "progress"
196
+ save if file
197
+ end
198
+
199
+ def done(io = STDERR)
200
+ done_msg = Log.color(:magenta, "· ") << Log.color(:green, "done")
201
+ if @start
202
+ ellapsed = (Time.now - @start)
203
+ else
204
+ ellapsed = 0
205
+ end
206
+ ellapsed_str = [ellapsed/3600, ellapsed/60 % 60, ellapsed % 60].map{|t| "%02i" % t }.join(':')
207
+ done_msg << " " << Log.color(:blue, (@ticks).to_s) << " #{bytes ? 'bytes' : 'items'} in " << Log.color(:green, ellapsed_str)
208
+ @last_count = 0
209
+ @last_time = @start
210
+ thr = ellapsed > 0 ? (@ticks / ellapsed).to_i.to_s : 0
211
+ done_msg << " - " << Log.color(:blue, thr) << " per second"
212
+ done_msg << Log.color(:magenta, " · " << desc)
213
+ print(io, Log.up_lines(@depth) << done_msg << Log.down_lines(@depth))
214
+
215
+ FileUtils.rm file if file and File.exist?(file)
216
+
217
+ @callback.call self if @callback
218
+ end
219
+
220
+ def error(io = STDERR)
221
+ done_msg = Log.color(:magenta, "· ") << Log.color(:red, "error")
222
+ if @start
223
+ ellapsed = (Time.now - @start).to_i
224
+ else
225
+ ellapsed = 0
226
+ end
227
+ ellapsed = [ellapsed/3600, ellapsed/60 % 60, ellapsed % 60].map{|t| "%02i" % t }.join(':')
228
+ done_msg << " " << Log.color(:blue, (@ticks).to_s) << " in " << Log.color(:green, ellapsed)
229
+ @last_count = 0
230
+ @last_time = @start
231
+ done_msg << " - " << thr_msg
232
+ done_msg << Log.color(:magenta, " · " << desc)
233
+ print(io, Log.up_lines(@depth) << done_msg << Log.down_lines(@depth))
234
+
235
+ FileUtils.rm file if file and File.exist?(file)
236
+
237
+ begin
238
+ @callback.call self
239
+ rescue
240
+ Log.debug "Callback failed for filed progress bar: #{$!.message}"
241
+ end if @callback
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,173 @@
1
+ require_relative '../../exceptions'
2
+ module Log
3
+ class ProgressBar
4
+ BAR_MUTEX = Mutex.new
5
+ BARS = []
6
+ REMOVE = []
7
+ SILENCED = []
8
+
9
+ def self.add_offset(value = 1)
10
+ value = 1 if TrueClass === value
11
+ @@offset = offset + value.to_i
12
+ @@offset = 0 if @@offset < 0
13
+ @@offset
14
+ end
15
+
16
+ def self.remove_offset(value = 1)
17
+ value = 1 if TrueClass === value
18
+ @@offset = offset - value.to_i
19
+ @@offset = 0 if @@offset < 0
20
+ @@offset
21
+ end
22
+
23
+
24
+ def self.offset
25
+ @@offset ||= 0
26
+ @@offset = 0 if @@offset < 0
27
+ @@offset
28
+ end
29
+
30
+ def self.new_bar(max, options = {})
31
+ options, max = max, nil if Hash === max
32
+ max = options[:max] if options && max.nil?
33
+ cleanup_bars
34
+ BAR_MUTEX.synchronize do
35
+ Log::LAST.replace "new_bar" if Log::LAST == "progress"
36
+ options = IndiferentHash.add_defaults options, :depth => BARS.length + Log::ProgressBar.offset
37
+ BARS << (bar = ProgressBar.new(max, options))
38
+ bar
39
+ end
40
+ end
41
+
42
+ def self.cleanup_bars
43
+ BAR_MUTEX.synchronize do
44
+ REMOVE.each do |bar|
45
+ index = BARS.index bar
46
+ if index
47
+ BARS.delete_at index
48
+ BARS.each_with_index do |bar,i|
49
+ bar.depth = i
50
+ end
51
+ end
52
+ index = SILENCED.index bar
53
+ if index
54
+ SILENCED.delete_at index
55
+ SILENCED.each_with_index do |bar,i|
56
+ bar.depth = i
57
+ end
58
+ end
59
+ end
60
+ REMOVE.clear
61
+ BARS.length
62
+ end
63
+ end
64
+
65
+ def self.remove_bar(bar, error = false)
66
+ BAR_MUTEX.synchronize do
67
+ return if REMOVE.include? bar
68
+ end
69
+ if error
70
+ bar.error if bar.respond_to? :error
71
+ else
72
+ bar.done if bar.respond_to? :done
73
+ end
74
+ BAR_MUTEX.synchronize do
75
+ REMOVE << bar
76
+ end
77
+ cleanup_bars
78
+ Log::LAST.replace "remove_bar" if Log::LAST == "progress"
79
+ end
80
+
81
+ def remove(error = false)
82
+ Log::ProgressBar.remove_bar self, error
83
+ end
84
+
85
+ def self.with_bar(max = nil, options = {})
86
+ bar = options.include?(:bar) ? options[:bar] : new_bar(max, options)
87
+ begin
88
+ error = false
89
+ keep = false
90
+ yield bar
91
+ rescue KeepBar
92
+ keep = true
93
+ rescue
94
+ error = true
95
+ raise $!
96
+ ensure
97
+ remove_bar(bar, error) if bar && ! keep
98
+ end
99
+ end
100
+
101
+ def self.guess_obj_max(obj)
102
+ begin
103
+ case obj
104
+ when (defined? Step and Step)
105
+ if obj.done?
106
+ path = obj.path
107
+ path = path.find if path.respond_to? :find
108
+ if File.exist? path
109
+ CMD.cmd("wc -l '#{path}'").read.to_i
110
+ else
111
+ nil
112
+ end
113
+ else
114
+ nil
115
+ end
116
+ when TSV
117
+ obj.length
118
+ when Array, Hash
119
+ obj.size
120
+ when File
121
+ return nil if Open.gzip?(obj.filename) or Open.bgzip?(obj.filename) or Open.remote?(obj.filename)
122
+ CMD.cmd("wc -l '#{obj.filename}'").read.to_i
123
+ when Path, String
124
+ obj = obj.find if Path === obj
125
+ if File.exist? obj
126
+ return nil if Open.gzip?(obj) or Open.bgzip?(obj)
127
+ CMD.cmd("wc -l '#{obj}'").read.to_i
128
+ else
129
+ nil
130
+ end
131
+ end
132
+ rescue Interrupt
133
+ raise $!
134
+ rescue Exception
135
+ nil
136
+ end
137
+ end
138
+
139
+ def self.get_obj_bar(obj, bar = nil)
140
+ return nil if bar.nil? || bar == false
141
+ case bar
142
+ when String
143
+ max = guess_obj_max(obj)
144
+ Log::ProgressBar.new_bar(max, {:desc => bar})
145
+ when TrueClass
146
+ max = guess_obj_max(obj)
147
+ Log::ProgressBar.new_bar(max)
148
+ when Numeric
149
+ max = guess_obj_max(obj)
150
+ Log::ProgressBar.new_bar(bar)
151
+ when Hash
152
+ max = IndiferentHash.process_options(bar, :max) || max
153
+ Log::ProgressBar.new_bar(max, bar)
154
+ when Log::ProgressBar
155
+ bar.max ||= guess_obj_max(obj)
156
+ bar
157
+ else
158
+ if (defined? Step and Step === bar)
159
+ max = guess_obj_max(obj)
160
+ Log::ProgressBar.new_bar(max, {:desc => bar.status, :file => bar.file(:progress)})
161
+ else
162
+ bar
163
+ end
164
+ end
165
+ end
166
+
167
+ def self.with_obj_bar(obj, bar = true, &block)
168
+ bar = get_obj_bar(obj, bar)
169
+ with_bar nil, bar: bar, &block
170
+ end
171
+ end
172
+ end
173
+
@@ -0,0 +1,106 @@
1
+ require_relative 'progress/util'
2
+ require_relative 'progress/report'
3
+ module Log
4
+
5
+ def self.no_bar=(value)
6
+ @@no_bar = value
7
+ end
8
+
9
+ def self.no_bar
10
+ @@no_bar = false unless defined?(@@no_bar)
11
+ @@no_bar || ENV["SCOUT_NO_PROGRESS"] == "true"
12
+ end
13
+
14
+ class ProgressBar
15
+
16
+ class << self
17
+ attr_accessor :default_file
18
+ attr_accessor :default_severity
19
+ end
20
+
21
+ attr_accessor :max, :ticks, :frequency, :depth, :desc, :file, :bytes, :process, :callback, :severity
22
+
23
+ def initialize(max = nil, options = {})
24
+ depth, desc, file, bytes, frequency, process, callback, severity =
25
+ IndiferentHash.process_options options, :depth, :desc, :file, :bytes, :frequency, :process, :callback, :severity,
26
+ :depth => 0, :frequency => 2, :severity => Log::ProgressBar.default_severity
27
+
28
+ max = nil if TrueClass === max
29
+
30
+ @max = max
31
+ @ticks = 0
32
+ @frequency = frequency
33
+ @severity = severity
34
+ @last_time = nil
35
+ @last_count = nil
36
+ @last_percent = nil
37
+ @depth = depth
38
+ @desc = desc.nil? ? "" : desc.gsub(/\n/,' ')
39
+ @file = file
40
+ @bytes = bytes
41
+ @process = process
42
+ @callback = callback
43
+ end
44
+
45
+ def percent
46
+ return 0 if @ticks == 0
47
+ return 100 if @max == 0
48
+ (@ticks * 100) / @max
49
+ end
50
+
51
+ def file
52
+ @file || ProgressBar.default_file
53
+ end
54
+
55
+ def init
56
+ @ticks, @bytes = 0
57
+ @last_time = @last_count = @last_percent = nil
58
+ @history, @mean_max, @max_history = nil
59
+ @start = @last_time = Time.now
60
+ @last_count = 0
61
+ report
62
+ end
63
+
64
+ def tick(step = 1)
65
+ return if Log.no_bar
66
+ @ticks += step
67
+
68
+ time = Time.now
69
+ if @last_time.nil?
70
+ @last_time = time
71
+ @last_count = @ticks
72
+ @start = time
73
+ return
74
+ end
75
+
76
+ diff = time - @last_time
77
+ report and return if diff >= @frequency
78
+ return unless max and max > 0
79
+
80
+ percent = self.percent
81
+ if @last_percent.nil?
82
+ @last_percent = percent
83
+ return
84
+ end
85
+ report && return if percent > @last_percent and diff > 0.3
86
+ end
87
+
88
+ def pos(pos)
89
+ step = pos - (@ticks || 0)
90
+ tick(step)
91
+ end
92
+
93
+ def process(elem)
94
+ case res = @process.call(elem)
95
+ when FalseClass
96
+ nil
97
+ when TrueClass
98
+ tick
99
+ when Integer
100
+ pos(res)
101
+ when Float
102
+ pos(res * max)
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,107 @@
1
+ module Log
2
+ def self.trap_std(msg = "STDOUT", msge = "STDERR", severity = 0, severity_err = nil)
3
+ sout, sin = Open.pipe
4
+ soute, sine = Open.pipe
5
+ backup_stderr = STDERR.dup
6
+ backup_stdout = STDOUT.dup
7
+ old_logfile = Log.logfile
8
+ Log.logfile(backup_stderr)
9
+
10
+ severity_err ||= severity
11
+ th_log = Thread.new do
12
+ while line = sout.gets
13
+ Log.logn "#{msg}: " + line, severity
14
+ end
15
+ end
16
+
17
+ th_loge = Thread.new do
18
+ while line = soute.gets
19
+ Log.logn "#{msge}: " + line, severity_err
20
+ end
21
+ end
22
+
23
+ begin
24
+ STDOUT.reopen(sin)
25
+ STDERR.reopen(sine)
26
+ yield
27
+ ensure
28
+ STDERR.reopen backup_stderr
29
+ STDOUT.reopen backup_stdout
30
+ sin.close
31
+ sine.close
32
+ th_log.join
33
+ th_loge.join
34
+ backup_stdout.close
35
+ backup_stderr.close
36
+ Log.logfile = old_logfile
37
+ end
38
+ end
39
+
40
+ def self.trap_stderr(msg = "STDERR", severity = 0)
41
+ sout, sin = Open.pipe
42
+ backup_stderr = STDERR.dup
43
+ old_logfile = Log.logfile
44
+ Log.logfile(backup_stderr)
45
+
46
+ th_log = Thread.new do
47
+ while line = sout.gets
48
+ Log.logn "#{msg}: " + line, severity
49
+ end
50
+ end
51
+
52
+ begin
53
+ STDERR.reopen(sin)
54
+ yield
55
+ sin.close
56
+ ensure
57
+ STDERR.reopen backup_stderr
58
+ th_log.join
59
+ backup_stderr.close
60
+ Log.logfile = old_logfile
61
+ end
62
+ end
63
+
64
+ def self._ignore_stderr
65
+ begin
66
+ File.open('/dev/null', 'w') do |f|
67
+ backup_stderr = STDERR.dup
68
+ STDERR.reopen(f)
69
+ begin
70
+ yield
71
+ ensure
72
+ STDERR.reopen backup_stderr
73
+ backup_stderr.close
74
+ end
75
+ end
76
+ rescue Errno::ENOENT
77
+ yield
78
+ end
79
+ end
80
+
81
+
82
+ def self.ignore_stderr(&block)
83
+ _ignore_stderr &block
84
+ end
85
+
86
+ def self._ignore_stdout
87
+ begin
88
+ File.open('/dev/null', 'w') do |f|
89
+ backup_stdout = STDOUT.dup
90
+ STDOUT.reopen(f)
91
+ begin
92
+ yield
93
+ ensure
94
+ STDOUT.reopen backup_stdout
95
+ backup_stdout.close
96
+ end
97
+ end
98
+ rescue Errno::ENOENT
99
+ yield
100
+ end
101
+ end
102
+
103
+
104
+ def self.ignore_stdout(&block)
105
+ _ignore_stdout &block
106
+ end
107
+ end