duct_tape 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +10 -0
- data/Gemfile.lock +35 -0
- data/LICENSE +25 -0
- data/README.md +223 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/duct_tape.gemspec +106 -0
- data/ext/mkrf_conf.rb +36 -0
- data/git_hooks/env_vars.sh +287 -0
- data/git_hooks/post-commit +43 -0
- data/git_hooks/post-merge +8 -0
- data/git_hooks/pre-commit +273 -0
- data/install_git_hooks +17 -0
- data/lib/algorithms/containers/heap.rb +15 -0
- data/lib/algorithms/containers/priority_queue.rb +11 -0
- data/lib/algorithms/containers.rb +1 -0
- data/lib/duct_tape/autoassociative_array.rb +110 -0
- data/lib/duct_tape.rb +10 -0
- data/lib/ext/array.rb +327 -0
- data/lib/ext/boolean.rb +3 -0
- data/lib/ext/datetime.rb +7 -0
- data/lib/ext/dir.rb +59 -0
- data/lib/ext/file.rb +40 -0
- data/lib/ext/hash.rb +83 -0
- data/lib/ext/kernel.rb +593 -0
- data/lib/ext/numeric.rb +74 -0
- data/lib/ext/object.rb +17 -0
- data/lib/ext/pathname.rb +114 -0
- data/lib/ext/range.rb +7 -0
- data/lib/ext/regexp.rb +12 -0
- data/lib/ext/string.rb +54 -0
- data/lib/ext/symbol.rb +8 -0
- data/lib/ext/time.rb +32 -0
- data/lib/ext/uri.rb +16 -0
- data/spec/algorithms/containers/heap_spec.rb +19 -0
- data/spec/algorithms/containers/priority_queue_spec.rb +19 -0
- data/spec/duct_tape/autoassociative_array_spec.rb +139 -0
- data/spec/ext/array_spec.rb +407 -0
- data/spec/ext/boolean_spec.rb +19 -0
- data/spec/ext/datetime_spec.rb +10 -0
- data/spec/ext/dir_spec.rb +46 -0
- data/spec/ext/file_spec.rb +10 -0
- data/spec/ext/hash_spec.rb +73 -0
- data/spec/ext/kernel_spec.rb +64 -0
- data/spec/ext/numeric_spec.rb +61 -0
- data/spec/ext/object_spec.rb +19 -0
- data/spec/ext/pathname_spec.rb +13 -0
- data/spec/ext/range_spec.rb +10 -0
- data/spec/ext/regexp_spec.rb +10 -0
- data/spec/ext/string_spec.rb +73 -0
- data/spec/ext/symbol_spec.rb +10 -0
- data/spec/ext/time_spec.rb +19 -0
- data/spec/ext/uri_spec.rb +28 -0
- data/spec/spec_helper.rb +7 -0
- metadata +183 -0
data/lib/ext/kernel.rb
ADDED
@@ -0,0 +1,593 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module Kernel
|
5
|
+
private
|
6
|
+
|
7
|
+
def this_method
|
8
|
+
(caller[0..-1].detect { |c| c =~ /`([^']*)'/ } && $1).to_sym
|
9
|
+
rescue NoMethodError
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def calling_method
|
14
|
+
(caller[1..-1].detect { |c| c =~ /`([^']*)'/ } && $1).to_sym
|
15
|
+
rescue NoMethodError
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def calling_method_file(idx=1)
|
20
|
+
c = caller[idx]
|
21
|
+
return nil unless c.rindex(/:\d+(:in `.*')?$/)
|
22
|
+
file = $`
|
23
|
+
return nil if /\A\((.*)\)/ =~ file
|
24
|
+
file
|
25
|
+
end
|
26
|
+
|
27
|
+
def calling_method_dirname(idx=1)
|
28
|
+
found = calling_method_file(idx+1)
|
29
|
+
found.nil? ? found : File.dirname(found)
|
30
|
+
end
|
31
|
+
|
32
|
+
def tty?
|
33
|
+
# TODO For win32: GetUserObjectInformation
|
34
|
+
# TODO For .Net: System.Environment.UserInteractive
|
35
|
+
$stdout.isatty && ((ENV["COLUMNS"] || `stty size 2>&1`.chomp.split(/ /).last).to_i > 0)
|
36
|
+
end
|
37
|
+
|
38
|
+
def tty_width
|
39
|
+
(tty? ? (ENV["COLUMNS"] || `stty size`.chomp.split(/ /).last).to_i : nil)
|
40
|
+
end
|
41
|
+
|
42
|
+
def assert_tty
|
43
|
+
raise "FATAL: This `#{calling_method}' requires an interactive tty" unless tty?
|
44
|
+
end
|
45
|
+
|
46
|
+
def not_implemented(message=nil)
|
47
|
+
raise NotImplementedError, "Method `#{calling_method}' has not been implemented", caller[2..-1]
|
48
|
+
end
|
49
|
+
|
50
|
+
def automatic_require(full_path=nil)
|
51
|
+
some_not_included = true
|
52
|
+
arg_passed = !full_path.nil?
|
53
|
+
type_assert(full_path, String, Array, nil)
|
54
|
+
|
55
|
+
# Discover filename and directory of function that called automatic_require
|
56
|
+
caller_dir = Dir.pwd
|
57
|
+
caller_file_basename = nil
|
58
|
+
if caller_file = calling_method_file
|
59
|
+
caller_dir = File.dirname(caller_file)
|
60
|
+
caller_file_basename = File.basename(caller_file, ".rb")
|
61
|
+
end
|
62
|
+
|
63
|
+
# If nothing was passed, use the basename without ".rb" as the require path
|
64
|
+
if full_path.nil?
|
65
|
+
full_path = Pathname.join([caller_dir, caller_file_basename].compact)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Discover files
|
69
|
+
files = []
|
70
|
+
[*full_path].each do |path|
|
71
|
+
try_these = [
|
72
|
+
Pathname.new(path),
|
73
|
+
Pathname.join([caller_dir, path].compact),
|
74
|
+
Pathname.join([caller_dir, caller_file_basename, path].compact)
|
75
|
+
].uniq
|
76
|
+
try_these.each do |possibility|
|
77
|
+
possibility = possibility.expand_path
|
78
|
+
if possibility.exist?
|
79
|
+
if possibility.file?
|
80
|
+
files |= [possibility.to_s]
|
81
|
+
elsif possibility.directory?
|
82
|
+
files |= Dir[possibility + "*.rb"]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
if files.empty? && arg_passed
|
88
|
+
raise RuntimeError, "No files found to require for #{full_path.inspect}", caller
|
89
|
+
end
|
90
|
+
|
91
|
+
# Require files & return the successful order
|
92
|
+
successful_require_order = []
|
93
|
+
retry_loop = 0
|
94
|
+
last_err = nil
|
95
|
+
while some_not_included and retry_loop <= (files.size ** 2) do
|
96
|
+
begin
|
97
|
+
some_not_included = false
|
98
|
+
for f in files do
|
99
|
+
val = require f
|
100
|
+
some_not_included ||= val
|
101
|
+
successful_require_order << f if val
|
102
|
+
end
|
103
|
+
rescue NameError => e
|
104
|
+
last_err = e
|
105
|
+
raise unless "#{e}" =~ /uninitialized constant|undefined method/i
|
106
|
+
some_not_included = true
|
107
|
+
files.push(files.shift)
|
108
|
+
end
|
109
|
+
retry_loop += 1
|
110
|
+
end
|
111
|
+
if some_not_included
|
112
|
+
warn "Couldn't auto-include all files in #{full_path.inspect}"
|
113
|
+
warn "#{last_err}"
|
114
|
+
raise last_err
|
115
|
+
end
|
116
|
+
successful_require_order
|
117
|
+
end
|
118
|
+
|
119
|
+
def type_assert(var, *klasses)
|
120
|
+
klasses.each { |k| return if k === var }
|
121
|
+
raise TypeError, "can't convert #{var.inspect}:#{var.class} into #{klasses.join(' or ')}", caller
|
122
|
+
end
|
123
|
+
|
124
|
+
alias_method :silence_warnings, :disable_warnings
|
125
|
+
|
126
|
+
# Detect the OS we're running on.
|
127
|
+
def detect_os
|
128
|
+
@@os_features ||= nil
|
129
|
+
return @@os_features if @@os_features
|
130
|
+
@@os_features ||= {}
|
131
|
+
|
132
|
+
# Mac Miner
|
133
|
+
mac_miner = lambda do
|
134
|
+
version = `sw_vers -productVersion`.match(/\d+\.\d+\.\d+/)[0]
|
135
|
+
@@os_features.merge!({
|
136
|
+
:platform => "darwin",
|
137
|
+
:os_distro => "Mac OSX",
|
138
|
+
:os_version => version,
|
139
|
+
:os_nickname => case version
|
140
|
+
when /^10.0/; "Cheetah"
|
141
|
+
when /^10.1/; "Puma"
|
142
|
+
when /^10.2/; "Jaguar"
|
143
|
+
when /^10.3/; "Panther"
|
144
|
+
when /^10.4/; "Tiger"
|
145
|
+
when /^10.5/; "Leopard"
|
146
|
+
when /^10.6/; "Snow Leopard"
|
147
|
+
when /^10.7/; "Lion"
|
148
|
+
when /^10.8/; "Mountain Lion"
|
149
|
+
else; "Unknown Version of OSX"
|
150
|
+
end,
|
151
|
+
:install_method => "install",
|
152
|
+
:hostname => `hostname`.chomp,
|
153
|
+
})
|
154
|
+
if Pathname.which("brew")
|
155
|
+
@@os_features[:install_cmd] = "brew install"
|
156
|
+
elsif Pathname.which("port")
|
157
|
+
@@os_features[:install_cmd] = "port install"
|
158
|
+
else
|
159
|
+
@@os_features[:install_method] = "build"
|
160
|
+
end
|
161
|
+
@@os_features
|
162
|
+
end
|
163
|
+
|
164
|
+
# Linux Miner
|
165
|
+
linux_miner = lambda do
|
166
|
+
# Ensure LSB is installed
|
167
|
+
if not Pathname.which("lsb_release")
|
168
|
+
pkg_mgrs = {
|
169
|
+
"apt-get" => "install -y lsb", # Debian/Ubuntu/Linux Mint/PCLinuxOS
|
170
|
+
"up2date" => "-i lsb", # RHEL/Oracle
|
171
|
+
"yum" => "install -y lsb", # CentOS/Fedora/RHEL/Oracle
|
172
|
+
"zypper" => "--non-interactive install lsb", # OpenSUSE/SLES
|
173
|
+
"pacman" => "-S --noconfirm lsb-release", # ArchLinux
|
174
|
+
"urpmi" => "--auto lsb-release", # Mandriva/Mageia
|
175
|
+
"emerge" => "lsb_release", # Gentoo
|
176
|
+
"slackpkg" => "", # Slackware NOTE - doesn't have lsb
|
177
|
+
}
|
178
|
+
ret = false
|
179
|
+
pkg_mgrs.each do |mgr,args|
|
180
|
+
if Pathname.which(mgr)
|
181
|
+
if mgr == "slackpkg" && File.exists?("/etc/slackware-version")
|
182
|
+
ret = true
|
183
|
+
else
|
184
|
+
ret = system("sudo #{mgr} #{args}")
|
185
|
+
end
|
186
|
+
break if ret
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
arch_family = `arch 2> /dev/null`.chomp
|
192
|
+
pkg_arch = arch_family
|
193
|
+
install_method = "install"
|
194
|
+
if File.exists?("/etc/slackware-version") || Pathname.which("slackpkg")
|
195
|
+
# Slackware
|
196
|
+
nickname = File.read("/etc/slackware-version").strip
|
197
|
+
version = nickname.split[1..-1].join(" ")
|
198
|
+
major_release = version.to_i
|
199
|
+
distro = "Slackware"
|
200
|
+
pkg_fmt = major_release < 13 ? "tgz" : "txz"
|
201
|
+
install = "slackpkg -batch=on -default_answer=y install"
|
202
|
+
local_install = "installpkg"
|
203
|
+
elsif File.exists?("/etc/oracle-release") || File.exists?("/etc/enterprise-release")
|
204
|
+
if File.exists?("/etc/oracle-release")
|
205
|
+
nickname = File.read("/etc/oracle-release").strip
|
206
|
+
else
|
207
|
+
nickname = File.read("/etc/enterprise-release").strip
|
208
|
+
end
|
209
|
+
version = nickname.match(/\d+(\.\d+)?/)[0]
|
210
|
+
major_release = version.to_i
|
211
|
+
distro, pkg_fmt, install, local_install = "Oracle", "rpm", "up2date -i", "rpm -Uvh"
|
212
|
+
else
|
213
|
+
version = `lsb_release -r 2> /dev/null`.strip.split[1..-1].join(" ")
|
214
|
+
major_release = version.to_i
|
215
|
+
nickname = `lsb_release -c 2> /dev/null`.strip.split[1..-1].join(" ")
|
216
|
+
lsb_release_output = `lsb_release -a 2> /dev/null`.chomp
|
217
|
+
distro, pkg_fmt, install, local_install = case lsb_release_output
|
218
|
+
when /(debian|ubuntu|mint)/i
|
219
|
+
pkg_arch = "amd64" if arch_family == "x86_64"
|
220
|
+
[$1, "deb", "apt-get install -y", "dpkg -i"]
|
221
|
+
when /(centos|fedora)/i
|
222
|
+
[$1, "rpm", "yum install -y", "yum localinstall -y"]
|
223
|
+
when /oracle/i
|
224
|
+
["Oracle", "rpm", "up2date -i", "rpm -Uvh"]
|
225
|
+
when /redhat|rhel/i
|
226
|
+
["RHEL", "rpm", "up2date -i", "rpm -Uvh"]
|
227
|
+
when /open\s*suse/i
|
228
|
+
["OpenSUSE", "rpm", "zypper --non-interactive install", "rpm -Uvh"]
|
229
|
+
when /suse.*enterprise/i
|
230
|
+
["SLES", "rpm", "zypper --non-interactive install", "rpm -Uvh"]
|
231
|
+
when /archlinux/i
|
232
|
+
["ArchLinux", "pkg.tar.xz", "pacman -S --noconfirm", "pacman -U --noconfirm"]
|
233
|
+
when /(mandriva|mageia)/i
|
234
|
+
[$1, "rpm", "urpmi --auto ", "rpm -Uvh"]
|
235
|
+
when /pc\s*linux\s*os/i
|
236
|
+
["PCLinuxOS", "rpm", "apt-get install -y", "rpm -Uvh"]
|
237
|
+
when /gentoo/i
|
238
|
+
["Gentoo", "tgz", "emerge", ""]
|
239
|
+
else
|
240
|
+
install_method = "build"
|
241
|
+
[`lsb_release -d 2> /dev/null`.strip.split[1..-1].join(" ")]
|
242
|
+
end
|
243
|
+
end
|
244
|
+
ret = {
|
245
|
+
:platform => "linux",
|
246
|
+
:os_distro => distro,
|
247
|
+
:pkg_format => pkg_fmt,
|
248
|
+
:pkg_arch => pkg_arch,
|
249
|
+
:os_version => version,
|
250
|
+
:install_method => install_method,
|
251
|
+
:install_cmd => install,
|
252
|
+
:local_install_cmd => local_install,
|
253
|
+
:os_nickname => nickname,
|
254
|
+
:hostname => `hostname`.chomp,
|
255
|
+
}
|
256
|
+
ret.reject! { |k,v| v.nil? }
|
257
|
+
@@os_features.merge!(ret)
|
258
|
+
end
|
259
|
+
|
260
|
+
# Solaris Miner
|
261
|
+
solaris_miner = lambda do
|
262
|
+
distro = `uname -a`.match(/(open\s*)?(solaris)/i)[1..-1].compact.map { |s| s.capitalize }.join
|
263
|
+
version = `uname -r`.strip
|
264
|
+
nickname = "#{distro} #{version.split('.')[-1]}"
|
265
|
+
if distro == "OpenSolaris"
|
266
|
+
nickname = File.read("/etc/release").match(/OpenSolaris [a-zA-Z0-9.]\+/i)[0].strip
|
267
|
+
end
|
268
|
+
@@os_features.merge!({
|
269
|
+
:platform => "solaris",
|
270
|
+
:os_distro => distro,
|
271
|
+
:os_version => version,
|
272
|
+
:install_method => "install",
|
273
|
+
:install_cmd => "pkg install",
|
274
|
+
:os_nickname => nickname,
|
275
|
+
:hostname => `hostname`.chomp,
|
276
|
+
})
|
277
|
+
end
|
278
|
+
|
279
|
+
# *BSD Miner
|
280
|
+
bsd_miner = lambda do
|
281
|
+
distro = `uname -s`.strip
|
282
|
+
version = `uname -r`.strip
|
283
|
+
@@os_features.merge!({
|
284
|
+
:platform => "bsd",
|
285
|
+
:os_distro => distro,
|
286
|
+
:os_version => version,
|
287
|
+
:install_method => "install",
|
288
|
+
:install_cmd => "pkg_add -r",
|
289
|
+
:os_nickname => "#{distro} #{version}",
|
290
|
+
:hostname => `hostname`.chomp,
|
291
|
+
})
|
292
|
+
end
|
293
|
+
|
294
|
+
# BeOS Miner
|
295
|
+
beos_miner = lambda do
|
296
|
+
version = `uname -r`.strip
|
297
|
+
distro = `uname -s`.strip
|
298
|
+
@@os_features.merge!({
|
299
|
+
:platform => "beos",
|
300
|
+
:os_distro => distro,
|
301
|
+
:os_version => version,
|
302
|
+
:install_method => "build",
|
303
|
+
:os_nickname => "#{distro} #{version}",
|
304
|
+
:hostname => `hostname`.chomp,
|
305
|
+
})
|
306
|
+
end
|
307
|
+
|
308
|
+
# Windows Miner
|
309
|
+
windows_miner = lambda do
|
310
|
+
sysinfo = `reg query "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"`.chomp
|
311
|
+
|
312
|
+
hostname = `reg query "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\ComputerName\\ComputerName"`.chomp
|
313
|
+
hostname = hostname.match(/^\s*ComputerName\s+\w+\s+(.*)/i)[1].strip
|
314
|
+
|
315
|
+
version = sysinfo.match(/^\s*CurrentVersion\s+\w+\s+(.*)/i)[1].strip << "."
|
316
|
+
version << sysinfo.match(/^\s*CurrentBuildNumber\s+\w+\s+(.*)/i)[1].strip
|
317
|
+
|
318
|
+
nickname = sysinfo.match(/^\s*ProductName\s+\w+\s+(.*)/i)[1].strip
|
319
|
+
nickname = "Microsoft #{nickname}" unless nickname =~ /^Microsoft/
|
320
|
+
|
321
|
+
try_boot_ini = `type C:\\boot.ini 2> nul | findstr /C:"WINDOWS="`.chomp
|
322
|
+
unless try_boot_ini.empty?
|
323
|
+
nickname = try_boot_ini.match(/WINDOWS="([^"]+)"/i)[1].strip
|
324
|
+
end
|
325
|
+
@@os_features.merge!({
|
326
|
+
:os_distro => nickname.split(/\s+/).reject { |s| s =~ /microsoft|windows/i }.join(" "),
|
327
|
+
:hostname => hostname,
|
328
|
+
:os_nickname => nickname,
|
329
|
+
:os_version => version,
|
330
|
+
:platform => "windows",
|
331
|
+
:install_method => "install",
|
332
|
+
:install_cmd => "install",
|
333
|
+
})
|
334
|
+
end
|
335
|
+
|
336
|
+
case ::RbConfig::CONFIG['host_os'].downcase
|
337
|
+
when /darwin/; mac_miner[]
|
338
|
+
when /mswin|mingw/; windows_miner[]
|
339
|
+
when /linux/; linux_miner[]
|
340
|
+
when /bsd/; bsd_miner[]
|
341
|
+
when /solaris/; solaris_miner[]
|
342
|
+
else
|
343
|
+
case `uname -s`.chomp.downcase
|
344
|
+
when /linux/; linux_miner[]
|
345
|
+
when /darwin/; mac_miner[]
|
346
|
+
when /solaris/; solaris_miner[]
|
347
|
+
when /bsd/; bsd_miner[]
|
348
|
+
when /dragonfly/; bsd_miner[]
|
349
|
+
when /haiku/; beos_miner[]
|
350
|
+
when /beos/; beos_miner[]
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
@@os_features.freeze
|
355
|
+
end
|
356
|
+
|
357
|
+
# Detect machine details
|
358
|
+
def detect_hardware
|
359
|
+
@@machine_details ||= nil
|
360
|
+
return @@machine_details if @@machine_details
|
361
|
+
|
362
|
+
# Processor Architecture Miner
|
363
|
+
proc_arch_miner = lambda do |stderr_redirect|
|
364
|
+
cmds = [
|
365
|
+
%<arch %s>, # Linux
|
366
|
+
%<lscpu %s | grep -i "Architecture" | awk '{print $2}'>, # Linux Alternative
|
367
|
+
%<uname -p %s>, # BSD-like
|
368
|
+
%<uname -m %s>, # BSD-like Alternate
|
369
|
+
%<reg query "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment" %s>, # Windows
|
370
|
+
%<sysinfo %s | grep -o "kernel_\\w*">, # Haiku
|
371
|
+
]
|
372
|
+
arch_str = nil
|
373
|
+
cmds.each do |cmd|
|
374
|
+
begin
|
375
|
+
arch_str = case `#{cmd % stderr_redirect}`.strip.downcase
|
376
|
+
when /sparc|sun4u/; "sparc"
|
377
|
+
when /ppc|powerpc/; "powerpc"
|
378
|
+
when /mips/; "mips"
|
379
|
+
when /s390/; "s390x"
|
380
|
+
when /ia64|itanium/; "itanium"
|
381
|
+
when /(x|x?(?:86_)|amd)64/; "x86_64"
|
382
|
+
when /(i[3-6]?|x)86|ia32/; "i386"
|
383
|
+
when /arm/; "arm"
|
384
|
+
end
|
385
|
+
break if arch_str
|
386
|
+
rescue Errno::ENOENT => e
|
387
|
+
end
|
388
|
+
end
|
389
|
+
arch_str
|
390
|
+
end
|
391
|
+
|
392
|
+
# Processor (core) Count Miner
|
393
|
+
proc_count_miner = lambda do |stderr_redirect|
|
394
|
+
cmds = [
|
395
|
+
%<cat /proc/cpuinfo %s | grep processor | wc -l>, # Linux
|
396
|
+
%<lscpu %s | grep -i "^CPU(s):" | awk '{print $2}'>, # Linux Alternative
|
397
|
+
%<sysctl -a %s | egrep -i "hw.ncpu" | awk '{print $2}'>, # FreeBSD
|
398
|
+
%<psrinfo %s | wc -l>, # Solaris
|
399
|
+
%<reg query "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment" %s | findstr /C:"NUMBER_OF_PROCESSORS">, # Windows
|
400
|
+
%<sysinfo %s | grep -i "CPU #[0-9]*:" | wc -l>, # Haiku
|
401
|
+
]
|
402
|
+
n_cpus = 0
|
403
|
+
cmds.each do |cmd|
|
404
|
+
begin
|
405
|
+
n_cpus = `#{cmd % stderr_redirect}`.strip.match(/\d+$/)[0].to_i
|
406
|
+
break if n_cpus > 0
|
407
|
+
rescue Errno::ENOENT, NoMethodError
|
408
|
+
end
|
409
|
+
end
|
410
|
+
n_cpus
|
411
|
+
end
|
412
|
+
|
413
|
+
# Physical Memory Size Miner
|
414
|
+
mem_size_miner = lambda do |stderr_redirect|
|
415
|
+
cmds = [
|
416
|
+
%<free -ob %s | grep "Mem:" | awk '{print $2}'>, # Linux
|
417
|
+
%<sysctl -a %s | grep hw.physmem>, # FreeBSD, Mac OSX
|
418
|
+
%<sysinfo %s | grep -i "bytes\\s*free" | grep -o "[0-9]*)" | grep -o "[0-9]*">, # Haiku
|
419
|
+
%<top -d1 -q %s | grep "Mem" | awk '{print $2}'>, # Solaris
|
420
|
+
%<systeminfo %s | findstr /C:"Total Physical Memory">, # Windows
|
421
|
+
]
|
422
|
+
mem_size = 0
|
423
|
+
cmds.each do |cmd|
|
424
|
+
begin
|
425
|
+
size = `#{cmd % stderr_redirect}`.strip.gsub(/,/, "")
|
426
|
+
size = size.strip.split(/:|=/)[-1].split.join
|
427
|
+
unless size.empty?
|
428
|
+
mem_size = size.to_i
|
429
|
+
if size =~ /(K|M|G|T|P|E)B?$/i
|
430
|
+
case $1.upcase
|
431
|
+
when "K"; mem_size *= 1024
|
432
|
+
when "M"; mem_size *= 1048576
|
433
|
+
when "G"; mem_size *= 1073741824
|
434
|
+
when "T"; mem_size *= 1099511627776
|
435
|
+
when "P"; mem_size *= 1125899906842624
|
436
|
+
when "E"; mem_size *= 1152921504606846976
|
437
|
+
end
|
438
|
+
end
|
439
|
+
break
|
440
|
+
end
|
441
|
+
rescue Errno::ENOENT, NoMethodError
|
442
|
+
end
|
443
|
+
end
|
444
|
+
mem_size
|
445
|
+
end
|
446
|
+
|
447
|
+
# MAC address Miner
|
448
|
+
mac_addr_miner = lambda do |stderr_redirect|
|
449
|
+
cmds = [
|
450
|
+
%<ifconfig -a %s>, # Linux
|
451
|
+
%</sbin/ifconfig -a %s>, # Linux Alt
|
452
|
+
%</bin/ifconfig -a %s>, # Linux Alt #2
|
453
|
+
%<ip addr %s>,
|
454
|
+
%<ipconfig /all %s>, # Windows
|
455
|
+
%<cat /sys/class/net/*/address %s>, # Linux Alt #3
|
456
|
+
]
|
457
|
+
re = %r/(?:[^:\-]|\A)((?:[0-9A-F][0-9A-F][:\-]){5}[0-9A-F][0-9A-F])(?:[^:\-]|\Z)/io
|
458
|
+
mac_addr = nil
|
459
|
+
cmds.each do |cmd|
|
460
|
+
begin
|
461
|
+
out = `#{cmd % stderr_redirect}`.strip
|
462
|
+
mac_addr = out.split("\n").map { |line| line =~ re && $1 }.compact[0]
|
463
|
+
break if mac_addr
|
464
|
+
rescue Errno::ENOENT, NoMethodError
|
465
|
+
end
|
466
|
+
end
|
467
|
+
mac_addr
|
468
|
+
end
|
469
|
+
|
470
|
+
err = test("e", "/dev/null") ? "2> /dev/null" : "2> nul"
|
471
|
+
@@machine_details ||= {
|
472
|
+
:arch => proc_arch_miner[err],
|
473
|
+
:n_cpus => proc_count_miner[err],
|
474
|
+
:ram => mem_size_miner[err],
|
475
|
+
:mac_addr => mac_addr_miner[err],
|
476
|
+
}
|
477
|
+
end
|
478
|
+
|
479
|
+
# Detect the interpreter we're running on.
|
480
|
+
def detect_interpreter
|
481
|
+
@@interpreter ||= nil
|
482
|
+
return @@interpreter if @@interpreter
|
483
|
+
|
484
|
+
var = ::RbConfig::CONFIG['RUBY_INSTALL_NAME'].downcase
|
485
|
+
if defined?(::RUBY_ENGINE)
|
486
|
+
var << " " << ::RUBY_ENGINE.downcase
|
487
|
+
end
|
488
|
+
@@interpreter = case var
|
489
|
+
when /jruby/; "jruby"
|
490
|
+
when /macruby/; "macruby"
|
491
|
+
when /rbx/; "rubinius"
|
492
|
+
when /maglev/; "maglev"
|
493
|
+
when /ir/; "ironruby"
|
494
|
+
when /ruby/
|
495
|
+
if GC.respond_to?(:copy_on_write_friendly=) && RUBY_VERSION < "1.9"
|
496
|
+
"rubyee"
|
497
|
+
elsif var.respond_to?(:shortest_abbreviation) && RUBY_VERSION >= "1.9"
|
498
|
+
"goruby"
|
499
|
+
else
|
500
|
+
"mri"
|
501
|
+
end
|
502
|
+
else; nil
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
# Detect the Language we're running on.
|
507
|
+
def detect_interpreter_language
|
508
|
+
@@interpreter_language ||= case detect_interpreter
|
509
|
+
when "jruby"; "java"
|
510
|
+
when "macruby"; "objective-c"
|
511
|
+
when "rubinius"; "c++"
|
512
|
+
when "maglev"; "smalltalk"
|
513
|
+
when "ironruby"; ".net"
|
514
|
+
when /rubyee|goruby|mri/; "c"
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
# Detect the most likely candidate for a public-facing IPv4 Address
|
519
|
+
def detect_reachable_ip
|
520
|
+
if RUBY_VERSION >= "1.9.2"
|
521
|
+
require 'socket'
|
522
|
+
possible_ips = Socket.ip_address_list.reject { |ip| !ip.ipv4? || ip.ipv4_loopback? }
|
523
|
+
return possible_ips.first.ip_address unless possible_ips.empty?
|
524
|
+
end
|
525
|
+
if detect_os[:platform] == "windows"
|
526
|
+
output = `ipconfig`
|
527
|
+
ip_regex = /IP(?:v4)?.*?([0-9]+(?:\.[0-9]+){3})/i
|
528
|
+
gateway_regex = /Gateway[^0-9]*([0-9]+(?:\.[0-9]+){3})?/i
|
529
|
+
ip_matches = output.split(/\n/).select { |s| s =~ ip_regex }
|
530
|
+
gateway_matches = output.split(/\n/).select { |s| s =~ gateway_regex }
|
531
|
+
possible_ips = ip_matches.zip(gateway_matches)
|
532
|
+
possible_ips.map! do |ip,gateway|
|
533
|
+
[ip.match(ip_regex)[1], gateway.match(gateway_regex)[1]]
|
534
|
+
end
|
535
|
+
possible_ips.reject! { |ip,gateway| ip == "127.0.0.1" || gateway.nil? }
|
536
|
+
return possible_ips[0][0]
|
537
|
+
elsif ENV['SSH_CONNECTION']
|
538
|
+
return ENV['SSH_CONNECTION'].split(/\s+/)[-2]
|
539
|
+
else
|
540
|
+
if Pathname.which("ifconfig")
|
541
|
+
ip_output = `ifconfig -a 2> /dev/null`.chomp
|
542
|
+
elsif File.executable?("/sbin/ifconfig")
|
543
|
+
ip_output = `/sbin/ifconfig -a 2> /dev/null`.chomp
|
544
|
+
else
|
545
|
+
ip_output = `ip addr 2> /dev/null`.chomp
|
546
|
+
end
|
547
|
+
possible_ips = ip_output.scan(/inet (?:addr:)?([0-9\.]+)/).flatten
|
548
|
+
possible_ips.reject! { |ip| ip == "127.0.0.1" }
|
549
|
+
return possible_ips.first
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
# Probe the platform for information
|
554
|
+
def detect_platform
|
555
|
+
@@platform_features ||= {
|
556
|
+
:interpreter => detect_interpreter,
|
557
|
+
:interpreter_language => detect_interpreter_language,
|
558
|
+
:ipv4 => detect_reachable_ip,
|
559
|
+
:ruby_version => RUBY_VERSION,
|
560
|
+
}.merge(detect_os).merge(detect_hardware)
|
561
|
+
end
|
562
|
+
|
563
|
+
# Gems that are required only when a module or class is used
|
564
|
+
def required_if_used(*args)
|
565
|
+
unless @required_gems
|
566
|
+
[:included, :extended, :inherited].each do |method_name|
|
567
|
+
define_method(method_name) do |klass|
|
568
|
+
super if defined?(super)
|
569
|
+
@required_gems.each { |gem| require gem.to_s }
|
570
|
+
end
|
571
|
+
end
|
572
|
+
end
|
573
|
+
@required_gems ||= []
|
574
|
+
@required_gems |= args
|
575
|
+
end
|
576
|
+
|
577
|
+
# Check if a gem is installed. Returns version string if installed, nil otherwise
|
578
|
+
def gem_installed?(gem)
|
579
|
+
begin
|
580
|
+
old_stderr, $stderr = $stderr, StringIO.new
|
581
|
+
if defined?(::Gem::Specification) && ::Gem::Specification.respond_to?(:find_by_name)
|
582
|
+
gem_spec = ::Gem::Specification.find_by_name(gem)
|
583
|
+
else
|
584
|
+
gem_spec = ::Gem::GemPathSearcher.new.find(gem)
|
585
|
+
end
|
586
|
+
gem_spec.nil? ? nil : gem_spec.version.to_s
|
587
|
+
rescue LoadError
|
588
|
+
nil
|
589
|
+
ensure
|
590
|
+
$stderr = old_stderr
|
591
|
+
end
|
592
|
+
end
|
593
|
+
end
|
data/lib/ext/numeric.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
class Numeric
|
2
|
+
def years; self * 31536000; end
|
3
|
+
def weeks; self * 604800; end
|
4
|
+
def days; self * 86400; end
|
5
|
+
def hours; self * 3600; end
|
6
|
+
def minutes; self * 60; end
|
7
|
+
def seconds; self; end
|
8
|
+
def mseconds; self / 1000.0; end
|
9
|
+
def useconds; self / 1000000.0; end
|
10
|
+
|
11
|
+
alias_method :year, :years
|
12
|
+
alias_method :week, :weeks
|
13
|
+
alias_method :day, :days
|
14
|
+
alias_method :hour, :hours
|
15
|
+
alias_method :minute, :minutes
|
16
|
+
alias_method :second, :seconds
|
17
|
+
alias_method :msecond, :mseconds
|
18
|
+
alias_method :usecond, :useconds
|
19
|
+
|
20
|
+
def eb; self * 1152921504606846976; end
|
21
|
+
def pb; self * 1125899906842624; end
|
22
|
+
def tb; self * 1099511627776; end
|
23
|
+
def gb; self * 1073741824; end
|
24
|
+
def mb; self * 1048576; end
|
25
|
+
def kb; self * 1024; end
|
26
|
+
|
27
|
+
alias_method :EB, :eb
|
28
|
+
alias_method :PB, :pb
|
29
|
+
alias_method :TB, :tb
|
30
|
+
alias_method :GB, :gb
|
31
|
+
alias_method :MB, :mb
|
32
|
+
alias_method :KB, :kb
|
33
|
+
|
34
|
+
alias_method :exabytes, :eb
|
35
|
+
alias_method :petabytes, :pb
|
36
|
+
alias_method :terabytes, :tb
|
37
|
+
alias_method :gigabytes, :gb
|
38
|
+
alias_method :megabytes, :mb
|
39
|
+
alias_method :kilobytes, :kb
|
40
|
+
|
41
|
+
alias_method :exabyte, :eb
|
42
|
+
alias_method :petabyte, :pb
|
43
|
+
alias_method :terabyte, :tb
|
44
|
+
alias_method :gigabyte, :gb
|
45
|
+
alias_method :megabyte, :mb
|
46
|
+
alias_method :kilobyte, :kb
|
47
|
+
|
48
|
+
# Convert to degrees
|
49
|
+
def to_degrees
|
50
|
+
self * Math::PI / 180
|
51
|
+
end
|
52
|
+
|
53
|
+
# Convert to radians
|
54
|
+
def to_radians
|
55
|
+
self * 180 / Math::PI
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return the square root of self
|
59
|
+
def sqrt
|
60
|
+
Math.sqrt(self)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Calculate the rank of self based on provided min and max
|
64
|
+
def rank(min, max)
|
65
|
+
s, min, max = self.to_f, min.to_f, max.to_f
|
66
|
+
min == max ? 0.0 : (s - min) / (max - min)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Calculate the percentage of self on n
|
70
|
+
def percentage_of(n, t=100)
|
71
|
+
n == 0 ? 0.0 : self / n.to_f * t
|
72
|
+
end
|
73
|
+
alias_method :percent_of, :percentage_of
|
74
|
+
end
|
data/lib/ext/object.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
class Object
|
2
|
+
def deep_dup
|
3
|
+
Marshal.load(Marshal.dump(self))
|
4
|
+
end
|
5
|
+
|
6
|
+
def just_my_methods
|
7
|
+
ret = self.methods
|
8
|
+
(self.class.ancestors - [self.class]).each { |klass|
|
9
|
+
if Module === klass
|
10
|
+
ret -= klass.methods
|
11
|
+
elsif Class === klass
|
12
|
+
ret -= klass.new.methods
|
13
|
+
end
|
14
|
+
}
|
15
|
+
ret
|
16
|
+
end
|
17
|
+
end
|