yore 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +23 -0
- data/Rakefile +64 -57
- data/VERSION +1 -0
- data/bin/yore +6 -11
- data/lib/yore/yore_core.rb +70 -43
- data/notes.txt +27 -0
- data/test/S3_test.rb +2 -5
- data/test/test_helper.rb +10 -0
- data/test/test_job_b.xml +1 -1
- data/test/yore_browsercms_loadsave_test.rb +191 -0
- data/test/{loadsave_yore_test.rb → yore_spree_loadsave_test.rb} +9 -10
- data/test/yore_test.rb +1 -4
- data/test.crontab +5 -0
- data/yore.vpj +120 -0
- data/yore.vpw +6 -0
- metadata +38 -82
- data/History.txt +0 -22
- data/Manifest.txt +0 -26
- data/PostInstall.txt +0 -7
- data/lib/ihl_ruby/config.rb +0 -202
- data/lib/ihl_ruby/database_utils.rb +0 -89
- data/lib/ihl_ruby/enum.rb +0 -50
- data/lib/ihl_ruby/extend_base_classes.rb +0 -319
- data/lib/ihl_ruby/logging.rb +0 -159
- data/lib/ihl_ruby/misc_utils.rb +0 -382
- data/lib/ihl_ruby/shell_extras.rb +0 -84
- data/lib/ihl_ruby/string_utils.rb +0 -53
- data/lib/ihl_ruby/xml_utils.rb +0 -177
- data/lib/yore.orig.rb +0 -6
- data/script/console +0 -10
- data/script/destroy +0 -14
- data/script/generate +0 -14
data/lib/ihl_ruby/logging.rb
DELETED
@@ -1,159 +0,0 @@
|
|
1
|
-
require 'logger'
|
2
|
-
require 'ihl_ruby/misc_utils'
|
3
|
-
|
4
|
-
class Logger
|
5
|
-
attr_reader :logdev
|
6
|
-
end
|
7
|
-
|
8
|
-
module LogUtils
|
9
|
-
|
10
|
-
# eg.
|
11
|
-
# {
|
12
|
-
# 'destination' => 'STDERR|STDOUT|FILE',
|
13
|
-
# 'filename' => '/path/to/file.ext',
|
14
|
-
# 'level' => 'DEBUG|INFO|...',
|
15
|
-
#
|
16
|
-
# 'age' = 'daily|weekly|monthly',
|
17
|
-
# OR
|
18
|
-
# 'max_files' => 3,
|
19
|
-
# 'max_bytes' => 1024000
|
20
|
-
# }
|
21
|
-
def self.create_logger_from_config(aConfigHash)
|
22
|
-
if not aConfigHash
|
23
|
-
result = Logger.new(STDERR)
|
24
|
-
result.level = Logger::INFO
|
25
|
-
return result
|
26
|
-
end
|
27
|
-
|
28
|
-
result = nil
|
29
|
-
case aConfigHash['destination']
|
30
|
-
when 'STDERR' then
|
31
|
-
result = Logger.new(STDERR)
|
32
|
-
when 'STDOUT' then
|
33
|
-
result = Logger.new(STDOUT)
|
34
|
-
when 'FILE' then
|
35
|
-
result = aConfigHash['age'] ?
|
36
|
-
Logger.new(aConfigHash['filename'],aConfigHash['age']) :
|
37
|
-
Logger.new(
|
38
|
-
aConfigHash['filename'],
|
39
|
-
(aConfigHash['max_files'] || 3).to_i,
|
40
|
-
(aConfigHash['max_bytes'] || 1024000).to_i
|
41
|
-
)
|
42
|
-
else
|
43
|
-
result = Logger.new(STDERR)
|
44
|
-
end
|
45
|
-
puts valstr = "Logger::#{(aConfigHash['level'] || 'INFO').upcase}"
|
46
|
-
result.level = eval(valstr)
|
47
|
-
return result
|
48
|
-
end
|
49
|
-
|
50
|
-
# use this to trunc a log file to 0 bytes
|
51
|
-
def self.trunc(aFilename)
|
52
|
-
f = File.open(aFilename, "w")
|
53
|
-
f.close
|
54
|
-
end
|
55
|
-
|
56
|
-
class ReportFormatter < Logger::Formatter
|
57
|
-
def call(severity, time, progname, msg)
|
58
|
-
"|%s %1s %s\n" % [(time.strftime('%H%M%S.')<<"%03d" % (time.usec/1000)),severity[0..0],msg2str(msg)]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
class Reporter < Logger
|
63
|
-
def initialize(logdev)
|
64
|
-
super(logdev)
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
def self.create_reporter(aFilename=nil)
|
70
|
-
aFilename ||= MiscUtils::temp_file()
|
71
|
-
result = Logger.new(aFilename)
|
72
|
-
result.formatter = ReportFormatter.new
|
73
|
-
result
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
class MultiLogger < Logger
|
80
|
-
|
81
|
-
attr_reader :loggers
|
82
|
-
|
83
|
-
def initialize(aLoggers)
|
84
|
-
@loggers = aLoggers.is_a?(Array) ? aLoggers : [aLoggers]
|
85
|
-
end
|
86
|
-
|
87
|
-
def add(severity, message = nil, progname = nil, &block)
|
88
|
-
return true if !@loggers
|
89
|
-
severity ||= UNKNOWN
|
90
|
-
@loggers.each do |lr|
|
91
|
-
block_given? ? lr.add(severity,message,progname,&block) : lr.add(severity,message,progname)
|
92
|
-
end
|
93
|
-
true
|
94
|
-
end
|
95
|
-
alias log add
|
96
|
-
|
97
|
-
def <<(msg)
|
98
|
-
@loggers.each do |lr|
|
99
|
-
lr << msg
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def close
|
104
|
-
@loggers.each do |lr|
|
105
|
-
lr.close
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
end
|
110
|
-
|
111
|
-
#DEBUG D
|
112
|
-
#INFO
|
113
|
-
#WARN ?
|
114
|
-
#ERROR !
|
115
|
-
#FATAL F
|
116
|
-
#UNKNOWN U
|
117
|
-
|
118
|
-
# Logger that mostly works like a STDOUT logger, except that warnings and above get sent to STDERR instead
|
119
|
-
class ConsoleLogger < Logger
|
120
|
-
|
121
|
-
class ReportFormatter < Logger::Formatter
|
122
|
-
def call(severity, time, progname, msg)
|
123
|
-
msg2str(msg)+"\n"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def initialize(aErrLevel = Severity::WARN)
|
128
|
-
super(STDOUT)
|
129
|
-
self.formatter = ReportFormatter.new
|
130
|
-
self.level = Severity::INFO
|
131
|
-
self << "\n"
|
132
|
-
@err_logger = Logger.new(STDERR)
|
133
|
-
@err_level = aErrLevel
|
134
|
-
@err_logger.formatter = ReportFormatter.new
|
135
|
-
end
|
136
|
-
|
137
|
-
alias_method :orig_add, :add
|
138
|
-
def add(severity, message = nil, progname = nil, &block)
|
139
|
-
if severity >= @err_level
|
140
|
-
block_given? ? @err_logger.add(severity,message,progname,&block) : @err_logger.add(severity,message,progname)
|
141
|
-
else
|
142
|
-
block_given? ? orig_add(severity,message,progname,&block) : orig_add(severity,message,progname)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
alias log add
|
146
|
-
|
147
|
-
#
|
148
|
-
# Close the logging device.
|
149
|
-
#
|
150
|
-
def close
|
151
|
-
begin
|
152
|
-
@logdev.close if @logdev
|
153
|
-
ensure
|
154
|
-
@err_logger.close
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
end
|
159
|
-
|
data/lib/ihl_ruby/misc_utils.rb
DELETED
@@ -1,382 +0,0 @@
|
|
1
|
-
require 'tmpdir'
|
2
|
-
require 'logger'
|
3
|
-
require 'pathname'
|
4
|
-
|
5
|
-
require 'ihl_ruby/logging'
|
6
|
-
|
7
|
-
module MiscUtils
|
8
|
-
|
9
|
-
def self.logger
|
10
|
-
@logger || @logger = Logger.new(STDERR)
|
11
|
-
end
|
12
|
-
|
13
|
-
# applies the given block to key/value pairs included/excluded by the given parameters
|
14
|
-
# aSource must be a hash, and may contain hashes which will be recursively processed.
|
15
|
-
# aInclude/aExclude may be nil, an array of selected keys, or a hash containing arrays of keys for inner hashes of aSource
|
16
|
-
# When aInclude/aExclude are a hash, non-hash source values may be selected by passing a value of true. Hash source values
|
17
|
-
# will be selected as a whole (all keys) when true is passed.
|
18
|
-
# input = { 'a' => 1, 'b' => {'x' => 9, 'y' => 8}, 'c' => 3 }
|
19
|
-
# filter_multilevel_hash(input,['a','b'],{'b'=>['y']}) {|h,k,v| h[k] = true}
|
20
|
-
# input now = { 'a' => true, 'b' => {'x' => true, 'y' => 8}, 'c' => 3 }
|
21
|
-
def self.filter_multilevel_hash(aSource,aInclude=nil,aExclude=nil,&block)
|
22
|
-
aSource.each do |key,value|
|
23
|
-
next if aInclude.is_a?(Array) and !aInclude.include?(key) # skip if not in aInclude array
|
24
|
-
next if aExclude.is_a?(Array) and aExclude.include?(key) # skip if in aExclude array
|
25
|
-
next if aExclude.is_a?(Hash) and aExclude[key]==true # skip if in aExclude hash with value=true
|
26
|
-
next if aInclude.is_a?(Hash) and !aInclude.include?(key) # skip if not in aInclude hash at all
|
27
|
-
if value.is_a?(Hash) # value is hash so recursively apply filter
|
28
|
-
filter_multilevel_hash(
|
29
|
-
value,
|
30
|
-
aInclude.is_a?(Hash) && (f = aInclude[key]) ? f : nil, # pass include array if provided for key
|
31
|
-
aExclude.is_a?(Hash) && (f = aExclude[key]) ? f : nil, # pass exclude array if provided for key
|
32
|
-
&block
|
33
|
-
)
|
34
|
-
else
|
35
|
-
yield(aSource,key,value)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# returns output string if succesful, or integer return code if not, or nil
|
41
|
-
def self.execute(aCommand,aWorkingDir=nil,aTimeout=nil,aTimeoutClass=nil)
|
42
|
-
return nil unless !aWorkingDir || File.exists?(aWorkingDir)
|
43
|
-
begin
|
44
|
-
orig_wd = Dir.getwd
|
45
|
-
pipe = nil
|
46
|
-
result = nil
|
47
|
-
Dir.chdir(aWorkingDir) if aWorkingDir
|
48
|
-
Timeout.timeout(aTimeout,aTimeoutClass || Timeout::Error) do # nil aTimeout will not time out
|
49
|
-
pipe = IO.popen(aCommand)
|
50
|
-
logger.debug "command PID:"+pipe.pid.to_s
|
51
|
-
result = pipe.read
|
52
|
-
end
|
53
|
-
ensure
|
54
|
-
pipe.close if pipe
|
55
|
-
Dir.chdir(orig_wd)
|
56
|
-
end
|
57
|
-
return result
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.execute_string(aCmdString,aWorkingDir=nil)
|
61
|
-
result = nil
|
62
|
-
begin
|
63
|
-
orig_dir = Dir.pwd
|
64
|
-
Dir.chdir(aWorkingDir) if aWorkingDir
|
65
|
-
result = `#{aCmdString}`
|
66
|
-
ensure
|
67
|
-
Dir.chdir(orig_dir) if aWorkingDir
|
68
|
-
end
|
69
|
-
return result
|
70
|
-
end
|
71
|
-
|
72
|
-
def self.temp_file(aExt=nil,aDir=nil)
|
73
|
-
aExt ||= '.tmp'
|
74
|
-
File.expand_path(("%08X" % rand(0x3FFFFFFF)) + aExt, aDir||Dir.tmpdir)
|
75
|
-
end
|
76
|
-
|
77
|
-
def self.make_temp_file(aName=nil,aDir=nil,aContent=nil)
|
78
|
-
filename = aName ? File.expand_path(aName,aDir || Dir.tmpdir) : temp_file(nil,aDir)
|
79
|
-
FileUtils.mkdir_p(File.dirname(filename))
|
80
|
-
aContent ||= "content of "+filename
|
81
|
-
string_to_file(aContent,filename)
|
82
|
-
filename
|
83
|
-
end
|
84
|
-
|
85
|
-
def self.make_temp_dir(aPrefix='')
|
86
|
-
new_dir = nil
|
87
|
-
begin
|
88
|
-
new_dir = File.join(Dir.tmpdir,aPrefix+("%08X" % rand(0x3FFFFFFF)))
|
89
|
-
end until new_dir && !File.exists?(new_dir)
|
90
|
-
Dir.mkdir new_dir
|
91
|
-
return new_dir
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.mkdir?(aPath,aPermissions)
|
95
|
-
if File.exists?(aPath)
|
96
|
-
File.chmod(aPermissions, aPath)
|
97
|
-
else
|
98
|
-
Dir.mkdir(aPath, aPermissions)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def self.string_to_file(aString,aFilename)
|
103
|
-
File.open(aFilename,'wb') {|file| file.puts aString }
|
104
|
-
end
|
105
|
-
|
106
|
-
def self.string_from_file(aFilename)
|
107
|
-
result = nil
|
108
|
-
File.open(aFilename, "rb") { |f| result = f.read }
|
109
|
-
return result && result[0..-2] # quick hack to stop returning false \n at end
|
110
|
-
end
|
111
|
-
|
112
|
-
def self.sniff_seperator(aPath)
|
113
|
-
result = 0.upto(aPath.length-1) do |i|
|
114
|
-
char = aPath[i,1]
|
115
|
-
break char if char=='\\' || char=='/'
|
116
|
-
end
|
117
|
-
result = File::SEPARATOR if result==0
|
118
|
-
return result
|
119
|
-
end
|
120
|
-
|
121
|
-
def self.append_slash(aPath,aSep=nil)
|
122
|
-
aSep = sniff_seperator(aPath) unless aSep
|
123
|
-
last_char = aPath[-1,1]
|
124
|
-
aPath += aSep unless last_char=='\\' || last_char=='/'
|
125
|
-
return aPath
|
126
|
-
end
|
127
|
-
|
128
|
-
def self.remove_slash(aPath)
|
129
|
-
last_char = aPath[-1,1]
|
130
|
-
aPath = aPath[0..-2] if last_char=='\\' || last_char=='/'
|
131
|
-
return aPath
|
132
|
-
end
|
133
|
-
|
134
|
-
# Remove base dir from given path. Result will be relative to base dir and not have a leading or trailing slash
|
135
|
-
#'/a/b/c','/a' = 'b/c'
|
136
|
-
#'/a/b/c','/' = 'a/b/c'
|
137
|
-
#'/','/' = ''
|
138
|
-
def self.path_debase(aPath,aBase)
|
139
|
-
aBase = MiscUtils::append_slash(aBase)
|
140
|
-
aPath = MiscUtils::remove_slash(aPath) unless aPath=='/'
|
141
|
-
aPath[0,aBase.length]==aBase ? aPath[aBase.length,aPath.length-aBase.length] : aPath
|
142
|
-
end
|
143
|
-
|
144
|
-
def self.path_rebase(aPath,aOldBase,aNewBase)
|
145
|
-
rel_path = path_debase(aPath,aOldBase)
|
146
|
-
append_slash(aNewBase)+rel_path
|
147
|
-
end
|
148
|
-
|
149
|
-
def self.path_combine(aBasePath,aPath)
|
150
|
-
return aBasePath if !aPath
|
151
|
-
return aPath if !aBasePath
|
152
|
-
return path_relative?(aPath) ? File.join(aBasePath,aPath) : aPath
|
153
|
-
end
|
154
|
-
|
155
|
-
def self.path_parent(aPath)
|
156
|
-
MiscUtils.append_slash(File.dirname(MiscUtils.remove_slash(File.expand_path(aPath))))
|
157
|
-
end
|
158
|
-
|
159
|
-
def self.simple_dir_name(aPath)
|
160
|
-
File.basename(remove_slash(aPath))
|
161
|
-
end
|
162
|
-
|
163
|
-
def self.path_parts(aPath)
|
164
|
-
sep = sniff_seperator(aPath)
|
165
|
-
aPath.split(sep)
|
166
|
-
end
|
167
|
-
|
168
|
-
def self.file_extension(aFile,aExtended=true)
|
169
|
-
f = File.basename(aFile)
|
170
|
-
dot = aExtended ? f.index('.') : f.rindex('.')
|
171
|
-
return dot ? f[dot+1..-1] : f
|
172
|
-
end
|
173
|
-
|
174
|
-
def self.file_no_extension(aFile,aExtended=true)
|
175
|
-
ext = file_extension(aFile,aExtended)
|
176
|
-
return aFile.chomp('.'+ext)
|
177
|
-
end
|
178
|
-
|
179
|
-
def self.file_change_ext(aFile,aExt,aExtend=false)
|
180
|
-
file_no_extension(aFile,false)+(aExtend ? '.'+aExt+'.'+file_extension(aFile,false) : '.'+aExt)
|
181
|
-
end
|
182
|
-
|
183
|
-
def self.platform
|
184
|
-
RUBY_PLATFORM.scan(/-(.+)$/).flatten.first
|
185
|
-
end
|
186
|
-
|
187
|
-
def self.windows_path(aPath)
|
188
|
-
aPath.gsub('/','\\')
|
189
|
-
end
|
190
|
-
|
191
|
-
def self.ruby_path(aPath)
|
192
|
-
aPath.gsub('\\','/')
|
193
|
-
end
|
194
|
-
|
195
|
-
def self.is_uri?(aString)
|
196
|
-
/^[a-zA-Z0-9+_]+\:\/\// =~ aString ? true : false
|
197
|
-
end
|
198
|
-
|
199
|
-
def self.native_path(aPath)
|
200
|
-
is_windows? ? windows_path(aPath) : ruby_path(aPath)
|
201
|
-
end
|
202
|
-
|
203
|
-
def self.path_relative?(aPath)
|
204
|
-
return false if aPath[0,1]=='/'
|
205
|
-
return false if aPath =~ /^[a-zA-Z]:/
|
206
|
-
return true
|
207
|
-
end
|
208
|
-
|
209
|
-
def self.path_absolute?(aPath)
|
210
|
-
!path_relative(aPath)
|
211
|
-
end
|
212
|
-
|
213
|
-
def self.is_windows?
|
214
|
-
platform=='mswin32'
|
215
|
-
end
|
216
|
-
|
217
|
-
# takes a path and combines it with a root path (which defaults to Dir.pwd) unless it is absolute
|
218
|
-
# the final result is then expanded
|
219
|
-
def self.canonize_path(aPath,aRootPath=nil)
|
220
|
-
path = Pathname.new(aPath)
|
221
|
-
path = Pathname.new(aRootPath || Dir.pwd)+path if path.relative?
|
222
|
-
File.expand_path(path)
|
223
|
-
end
|
224
|
-
|
225
|
-
def self.get_files(aArray,aPath,aFullPath=true,aRootPath=nil,&block)
|
226
|
-
#puts "get_files: aPath='#{aPath}'"
|
227
|
-
if aRootPath
|
228
|
-
abssrcpath = path_combine(aRootPath,aPath)
|
229
|
-
else
|
230
|
-
abssrcpath = aRootPath = aPath
|
231
|
-
aPath = nil
|
232
|
-
end
|
233
|
-
return aArray if !File.exists?(abssrcpath)
|
234
|
-
#abssrcpath is real path to query
|
235
|
-
#aRootPath is highest level path
|
236
|
-
#aPath is current path relative to aRootPath
|
237
|
-
Dir.new(abssrcpath).to_a.each do |file|
|
238
|
-
next if ['.','..'].include? file
|
239
|
-
fullpath = File.join(abssrcpath,file)
|
240
|
-
resultpath = aFullPath ? fullpath : path_combine(aPath,file)
|
241
|
-
if !block_given? || yield(resultpath)
|
242
|
-
if FileTest.directory?(fullpath)
|
243
|
-
block_given? ? get_files(aArray,path_combine(aPath,file),aFullPath,aRootPath,&block) : get_files(aArray,path_combine(aPath,file),aFullPath,aRootPath)
|
244
|
-
else
|
245
|
-
aArray << resultpath
|
246
|
-
end
|
247
|
-
end
|
248
|
-
end
|
249
|
-
return aArray
|
250
|
-
end
|
251
|
-
|
252
|
-
def self.recursive_file_list(aPath,aFullPath=true,&block)
|
253
|
-
block_given? ? get_files([],aPath,aFullPath,nil,&block) : get_files([],aPath,aFullPath)
|
254
|
-
end
|
255
|
-
|
256
|
-
# returns true if aPath1 and aPath2 are the same path (doesn't query file system)
|
257
|
-
# both must be absolute or both relative
|
258
|
-
def self.path_same(aPath1,aPath2)
|
259
|
-
return nil unless path_relative?(aPath1) == path_relative?(aPath2)
|
260
|
-
remove_slash(aPath1) == remove_slash(aPath2)
|
261
|
-
end
|
262
|
-
|
263
|
-
# returns true if aPath is under aPathParent
|
264
|
-
# both must be absolute or both relative
|
265
|
-
def self.path_ancestor(aPathParent,aPath)
|
266
|
-
return nil unless path_relative?(aPathParent) == path_relative?(aPath)
|
267
|
-
aPath.index(append_slash(aPathParent))==0
|
268
|
-
end
|
269
|
-
|
270
|
-
# returns the lowest path containing all files (assumes aFiles contains only absolute paths)
|
271
|
-
def self.file_list_ancestor(aFiles)
|
272
|
-
files = aFiles.is_a?(Hash) ? aFiles.keys : aFiles
|
273
|
-
result = File.dirname(files.first)
|
274
|
-
files.each do |fp|
|
275
|
-
filedir = File.dirname(fp)
|
276
|
-
while path_same(result,filedir)==false && path_ancestor(result,filedir)==false
|
277
|
-
result = path_parent(result)
|
278
|
-
end
|
279
|
-
end
|
280
|
-
result
|
281
|
-
end
|
282
|
-
|
283
|
-
def self.path_match(aPath,aPatterns)
|
284
|
-
aPatterns = [aPatterns] unless aPatterns.is_a? Array
|
285
|
-
aPatterns.any? do |pat|
|
286
|
-
case pat
|
287
|
-
when String then aPath[0,pat.length] == pat
|
288
|
-
when Regexp then aPath =~ pat
|
289
|
-
else false
|
290
|
-
end
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
|
295
|
-
# takes a hash and returns a single closed tag containing the hash pairs as attributes, correctly encoded
|
296
|
-
def self.hash_to_xml_tag(aName,aHash)
|
297
|
-
atts = ''
|
298
|
-
aHash.each do |k,v|
|
299
|
-
atts += ' ' + k.to_s + "=\"#{v.to_s.to_xs}\""
|
300
|
-
end
|
301
|
-
"<#{aName}#{atts}/>"
|
302
|
-
end
|
303
|
-
|
304
|
-
def self.filelist_from_patterns(aPatterns,aBasePath)
|
305
|
-
return [] unless aPatterns
|
306
|
-
aPatterns = [aPatterns] unless aPatterns.is_a? Array
|
307
|
-
|
308
|
-
aPatterns.map do |fp|
|
309
|
-
fp = File.expand_path(fp,aBasePath) # relative to rails root
|
310
|
-
fp = FileList[fp] if fp['*'] || fp['?']
|
311
|
-
fp
|
312
|
-
end.flatten
|
313
|
-
end
|
314
|
-
|
315
|
-
#:host
|
316
|
-
#:port
|
317
|
-
#:helodomain
|
318
|
-
#:user
|
319
|
-
#:password
|
320
|
-
#:from
|
321
|
-
#:from_alias
|
322
|
-
#:to
|
323
|
-
#:to_alias
|
324
|
-
#:subject
|
325
|
-
#:message
|
326
|
-
#:auth : 'plain', 'login', 'cram_md5'
|
327
|
-
|
328
|
-
# send an email via an SMTP server
|
329
|
-
def self.send_email(aArgs)
|
330
|
-
msg = <<END_OF_MESSAGE
|
331
|
-
From: #{aArgs[:from_alias]} <#{aArgs[:from]}>
|
332
|
-
To: #{aArgs[:to_alias]} <#{aArgs[:to]}>
|
333
|
-
Subject: #{aArgs[:subject]}
|
334
|
-
|
335
|
-
#{aArgs[:message]}
|
336
|
-
END_OF_MESSAGE
|
337
|
-
|
338
|
-
Net::SMTP.start(
|
339
|
-
aArgs[:host],
|
340
|
-
aArgs[:port],
|
341
|
-
aArgs[:helodomain],
|
342
|
-
aArgs[:user],
|
343
|
-
aArgs[:password],
|
344
|
-
aArgs[:auth]
|
345
|
-
) do |smtp|
|
346
|
-
smtp.send_message msg, aArgs[:from], aArgs[:to]
|
347
|
-
end
|
348
|
-
end
|
349
|
-
|
350
|
-
end
|
351
|
-
|
352
|
-
# include this at the top of a class to protect it from baddies.
|
353
|
-
# eg.
|
354
|
-
# + nearly all ancestor public_instance_methods will be hidden
|
355
|
-
# + inspect will only return the class name
|
356
|
-
# + methods will return public methods
|
357
|
-
module SecureThisClass
|
358
|
-
def self.hack(aClass,aOptions={})
|
359
|
-
include_actions = (aOptions[:include] || aClass.public_instance_methods.clone)
|
360
|
-
exclude_actions = ['class','public_methods'] | (aOptions[:exclude] || [])
|
361
|
-
actions_to_hide = include_actions-exclude_actions
|
362
|
-
aClass.class_eval do
|
363
|
-
actions_to_hide.each { |m| protected m.to_sym }
|
364
|
-
|
365
|
-
def inspect
|
366
|
-
return self.class.name
|
367
|
-
end
|
368
|
-
|
369
|
-
def methods
|
370
|
-
public_methods
|
371
|
-
end
|
372
|
-
end
|
373
|
-
end
|
374
|
-
end
|
375
|
-
|
376
|
-
|
377
|
-
module ::Kernel
|
378
|
-
def secure_class(aOptions={})
|
379
|
-
SecureThisClass::hack(self,aOptions)
|
380
|
-
end
|
381
|
-
end
|
382
|
-
|
@@ -1,84 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
gem 'RequirePaths'; require 'require_paths'
|
3
|
-
require_paths '.','..'
|
4
|
-
|
5
|
-
gem 'Platform'; require 'platform'
|
6
|
-
gem 'shairontoledo-popen4'; require 'popen4'
|
7
|
-
|
8
|
-
module POpen4
|
9
|
-
|
10
|
-
class ExecuteError < StandardError
|
11
|
-
|
12
|
-
attr_reader :result #,:stderr,:stdout,:exitcode,:pid
|
13
|
-
|
14
|
-
def initialize(aArg)
|
15
|
-
if aArg.is_a? Hash
|
16
|
-
msg = ([aArg[:stderr],aArg[:stdout],"Error #{aArg[:exitcode].to_s}"].find {|i| i && !i.empty?})
|
17
|
-
super(msg)
|
18
|
-
@result = aArg
|
19
|
-
else
|
20
|
-
super(aArg)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def inspect
|
25
|
-
"#{self.class.to_s}: #{@result.inspect}"
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.pump_thread(aIn,aOut)
|
31
|
-
Thread.new do
|
32
|
-
loop { aOut.puts aIn.gets }
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Usage :
|
37
|
-
# result = POpen4::shell('somebinary') do |r| # block gives opportunity to adjust result, and avoid exception raised from non-zero exit codes
|
38
|
-
# if r[:exitcode]==254 # eg. say this binary returns 254 to mean something special but not an error
|
39
|
-
# r[:stdout] = 'some correct output'
|
40
|
-
# r[:stderr] = ''
|
41
|
-
# r[:exitcode] = 0
|
42
|
-
# end
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
# OR
|
46
|
-
#
|
47
|
-
# result = POpen4::shell('somebinary');
|
48
|
-
# puts result[:stdout]
|
49
|
-
#
|
50
|
-
# Giving aStdOut,aStdErr causes the command output to be connected to the given stream, and that stream to not be given in the result hash
|
51
|
-
def self.shell(aCommand,aWorkingDir=nil,aTimeout=nil,aStdOut=nil,aStdErr=nil)
|
52
|
-
raise ExecuteError.new('aWorkingDir doesnt exist') unless !aWorkingDir || File.exists?(aWorkingDir)
|
53
|
-
orig_wd = Dir.getwd
|
54
|
-
result = {:command => aCommand, :dir => (aWorkingDir || orig_wd)}
|
55
|
-
status = nil
|
56
|
-
begin
|
57
|
-
Dir.chdir(aWorkingDir) if aWorkingDir
|
58
|
-
Timeout.timeout(aTimeout,ExecuteError) do # nil aTimeout will not time out
|
59
|
-
status = POpen4::popen4(aCommand) do |stdout, stderr, stdin, pid|
|
60
|
-
thrOut = aStdOut ? Thread.new { aStdOut.puts stdout.read } : nil
|
61
|
-
thrErr = aStdErr ? Thread.new { aStdErr.puts stderr.read } : nil
|
62
|
-
thrOut.join if thrOut
|
63
|
-
thrErr.join if thrErr
|
64
|
-
|
65
|
-
result[:stdout] = stdout.read unless aStdOut
|
66
|
-
result[:stderr] = stderr.read unless aStdErr
|
67
|
-
result[:pid] = pid
|
68
|
-
end
|
69
|
-
end
|
70
|
-
ensure
|
71
|
-
Dir.chdir(orig_wd)
|
72
|
-
end
|
73
|
-
result[:exitcode] = (status && status.exitstatus) || 1
|
74
|
-
yield(result) if block_given?
|
75
|
-
raise ExecuteError.new(result) if result[:exitcode] != 0
|
76
|
-
return result
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.shell_out(aCommand,aWorkingDir=nil,aTimeout=nil,&block)
|
80
|
-
block_given? ? POpen4::shell(aCommand,aWorkingDir,aTimeout,STDOUT,STDERR,&block) : POpen4::shell(aCommand,aWorkingDir,aTimeout,STDOUT,STDERR)
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
84
|
-
|
@@ -1,53 +0,0 @@
|
|
1
|
-
module StringUtils
|
2
|
-
def self.crop(aString,aLength,aEllipsis=true,aConvertNil=true)
|
3
|
-
return aConvertNil ? ' '*aLength : nil if !aString
|
4
|
-
|
5
|
-
increase = aLength-aString.length
|
6
|
-
return aString+' '*increase if increase>=0
|
7
|
-
return aEllipsis ? aString[0,aLength-3]+'...' : aString[0,aLength]
|
8
|
-
end
|
9
|
-
|
10
|
-
# aTemplate is a string containing tokens like ${SOME_TOKEN}
|
11
|
-
# aValues is a hash of token names eg. 'SOME_TOKEN' and their values to substitute
|
12
|
-
def self.render_template(aTemplate,aValues)
|
13
|
-
# get positions of tokens
|
14
|
-
result = aTemplate.gsub(/\$\{(.*?)\}/) do |s|
|
15
|
-
key = s[2..-2]
|
16
|
-
rep = (aValues[key] || s)
|
17
|
-
#puts "replacing #{s} with #{rep}"
|
18
|
-
rep
|
19
|
-
end
|
20
|
-
#puts "rendered :\n#{result}"
|
21
|
-
return result
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.clean_number(aString)
|
25
|
-
aString.gsub(/[^0-9.-]/,'')
|
26
|
-
end
|
27
|
-
|
28
|
-
# supply a block with 2 parameters, and it will get called for each char as an integer
|
29
|
-
def self.each_unicode_char(aString)
|
30
|
-
len = 1
|
31
|
-
index = 0
|
32
|
-
char = 0
|
33
|
-
aString.each_byte do |b|
|
34
|
-
if index==0
|
35
|
-
len = 1
|
36
|
-
len = 2 if b & 0b11000000 != 0
|
37
|
-
len = 3 if b & 0b11100000 != 0
|
38
|
-
len = 4 if b & 0b11110000 != 0
|
39
|
-
char = 0
|
40
|
-
end
|
41
|
-
|
42
|
-
char |= b << index*8
|
43
|
-
|
44
|
-
yield(char,len) if index==len-1 # last byte; char is complete
|
45
|
-
|
46
|
-
index += 1
|
47
|
-
index = 0 if index >= len
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
end
|
53
|
-
|