scout-essentials 1.0.0

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