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