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.
- 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
|