scout-essentials 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.vimproject +78 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/lib/scout/cmd.rb +348 -0
- data/lib/scout/concurrent_stream.rb +284 -0
- data/lib/scout/config.rb +168 -0
- data/lib/scout/exceptions.rb +77 -0
- data/lib/scout/indiferent_hash/case_insensitive.rb +30 -0
- data/lib/scout/indiferent_hash/options.rb +115 -0
- data/lib/scout/indiferent_hash.rb +96 -0
- data/lib/scout/log/color.rb +224 -0
- data/lib/scout/log/color_class.rb +269 -0
- data/lib/scout/log/fingerprint.rb +69 -0
- data/lib/scout/log/progress/report.rb +244 -0
- data/lib/scout/log/progress/util.rb +173 -0
- data/lib/scout/log/progress.rb +106 -0
- data/lib/scout/log/trap.rb +107 -0
- data/lib/scout/log.rb +441 -0
- data/lib/scout/meta_extension.rb +100 -0
- data/lib/scout/misc/digest.rb +63 -0
- data/lib/scout/misc/filesystem.rb +25 -0
- data/lib/scout/misc/format.rb +255 -0
- data/lib/scout/misc/helper.rb +31 -0
- data/lib/scout/misc/insist.rb +56 -0
- data/lib/scout/misc/monitor.rb +66 -0
- data/lib/scout/misc/system.rb +73 -0
- data/lib/scout/misc.rb +10 -0
- data/lib/scout/named_array.rb +138 -0
- data/lib/scout/open/lock/lockfile.rb +587 -0
- data/lib/scout/open/lock.rb +68 -0
- data/lib/scout/open/remote.rb +135 -0
- data/lib/scout/open/stream.rb +491 -0
- data/lib/scout/open/util.rb +244 -0
- data/lib/scout/open.rb +170 -0
- data/lib/scout/path/find.rb +204 -0
- data/lib/scout/path/tmpfile.rb +8 -0
- data/lib/scout/path/util.rb +127 -0
- data/lib/scout/path.rb +51 -0
- data/lib/scout/persist/open.rb +17 -0
- data/lib/scout/persist/path.rb +15 -0
- data/lib/scout/persist/serialize.rb +157 -0
- data/lib/scout/persist.rb +104 -0
- data/lib/scout/resource/open.rb +8 -0
- data/lib/scout/resource/path.rb +80 -0
- data/lib/scout/resource/produce/rake.rb +69 -0
- data/lib/scout/resource/produce.rb +151 -0
- data/lib/scout/resource/scout.rb +3 -0
- data/lib/scout/resource/software.rb +178 -0
- data/lib/scout/resource/util.rb +59 -0
- data/lib/scout/resource.rb +40 -0
- data/lib/scout/simple_opt/accessor.rb +54 -0
- data/lib/scout/simple_opt/doc.rb +126 -0
- data/lib/scout/simple_opt/get.rb +57 -0
- data/lib/scout/simple_opt/parse.rb +67 -0
- data/lib/scout/simple_opt/setup.rb +26 -0
- data/lib/scout/simple_opt.rb +5 -0
- data/lib/scout/tmpfile.rb +129 -0
- data/lib/scout-essentials.rb +10 -0
- data/scout-essentials.gemspec +143 -0
- data/share/color/color_names +507 -0
- data/share/color/diverging_colors.hex +12 -0
- data/share/software/install_helpers +523 -0
- data/test/scout/indiferent_hash/test_case_insensitive.rb +16 -0
- data/test/scout/indiferent_hash/test_options.rb +46 -0
- data/test/scout/log/test_color.rb +0 -0
- data/test/scout/log/test_progress.rb +108 -0
- data/test/scout/misc/test_digest.rb +30 -0
- data/test/scout/misc/test_filesystem.rb +30 -0
- data/test/scout/misc/test_insist.rb +13 -0
- data/test/scout/misc/test_system.rb +21 -0
- data/test/scout/open/test_lock.rb +52 -0
- data/test/scout/open/test_remote.rb +25 -0
- data/test/scout/open/test_stream.rb +676 -0
- data/test/scout/open/test_util.rb +73 -0
- data/test/scout/path/test_find.rb +110 -0
- data/test/scout/path/test_util.rb +22 -0
- data/test/scout/persist/test_open.rb +37 -0
- data/test/scout/persist/test_path.rb +37 -0
- data/test/scout/persist/test_serialize.rb +114 -0
- data/test/scout/resource/test_path.rb +58 -0
- data/test/scout/resource/test_produce.rb +94 -0
- data/test/scout/resource/test_software.rb +24 -0
- data/test/scout/resource/test_util.rb +38 -0
- data/test/scout/simple_opt/test_doc.rb +16 -0
- data/test/scout/simple_opt/test_get.rb +11 -0
- data/test/scout/simple_opt/test_parse.rb +10 -0
- data/test/scout/simple_opt/test_setup.rb +77 -0
- data/test/scout/test_cmd.rb +85 -0
- data/test/scout/test_concurrent_stream.rb +29 -0
- data/test/scout/test_config.rb +66 -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 +80 -0
- data/test/scout/test_misc.rb +6 -0
- data/test/scout/test_named_array.rb +43 -0
- data/test/scout/test_open.rb +146 -0
- data/test/scout/test_path.rb +54 -0
- data/test/scout/test_persist.rb +186 -0
- data/test/scout/test_resource.rb +26 -0
- data/test/scout/test_tmpfile.rb +53 -0
- data/test/test_helper.rb +50 -0
- metadata +247 -0
@@ -0,0 +1,255 @@
|
|
1
|
+
module Misc
|
2
|
+
COLOR_LIST = %w(#BC80BD #CCEBC5 #FFED6F #8DD3C7 #FFFFB3 #BEBADA #FB8072 #80B1D3 #FDB462 #B3DE69 #FCCDE5 #D9D9D9)
|
3
|
+
|
4
|
+
def self.colors_for(list)
|
5
|
+
unused = COLOR_LIST.dup
|
6
|
+
|
7
|
+
used = {}
|
8
|
+
colors = list.collect do |elem|
|
9
|
+
if used.include? elem
|
10
|
+
used[elem]
|
11
|
+
else
|
12
|
+
color = unused.shift
|
13
|
+
used[elem]=color
|
14
|
+
color
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
[colors, used]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.format_seconds(time, extended = false)
|
22
|
+
seconds = time.to_i
|
23
|
+
str = [seconds/3600, seconds/60 % 60, seconds % 60].map{|t| "%02i" % t }.join(':')
|
24
|
+
str << ".%02i" % ((time - seconds) * 100) if extended
|
25
|
+
str
|
26
|
+
end
|
27
|
+
|
28
|
+
CHAR_SENCONDS = ENV["SCOUT_NOCOLOR"] == "true" ? "sec" : "″"
|
29
|
+
def self.format_seconds_short(time)
|
30
|
+
if time < 0.0001
|
31
|
+
"%.5g" % time + CHAR_SENCONDS
|
32
|
+
elsif time < 60
|
33
|
+
"%.2g" % time + CHAR_SENCONDS
|
34
|
+
else
|
35
|
+
format_seconds(time)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
MAX_TTY_LINE_WIDTH = 100
|
42
|
+
def self.format_paragraph(text, size = nil, indent = nil, offset = nil)
|
43
|
+
size ||= Log.tty_size || MAX_TTY_LINE_WIDTH
|
44
|
+
size = MAX_TTY_LINE_WIDTH if size > MAX_TTY_LINE_WIDTH
|
45
|
+
indent ||= 0
|
46
|
+
offset ||= 0
|
47
|
+
|
48
|
+
i = 0
|
49
|
+
size = size + offset + indent
|
50
|
+
re = /((?:\n\s*\n\s*)|(?:\n\s*(?=\*)))/
|
51
|
+
text.split(re).collect do |paragraph|
|
52
|
+
i += 1
|
53
|
+
str = if i % 2 == 1
|
54
|
+
words = paragraph.gsub(/\s+/, "\s").split(" ")
|
55
|
+
lines = []
|
56
|
+
line = " "*offset
|
57
|
+
word = words.shift
|
58
|
+
while word
|
59
|
+
word = word[0..size-indent-offset-4] + '...' if word.length >= size - indent - offset
|
60
|
+
while word and Log.uncolor(line).length + Log.uncolor(word).length <= size - indent
|
61
|
+
line << word << " "
|
62
|
+
word = words.shift
|
63
|
+
end
|
64
|
+
offset = 0
|
65
|
+
lines << ((" " * indent) << line[0..-2])
|
66
|
+
line = ""
|
67
|
+
end
|
68
|
+
(lines * "\n")
|
69
|
+
else
|
70
|
+
paragraph
|
71
|
+
end
|
72
|
+
offset = 0
|
73
|
+
str
|
74
|
+
end*""
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.format_definition_list_item(dt, dd, indent = nil, size = nil, color = :yellow)
|
78
|
+
if size.nil?
|
79
|
+
base_size = MAX_TTY_LINE_WIDTH
|
80
|
+
base_indent = indent || (base_size / 3)
|
81
|
+
size = base_size - base_indent
|
82
|
+
end
|
83
|
+
|
84
|
+
indent ||= base_indent || size / 3
|
85
|
+
|
86
|
+
dd = "" if dd.nil?
|
87
|
+
dt = Log.color color, dt if color
|
88
|
+
dt = dt.to_s unless dd.empty?
|
89
|
+
len = Log.uncolor(dt).length
|
90
|
+
|
91
|
+
if indent < 0
|
92
|
+
text = format_paragraph(dd, size, indent.abs-1, 0)
|
93
|
+
text = dt << "\n" << text
|
94
|
+
else
|
95
|
+
offset = len - indent
|
96
|
+
offset = 0 if offset < 0
|
97
|
+
text = format_paragraph(dd, size, indent.abs+1, offset)
|
98
|
+
text[0..len-1] = dt
|
99
|
+
end
|
100
|
+
text
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.format_definition_list(defs, indent = nil, size = nil, color = :yellow, sep = "\n\n")
|
104
|
+
indent ||= 30
|
105
|
+
size ||= (Log.tty_size || MAX_TTY_LINE_WIDTH) - indent
|
106
|
+
entries = []
|
107
|
+
defs.each do |dt,dd|
|
108
|
+
text = format_definition_list_item(dt,dd,indent, size,color)
|
109
|
+
entries << text
|
110
|
+
end
|
111
|
+
entries * sep
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.camel_case(string)
|
115
|
+
return string if string !~ /_/ && string =~ /[A-Z]+.*/
|
116
|
+
string.split(/_|(\d+)/).map{|e|
|
117
|
+
(e =~ /^[A-Z]{2,}$/ ? e : e.capitalize)
|
118
|
+
}.join
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.camel_case_lower(string)
|
122
|
+
string.split('_').inject([]){ |buffer,e|
|
123
|
+
buffer.push(buffer.empty? ? e.downcase : (e =~ /^[A-Z]{2,}$/ ? e : e.capitalize))
|
124
|
+
}.join
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.snake_case(string)
|
128
|
+
return nil if string.nil?
|
129
|
+
string = string.to_s if Symbol === string
|
130
|
+
string.
|
131
|
+
gsub(/([A-Z]{2,})([A-Z][a-z])/,'\1_\2').
|
132
|
+
gsub(/([a-z])([A-Z])/,'\1_\2').
|
133
|
+
gsub(/\s/,'_').gsub(/[^\w]/, '').
|
134
|
+
split("_").collect{|p| p.match(/[A-Z]{2,}/) ? p : p.downcase } * "_"
|
135
|
+
end
|
136
|
+
|
137
|
+
# source: https://gist.github.com/ekdevdes/2450285
|
138
|
+
# author: Ethan Kramer (https://github.com/ekdevdes)
|
139
|
+
def self.humanize(value, options = {})
|
140
|
+
if options.empty?
|
141
|
+
options[:format] = :sentence
|
142
|
+
end
|
143
|
+
|
144
|
+
values = value.to_s.split('_')
|
145
|
+
values.each_index do |index|
|
146
|
+
# lower case each item in array
|
147
|
+
# Miguel Vazquez edit: Except for acronyms
|
148
|
+
values[index].downcase! unless values[index].match(/[a-zA-Z][A-Z]/)
|
149
|
+
end
|
150
|
+
if options[:format] == :allcaps
|
151
|
+
values.each do |value|
|
152
|
+
value.capitalize!
|
153
|
+
end
|
154
|
+
|
155
|
+
if options.empty?
|
156
|
+
options[:seperator] = " "
|
157
|
+
end
|
158
|
+
|
159
|
+
return values.join " "
|
160
|
+
end
|
161
|
+
|
162
|
+
if options[:format] == :class
|
163
|
+
values.each do |value|
|
164
|
+
value.capitalize!
|
165
|
+
end
|
166
|
+
|
167
|
+
return values.join ""
|
168
|
+
end
|
169
|
+
|
170
|
+
if options[:format] == :sentence
|
171
|
+
values[0].capitalize! unless values[0].match(/[a-zA-Z][A-Z]/)
|
172
|
+
|
173
|
+
return values.join " "
|
174
|
+
end
|
175
|
+
|
176
|
+
if options[:format] == :nocaps
|
177
|
+
return values.join " "
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.fixascii(string)
|
182
|
+
if string.respond_to?(:encode)
|
183
|
+
self.fixutf8(string).encode("ASCII-8BIT")
|
184
|
+
else
|
185
|
+
string
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def self.to_utf8(string)
|
190
|
+
string.encode("UTF-16BE", :invalid => :replace, :undef => :replace, :replace => "?").encode('UTF-8')
|
191
|
+
end
|
192
|
+
|
193
|
+
def self.fixutf8(string)
|
194
|
+
return nil if string.nil?
|
195
|
+
return string if string.respond_to?(:encoding) && string.encoding.to_s == "UTF-8" && (string.respond_to?(:valid_encoding?) && string.valid_encoding?) ||
|
196
|
+
(string.respond_to?(:valid_encoding) && string.valid_encoding)
|
197
|
+
|
198
|
+
if string.respond_to?(:encode)
|
199
|
+
string.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
|
200
|
+
else
|
201
|
+
require 'iconv'
|
202
|
+
@@ic ||= Iconv.new('UTF-8//IGNORE', 'UTF-8')
|
203
|
+
@@ic.iconv(string)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.humanize_list(list)
|
208
|
+
return "" if list.empty?
|
209
|
+
if list.length == 1
|
210
|
+
list.first
|
211
|
+
else
|
212
|
+
list[0..-2].collect{|e| e.to_s} * ", " << " and " << list[-1].to_s
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def self.parse_sql_values(txt)
|
217
|
+
io = StringIO.new txt.strip
|
218
|
+
|
219
|
+
values = []
|
220
|
+
fields = []
|
221
|
+
current = nil
|
222
|
+
quoted = false
|
223
|
+
while c = io.getc
|
224
|
+
if quoted
|
225
|
+
if c == "'"
|
226
|
+
quoted = false
|
227
|
+
else
|
228
|
+
current << c
|
229
|
+
end
|
230
|
+
else
|
231
|
+
case c
|
232
|
+
when "("
|
233
|
+
current = ""
|
234
|
+
when ")"
|
235
|
+
fields << current
|
236
|
+
values << fields
|
237
|
+
fields = []
|
238
|
+
current = nil
|
239
|
+
when ','
|
240
|
+
if not current.nil?
|
241
|
+
fields << current
|
242
|
+
current = ""
|
243
|
+
end
|
244
|
+
when "'"
|
245
|
+
quoted = true
|
246
|
+
when ";"
|
247
|
+
break
|
248
|
+
else
|
249
|
+
current << c
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
values
|
254
|
+
end
|
255
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Misc
|
2
|
+
def self.intersect_sorted_arrays(a1, a2)
|
3
|
+
e1, e2 = a1.shift, a2.shift
|
4
|
+
intersect = []
|
5
|
+
while true
|
6
|
+
break if e1.nil? or e2.nil?
|
7
|
+
case e1 <=> e2
|
8
|
+
when 0
|
9
|
+
intersect << e1
|
10
|
+
e1, e2 = a1.shift, a2.shift
|
11
|
+
when -1
|
12
|
+
e1 = a1.shift while not e1.nil? and e1 < e2
|
13
|
+
when 1
|
14
|
+
e2 = a2.shift
|
15
|
+
e2 = a2.shift while not e2.nil? and e2 < e1
|
16
|
+
end
|
17
|
+
end
|
18
|
+
intersect
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.counts(array)
|
22
|
+
counts = {}
|
23
|
+
array.each do |e|
|
24
|
+
counts[e] ||= 0
|
25
|
+
counts[e] += 1
|
26
|
+
end
|
27
|
+
|
28
|
+
counts
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Misc
|
2
|
+
def self.insist(times = 4, sleep = nil, msg = nil)
|
3
|
+
sleep_array = nil
|
4
|
+
|
5
|
+
try = 0
|
6
|
+
begin
|
7
|
+
begin
|
8
|
+
yield
|
9
|
+
rescue Exception
|
10
|
+
if Array === times
|
11
|
+
sleep_array = times
|
12
|
+
times = sleep_array.length
|
13
|
+
sleep = sleep_array.shift
|
14
|
+
end
|
15
|
+
|
16
|
+
if sleep.nil?
|
17
|
+
sleep_array = ([0] + [0.001, 0.01, 0.1, 0.5] * (times / 3)).sort[0..times-1]
|
18
|
+
sleep = sleep_array.shift
|
19
|
+
end
|
20
|
+
raise $!
|
21
|
+
end
|
22
|
+
rescue TryAgain
|
23
|
+
sleep sleep
|
24
|
+
retry
|
25
|
+
rescue StopInsist
|
26
|
+
raise $!.exception
|
27
|
+
rescue Aborted, Interrupt
|
28
|
+
if msg
|
29
|
+
Log.warn("Not Insisting after Aborted: #{$!.message} -- #{msg}")
|
30
|
+
else
|
31
|
+
Log.warn("Not Insisting after Aborted: #{$!.message}")
|
32
|
+
end
|
33
|
+
raise $!
|
34
|
+
rescue Exception
|
35
|
+
Log.exception $! if ENV["SCOUT_LOG_INSIST"] == 'true'
|
36
|
+
if msg
|
37
|
+
Log.warn("Insisting after exception: #{$!.class} #{$!.message} -- #{msg}")
|
38
|
+
elsif FalseClass === msg
|
39
|
+
nil
|
40
|
+
else
|
41
|
+
Log.warn("Insisting after exception: #{$!.class} #{$!.message}")
|
42
|
+
end
|
43
|
+
|
44
|
+
if sleep and try > 0
|
45
|
+
sleep sleep
|
46
|
+
sleep = sleep_array.shift || sleep if sleep_array
|
47
|
+
else
|
48
|
+
Thread.pass
|
49
|
+
end
|
50
|
+
|
51
|
+
try += 1
|
52
|
+
retry if try < times
|
53
|
+
raise $!
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Misc
|
2
|
+
def self.pid_alive?(pid)
|
3
|
+
!! Process.kill(0, pid) rescue false
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.benchmark(repeats = 1, message = nil)
|
7
|
+
require 'benchmark'
|
8
|
+
res = nil
|
9
|
+
begin
|
10
|
+
measure = Benchmark.measure do
|
11
|
+
repeats.times do
|
12
|
+
res = yield
|
13
|
+
end
|
14
|
+
end
|
15
|
+
if message
|
16
|
+
puts "#{message }: #{ repeats } repeats"
|
17
|
+
else
|
18
|
+
puts "Benchmark for #{ repeats } repeats (#{caller.first})"
|
19
|
+
end
|
20
|
+
puts measure
|
21
|
+
rescue Exception
|
22
|
+
puts "Benchmark aborted"
|
23
|
+
raise $!
|
24
|
+
end
|
25
|
+
res
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.profile(options = {})
|
29
|
+
require 'ruby-prof'
|
30
|
+
profiler = RubyProf::Profile.new
|
31
|
+
profiler.start
|
32
|
+
begin
|
33
|
+
res = yield
|
34
|
+
rescue Exception
|
35
|
+
puts "Profiling aborted"
|
36
|
+
raise $!
|
37
|
+
ensure
|
38
|
+
result = profiler.stop
|
39
|
+
printer = RubyProf::FlatPrinter.new(result)
|
40
|
+
printer.print(STDOUT, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
res
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.exec_time(&block)
|
47
|
+
start = Time.now
|
48
|
+
eend = nil
|
49
|
+
begin
|
50
|
+
yield
|
51
|
+
ensure
|
52
|
+
eend = Time.now
|
53
|
+
end
|
54
|
+
eend - start
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.wait_for_interrupt
|
58
|
+
while true
|
59
|
+
begin
|
60
|
+
sleep 1
|
61
|
+
rescue Interrupt
|
62
|
+
break
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Misc
|
2
|
+
|
3
|
+
def self.hostname
|
4
|
+
@@hostname ||= begin
|
5
|
+
`hostname`.strip
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.children(ppid = nil)
|
10
|
+
require 'sys/proctable'
|
11
|
+
|
12
|
+
ppid ||= Process.pid
|
13
|
+
Sys::ProcTable.ps.select{ |pe| pe.ppid == ppid }
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.env_add(var, value, sep = ":", prepend = true)
|
17
|
+
if ENV[var].nil?
|
18
|
+
ENV[var] = value
|
19
|
+
elsif ENV[var] =~ /(#{sep}|^)#{Regexp.quote value}(#{sep}|$)/
|
20
|
+
return
|
21
|
+
else
|
22
|
+
if prepend
|
23
|
+
ENV[var] = value + sep + ENV[var]
|
24
|
+
else
|
25
|
+
ENV[var] += sep + value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.with_env(var, value, &block)
|
31
|
+
old_value = ENV[var]
|
32
|
+
begin
|
33
|
+
ENV[var] = value
|
34
|
+
yield
|
35
|
+
ensure
|
36
|
+
ENV[var] = old_value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.update_git(gem_name = 'scout-gear')
|
41
|
+
gem_name = 'scout-gear' if gem_name.nil?
|
42
|
+
dir = File.join(__dir__, '../../../../', gem_name)
|
43
|
+
return unless Open.exist?(dir)
|
44
|
+
Misc.in_dir dir do
|
45
|
+
begin
|
46
|
+
begin
|
47
|
+
CMD.cmd_log('git pull')
|
48
|
+
rescue
|
49
|
+
raise "Could not update #{gem_name}"
|
50
|
+
end
|
51
|
+
|
52
|
+
begin
|
53
|
+
CMD.cmd_log('git submodule update')
|
54
|
+
rescue
|
55
|
+
raise "Could not update #{gem_name} submodules"
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
begin
|
60
|
+
CMD.cmd_log('rake install')
|
61
|
+
rescue
|
62
|
+
raise "Could not install updated #{gem_name}"
|
63
|
+
end
|
64
|
+
rescue
|
65
|
+
Log.warn $!.message
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.processors
|
71
|
+
Etc.nprocessors
|
72
|
+
end
|
73
|
+
end
|
data/lib/scout/misc.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require_relative 'meta_extension'
|
2
|
+
module NamedArray
|
3
|
+
extend MetaExtension
|
4
|
+
extension_attr :fields, :key
|
5
|
+
|
6
|
+
def self.field_match(field, name)
|
7
|
+
if (String === field) && (String === name)
|
8
|
+
field == name ||
|
9
|
+
field.start_with?(name) || field.include?("(" + name + ")") ||
|
10
|
+
name.start_with?(field) || name.include?("(" + field + ")")
|
11
|
+
else
|
12
|
+
field == name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.identify_name(names, selected, strict: false)
|
17
|
+
res = (Array === selected ? selected : [selected]).collect do |field|
|
18
|
+
case field
|
19
|
+
when nil
|
20
|
+
0
|
21
|
+
when Range
|
22
|
+
field
|
23
|
+
when Integer
|
24
|
+
field
|
25
|
+
when Symbol
|
26
|
+
field == :key ? field : identify_name(names, field.to_s)
|
27
|
+
when (names.nil? and String)
|
28
|
+
if field =~ /^\d+$/
|
29
|
+
identify_field(key_field, fields, field.to_i)
|
30
|
+
else
|
31
|
+
raise "No name information available and specified name not numeric: #{ field }"
|
32
|
+
end
|
33
|
+
when Symbol
|
34
|
+
names.index{|f| f.to_s == field.to_s }
|
35
|
+
when String
|
36
|
+
pos = names.index{|f| f.to_s == field }
|
37
|
+
next pos if pos
|
38
|
+
if field =~ /^\d+$/
|
39
|
+
next identify_names(names, field.to_i)
|
40
|
+
end
|
41
|
+
next pos if strict
|
42
|
+
pos = names.index{|name| field_match(field, name) }
|
43
|
+
next pos if pos
|
44
|
+
nil
|
45
|
+
else
|
46
|
+
raise "Field '#{ Log.fingerprint field }' was not understood. Options: (#{ Log.fingerprint names })"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Array === selected ? res : res.first
|
51
|
+
end
|
52
|
+
|
53
|
+
def identify_name(selected)
|
54
|
+
NamedArray.identify_name(fields, selected)
|
55
|
+
end
|
56
|
+
|
57
|
+
def positions(fields)
|
58
|
+
if Array == fields
|
59
|
+
fields.collect{|field|
|
60
|
+
NamedArray.identify_name(@fields, field)
|
61
|
+
}
|
62
|
+
else
|
63
|
+
NamedArray.identify_name(@fields, fields)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def [](key)
|
68
|
+
pos = NamedArray.identify_name(@fields, key)
|
69
|
+
return nil if pos.nil?
|
70
|
+
super(pos)
|
71
|
+
end
|
72
|
+
|
73
|
+
def concat(other)
|
74
|
+
super(other)
|
75
|
+
self.fields.concat(other.fields) if NamedArray === other
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_hash
|
80
|
+
hash = {}
|
81
|
+
self.fields.zip(self) do |field,value|
|
82
|
+
hash[field] = value
|
83
|
+
end
|
84
|
+
IndiferentHash.setup hash
|
85
|
+
end
|
86
|
+
|
87
|
+
def values_at(*positions)
|
88
|
+
super(*identify_name(positions))
|
89
|
+
end
|
90
|
+
|
91
|
+
def self._zip_fields(array, max = nil)
|
92
|
+
return [] if array.nil? or array.empty? or (first = array.first).nil?
|
93
|
+
|
94
|
+
max = array.collect{|l| l.length }.max if max.nil?
|
95
|
+
|
96
|
+
rest = array[1..-1].collect{|v|
|
97
|
+
v.length == 1 & max > 1 ? v * max : v
|
98
|
+
}
|
99
|
+
|
100
|
+
first = first * max if first.length == 1 and max > 1
|
101
|
+
|
102
|
+
first.zip(*rest)
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.zip_fields(array)
|
106
|
+
if array.length < 10000
|
107
|
+
_zip_fields(array)
|
108
|
+
else
|
109
|
+
zipped_slices = []
|
110
|
+
max = array.collect{|l| l.length}.max
|
111
|
+
array.each_slice(10000) do |slice|
|
112
|
+
zipped_slices << _zip_fields(slice, max)
|
113
|
+
end
|
114
|
+
new = zipped_slices.first
|
115
|
+
zipped_slices[1..-1].each do |rest|
|
116
|
+
rest.each_with_index do |list,i|
|
117
|
+
new[i].concat list
|
118
|
+
end
|
119
|
+
end
|
120
|
+
new
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.add_zipped(source, new)
|
125
|
+
source.zip(new).each do |s,n|
|
126
|
+
s.concat(n)
|
127
|
+
end
|
128
|
+
source
|
129
|
+
end
|
130
|
+
|
131
|
+
def method_missing(name, *args)
|
132
|
+
if identify_name(name)
|
133
|
+
return self[name]
|
134
|
+
else
|
135
|
+
return super(name, *args)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|