cowtech-lib 1.9.0 → 1.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/cowtech-lib.gemspec +1 -9
- data/lib/cowtech-lib.rb +9 -5
- data/lib/cowtech-lib/console.rb +287 -245
- data/lib/cowtech-lib/option_parser.rb +52 -50
- data/lib/cowtech-lib/script.rb +26 -28
- data/lib/cowtech-lib/shell.rb +23 -18
- data/lib/cowtech-lib/version.rb +2 -2
- metadata +4 -33
- data/Gemfile +0 -6
- data/Gemfile.lock +0 -17
data/cowtech-lib.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{cowtech-lib}
|
8
|
-
s.version = "1.9.
|
8
|
+
s.version = "1.9.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Shogun"]
|
@@ -18,8 +18,6 @@ Gem::Specification.new do |s|
|
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
|
-
"Gemfile",
|
22
|
-
"Gemfile.lock",
|
23
21
|
"LICENSE.txt",
|
24
22
|
"README.rdoc",
|
25
23
|
"Rakefile",
|
@@ -42,15 +40,9 @@ Gem::Specification.new do |s|
|
|
42
40
|
s.specification_version = 3
|
43
41
|
|
44
42
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
45
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
|
46
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
47
43
|
else
|
48
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
49
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
50
44
|
end
|
51
45
|
else
|
52
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
53
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
54
46
|
end
|
55
47
|
end
|
56
48
|
|
data/lib/cowtech-lib.rb
CHANGED
@@ -22,8 +22,12 @@
|
|
22
22
|
# A copy of the GNU General Public License is available at: http://www.gnu.org/licenses/gpl.txt
|
23
23
|
#
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
module Cowtech
|
26
|
+
module Lib
|
27
|
+
autoload :Version, 'cowtech-lib/version'
|
28
|
+
autoload :Console, 'cowtech-lib/console'
|
29
|
+
autoload :OptionParser, 'cowtech-lib/option_parser'
|
30
|
+
autoload :Shell, 'cowtech-lib/shell'
|
31
|
+
autoload :Script, 'cowtech-lib/script'
|
32
|
+
end
|
33
|
+
end
|
data/lib/cowtech-lib/console.rb
CHANGED
@@ -26,289 +26,331 @@
|
|
26
26
|
#
|
27
27
|
|
28
28
|
require "rexml/document"
|
29
|
-
require "open4"
|
30
|
-
require "find"
|
31
|
-
require "fileutils"
|
32
29
|
|
33
30
|
class String
|
34
31
|
def to_a
|
35
32
|
[self]
|
36
33
|
end
|
37
34
|
end
|
35
|
+
|
36
|
+
class Hash
|
37
|
+
def method_missing(method, *arg)
|
38
|
+
# PER ORA SUPPORTIAMO SOLO I GETTER
|
39
|
+
self[method.to_sym]
|
40
|
+
end
|
38
41
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
class Console
|
44
|
-
public
|
45
|
-
|
46
|
-
# Indentation level
|
47
|
-
attr :indent_level
|
48
|
-
|
49
|
-
# Whether show executed commands
|
50
|
-
attr :show_commands
|
51
|
-
|
52
|
-
# Whether show output of executed commands
|
53
|
-
attr :show_outputs
|
54
|
-
|
55
|
-
# Whether simply print commands rather than executing them
|
56
|
-
attr :skip_commands
|
57
|
-
|
58
|
-
# Exit status for commands
|
59
|
-
attr_reader :statuses
|
60
|
-
|
61
|
-
# Indentation string(s)
|
62
|
-
attr :indentator, true
|
63
|
-
|
64
|
-
# Sets indentation level.
|
65
|
-
# Arguments:
|
66
|
-
# * <em>indent</em>: The new indentation level
|
67
|
-
# * <em></em>: If the level is absolute or relative to the current level
|
68
|
-
def indent_set(level, absolute = false)
|
69
|
-
@indent_level = Math.max((!absolute ? @indent_level : 0) + level, 0)
|
70
|
-
end
|
71
|
-
|
72
|
-
# Resets indentation level to 0.
|
73
|
-
def indent_reset
|
74
|
-
@indent_level = 0
|
75
|
-
end
|
42
|
+
def respond_to?(method)
|
43
|
+
self.has_key?(method.to_sym)
|
44
|
+
end
|
45
|
+
end
|
76
46
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
# Returns: The indentated message
|
91
|
-
def indent(msg, level = nil)
|
92
|
-
(@@indentator * (level || @indent_level)) + msg
|
93
|
-
end
|
94
|
-
|
95
|
-
=begin rdoc
|
96
|
-
Substitute tag with color.
|
97
|
-
|
98
|
-
Arguments:
|
99
|
-
* <em>node</em>: The node which operate on
|
100
|
-
* <em>stack</em>: The stack of old styles. <b>Do not set this by yourself!</b>
|
101
|
-
|
102
|
-
Returns: The new text
|
103
|
-
=end
|
104
|
-
def subst_color(node, stack = [])
|
105
|
-
rv = ""
|
106
|
-
styles = (node.name == "text" and node.attributes["style"]) ? node.attributes["style"].split(" ") : nil
|
107
|
-
|
108
|
-
# Add style of current tag
|
109
|
-
if styles then
|
110
|
-
styles.each do |style|
|
111
|
-
rv += @@styles[style] || ""
|
112
|
-
end
|
47
|
+
module Cowtech
|
48
|
+
module Lib
|
49
|
+
# A class which provides some method to operate with files and to format pretty messages.
|
50
|
+
# @author Shogun
|
51
|
+
class Console
|
52
|
+
# Indentation level
|
53
|
+
attr_accessor :indent_level
|
54
|
+
|
55
|
+
# Whether show executed commands
|
56
|
+
attr_accessor :show_commands
|
57
|
+
|
58
|
+
# Whether show output of executed commands
|
59
|
+
attr_accessor :show_outputs
|
113
60
|
|
114
|
-
|
61
|
+
# Whether simply print commands rather than executing them
|
62
|
+
attr_accessor :skip_commands
|
63
|
+
|
64
|
+
# Exit status for commands
|
65
|
+
attr_reader :statuses
|
66
|
+
|
67
|
+
# Indentation string(s)
|
68
|
+
attr_accessor :indentator
|
69
|
+
|
70
|
+
# Sets indentation level.
|
71
|
+
# Arguments:
|
72
|
+
# * <em>indent</em>: The new indentation level
|
73
|
+
# * <em></em>: If the level is absolute or relative to the current level
|
74
|
+
def indent_set(level, absolute = false)
|
75
|
+
@indent_level = [(!absolute ? @indent_level : 0) + level, 0].max
|
115
76
|
end
|
116
77
|
|
117
|
-
#
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
78
|
+
# Resets indentation level to 0.
|
79
|
+
def indent_reset
|
80
|
+
@indent_level = 0
|
81
|
+
end
|
82
|
+
|
83
|
+
# Execute codes in an indented block
|
84
|
+
def indent_region(level, absolute = false)
|
85
|
+
old_level = @indent_level
|
86
|
+
self.indent_set(level, absolute)
|
87
|
+
yield
|
88
|
+
@indent_level = old_level
|
124
89
|
end
|
125
90
|
|
126
|
-
#
|
127
|
-
|
128
|
-
|
91
|
+
# Indents a message.
|
92
|
+
#
|
93
|
+
# Arguments:
|
94
|
+
# * <em>msg</em>: The message to indent
|
95
|
+
# * <em>add_additional</em>: Whether add extra space to align to initial message "*"
|
96
|
+
# Returns: The indentated message
|
97
|
+
def indent(msg, level = nil)
|
98
|
+
(@@indentator * (level || @indent_level)) + msg
|
99
|
+
end
|
100
|
+
|
101
|
+
# Substitute tag with color.
|
102
|
+
#
|
103
|
+
# Arguments:
|
104
|
+
# * <em>node</em>: The node which operate on
|
105
|
+
# * <em>stack</em>: The stack of old styles. <b>Do not set this by yourself!</b>
|
106
|
+
#
|
107
|
+
# Returns: The new text
|
108
|
+
def parse_message(node, stack = [])
|
109
|
+
rv = ""
|
110
|
+
styles = (node.name == "text" and node.attributes["style"]) ? node.attributes["style"].split(" ") : nil
|
111
|
+
|
112
|
+
# Add style of current tag
|
113
|
+
if styles then
|
114
|
+
styles.each do |style|
|
115
|
+
rv += @@styles[style] || ""
|
116
|
+
end
|
117
|
+
|
118
|
+
stack.push(styles)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Now parse subnodes
|
122
|
+
node.children.each do |child|
|
123
|
+
if child.node_type == :text then
|
124
|
+
rv += child.to_s
|
125
|
+
elsif child.name == "text" then
|
126
|
+
rv += self.parse_message(child, stack)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Remove style of current tag
|
131
|
+
if styles then
|
132
|
+
stack.pop()
|
129
133
|
|
130
|
-
|
131
|
-
|
132
|
-
|
134
|
+
# Restore previous style
|
135
|
+
(stack.pop || ["default"]).each do |style|
|
136
|
+
rv += @@styles[style]
|
137
|
+
end
|
133
138
|
end
|
139
|
+
|
140
|
+
rv
|
134
141
|
end
|
135
|
-
|
136
|
-
rv
|
137
|
-
end
|
138
142
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
143
|
+
# Prints a message.
|
144
|
+
# Arguments:
|
145
|
+
# * <em>msg</em>: The message to print
|
146
|
+
# * <em>dots</em>: Whether add "..." to the message
|
147
|
+
# * <em>newline</em>: Whether add a newline to the message
|
148
|
+
# * <em>plain</em>: Whether ignore tags
|
149
|
+
# * <em>must_indent</em>: Whether indent the message
|
150
|
+
# * <em>internal</em>: If the method is called by another method. <b>Do not set this by yourself!</b>
|
151
|
+
def write(args)
|
152
|
+
msg = args[:msg]
|
153
|
+
|
154
|
+
# Check some alternative syntax
|
155
|
+
[:begin, :warn, :error, :debug, :info, :right, :end].each do |t|
|
156
|
+
if args[t] then
|
157
|
+
msg = args[t]
|
158
|
+
args[:type] = t
|
159
|
+
args[t] = nil
|
160
|
+
end
|
161
|
+
end
|
162
|
+
args[:fatal] = true if args[:status] == :fail
|
163
|
+
|
164
|
+
# Check for specific msg type
|
165
|
+
if [:begin, :warn, :error, :debug, :info].include?(args[:type]) then
|
166
|
+
mc = {:begin => "bold green", :warn => "bold yellow", :error => "bold red", :debug => "magenta", :info => "bold cyan"}
|
167
|
+
color = args[:color] || mc[args[:type]]
|
168
|
+
msg = !args[:full_color] ? "<text style=\"#{color}\">*</text> #{self.indent(msg)}" : "<text style=\"#{color}\">* #{self.indent(msg)}</text>"
|
169
|
+
end
|
170
|
+
|
171
|
+
# Add dots and indentation if needed
|
172
|
+
msg = self.indent(msg + (args.fetch(:dots, true) ? "..." : ""), args[:indent] ? @indent_level : 0)
|
173
|
+
|
174
|
+
# Parse the message
|
175
|
+
unless args[:plain] then
|
176
|
+
begin
|
177
|
+
xml = "<text>#{msg}</text>"
|
178
|
+
msg = self.parse_message(REXML::Document.new(xml).root)
|
179
|
+
rescue Exception => e
|
180
|
+
print "[ERROR] Invalid message tagging, check XML syntax (or color requested) of the following message:\n\n\t#{xml}\n\n"
|
181
|
+
print "\tThe errors was: #{e.message} (#{e.class.to_s})\n\n"
|
182
|
+
exit(1)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# Add newline if needed
|
187
|
+
msg += "\n" if args.fetch(:newline, true)
|
188
|
+
|
189
|
+
if args[:internal] then
|
190
|
+
msg
|
191
|
+
else
|
192
|
+
if [:end, :right].include?(args[:type]) then
|
193
|
+
# Get screen width
|
194
|
+
@tty_width = `tput cols`.to_i if @tty_width < 0
|
195
|
+
|
196
|
+
# Get padding
|
197
|
+
pad = @tty_width - msg.inspect.gsub(/(\\e\[[0-9]+m)|(\")|(\\n)/, "").length
|
198
|
+
|
199
|
+
print "\033[A" if args[:up]
|
200
|
+
print "\033[0G\033[#{pad}C"
|
201
|
+
end
|
202
|
+
|
203
|
+
print(msg)
|
204
|
+
end
|
205
|
+
|
206
|
+
exit(args[:code] || 0) if args[:exit_after] || args[:fatal]
|
156
207
|
end
|
157
|
-
|
158
|
-
|
159
|
-
#
|
160
|
-
|
161
|
-
|
162
|
-
color = args[:color] || mc[args[:type]]
|
208
|
+
|
209
|
+
# Syntatic sugar
|
210
|
+
# Prints a warning message.
|
211
|
+
def warn(msg, args = nil)
|
212
|
+
args ||= {}
|
163
213
|
|
164
|
-
if
|
165
|
-
|
214
|
+
if msg.is_a?(Hash) then
|
215
|
+
args.merge!(msg)
|
166
216
|
else
|
167
|
-
msg =
|
217
|
+
args[:msg] = msg
|
168
218
|
end
|
219
|
+
|
220
|
+
args[:warn] = args[:msg]
|
221
|
+
|
222
|
+
self.write(args)
|
169
223
|
end
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
print "[ERROR] Invalid message tagging, check XML syntax (or color requested) of the following message:\n\n\t#{msg}\n\n"
|
180
|
-
exit(1)
|
224
|
+
|
225
|
+
# Prints an error message.
|
226
|
+
def error(msg, args = nil)
|
227
|
+
args ||= {}
|
228
|
+
|
229
|
+
if msg.is_a?(Hash) then
|
230
|
+
args.merge!(msg)
|
231
|
+
else
|
232
|
+
args[:msg] = msg
|
181
233
|
end
|
234
|
+
|
235
|
+
args[:error] = args[:msg]
|
236
|
+
|
237
|
+
self.write(args)
|
182
238
|
end
|
183
239
|
|
184
|
-
#
|
185
|
-
msg
|
186
|
-
|
187
|
-
|
188
|
-
msg
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
@tty_width = `tput cols`.to_i if @tty_width < 0
|
193
|
-
|
194
|
-
# Get padding
|
195
|
-
pad = @tty_width - msg.inspect.gsub(/(\\e\[[0-9]+m)|(\")|(\\n)/, "").length
|
196
|
-
|
197
|
-
print "\033[A" if args[:up]
|
198
|
-
print "\033[0G\033[#{pad}C"
|
240
|
+
# Prints and error message then abort.
|
241
|
+
def fatal(msg, args = nil)
|
242
|
+
args ||= {}
|
243
|
+
|
244
|
+
if msg.is_a?(Hash) then
|
245
|
+
args.merge!(msg)
|
246
|
+
else
|
247
|
+
args[:msg] = msg
|
199
248
|
end
|
200
|
-
|
201
|
-
|
249
|
+
|
250
|
+
args[:error] = args[:msg]
|
251
|
+
args[:exit_after] = true
|
252
|
+
args[:code] ||= 1
|
253
|
+
|
254
|
+
self.write(args)
|
202
255
|
end
|
203
|
-
|
204
|
-
exit(args[:code] || 0) if args[:exit_after] || args[:fatal]
|
205
|
-
end
|
206
256
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
args[:warn] = msg
|
211
|
-
self.write(*args)
|
212
|
-
end
|
257
|
+
# Prints an error status
|
258
|
+
def status(status, args = nil)
|
259
|
+
args ||= {}
|
213
260
|
|
214
|
-
|
215
|
-
|
216
|
-
args[:error] = msg
|
217
|
-
self.write(*args)
|
218
|
-
end
|
219
|
-
|
220
|
-
# Prints and error message then abort.
|
221
|
-
def fatal(msg, *args)
|
222
|
-
args[:error] = msg
|
223
|
-
args[:exit_after] = true
|
224
|
-
args[:code] ||= 1
|
225
|
-
self.write(*args)
|
226
|
-
end
|
227
|
-
|
228
|
-
# Prints an error status
|
229
|
-
def status(*args)
|
230
|
-
args[:end] = @@statuses[status] || @@statuses[:ok]
|
231
|
-
self.write(*args)
|
232
|
-
end
|
233
|
-
|
234
|
-
# Read input from the user.
|
235
|
-
#
|
236
|
-
# Arguments:
|
237
|
-
# * <em>msg</em>: The prompt to show
|
238
|
-
# * <em>valids</em>: A list of regexp to validate the input
|
239
|
-
# * <em>case_sensitive</em>: Wheter the validation is case_sensitive
|
240
|
-
#
|
241
|
-
# Returns: The read input
|
242
|
-
def read(*args)
|
243
|
-
# Adjust prompt
|
244
|
-
msg = args[:msg] + (msg !~ /([:?](\s*))$/) ? ":" : "")
|
245
|
-
msg += " " unless msg =~ / ^/
|
246
|
-
|
247
|
-
# Turn choices into regular expressions
|
248
|
-
regexps = (args[:valids] || []).to_a.collect do |valid|
|
249
|
-
unless valid.is_a?(Regexp) then
|
250
|
-
valid = Regexp.new((valid !~ /^\^/ ? "^" : "") + valid + (valid !~ /\$$/ ? "$" : ""), Regexp::EXTENDED + (args[:case_sensitive] ? Regexp::IGNORECASE : 0), "U")
|
261
|
+
if status.is_a?(Hash) then
|
262
|
+
args.merge!(status)
|
251
263
|
else
|
252
|
-
|
264
|
+
args[:status] = status
|
253
265
|
end
|
266
|
+
|
267
|
+
status = status.is_a?(Hash) ? status[:status] : status
|
268
|
+
args[:end] = @@statuses[status] || @@statuses[:ok]
|
269
|
+
args[:dots] = false
|
270
|
+
args[:up] = true if args[:up] == nil
|
271
|
+
self.write(args)
|
254
272
|
end
|
255
273
|
|
256
|
-
|
257
|
-
|
258
|
-
#
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
274
|
+
# Read input from the user.
|
275
|
+
#
|
276
|
+
# Arguments:
|
277
|
+
# * <em>msg</em>: The prompt to show
|
278
|
+
# * <em>valids</em>: A list of regexp to validate the input
|
279
|
+
# * <em>case_sensitive</em>: Wheter the validation is case_sensitive
|
280
|
+
#
|
281
|
+
# Returns: The read input
|
282
|
+
def read(args)
|
283
|
+
# Adjust prompt
|
284
|
+
msg = args[:msg] + ((msg !~ /([:?](\s*))$/) ? ":" : "")
|
285
|
+
msg += " " unless msg =~ / ^/
|
286
|
+
|
287
|
+
# Turn choices into regular expressions
|
288
|
+
regexps = (args[:valids] || []).to_a.collect do |valid|
|
289
|
+
unless valid.is_a?(Regexp) then
|
290
|
+
valid = Regexp.new((valid !~ /^\^/ ? "^" : "") + valid + (valid !~ /\$$/ ? "$" : ""), Regexp::EXTENDED + (args[:case_sensitive] ? Regexp::IGNORECASE : 0), "U")
|
291
|
+
else
|
292
|
+
valid
|
293
|
+
end
|
270
294
|
end
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
295
|
+
|
296
|
+
rv = nil
|
297
|
+
|
298
|
+
# Read input
|
299
|
+
while true do
|
300
|
+
# Show message
|
301
|
+
print(msg)
|
302
|
+
|
303
|
+
# Get reply
|
304
|
+
bufs = gets.chop()
|
305
|
+
|
306
|
+
# If we don't have any regexp
|
307
|
+
if regexps.length == 0 then
|
275
308
|
rv = bufs
|
276
309
|
break
|
277
310
|
end
|
311
|
+
|
312
|
+
# Validate inputs
|
313
|
+
regexps.each do |re|
|
314
|
+
if bufs =~ re then
|
315
|
+
rv = bufs
|
316
|
+
break
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
break if rv
|
321
|
+
self.write(:warn => "Sorry, your reply was not understood. Please try again")
|
278
322
|
end
|
279
|
-
|
280
|
-
|
281
|
-
|
323
|
+
|
324
|
+
rv
|
325
|
+
end
|
326
|
+
|
327
|
+
# Create a new Console.
|
328
|
+
def initialize
|
329
|
+
@indent_level = 0
|
330
|
+
@show_commands = false
|
331
|
+
@show_outputs = false
|
332
|
+
@skip_commands = false
|
333
|
+
@tty_width = -1
|
334
|
+
@@indentator= " "
|
335
|
+
|
336
|
+
@@styles = {
|
337
|
+
# Default color
|
338
|
+
"default" => "\33[0m",
|
339
|
+
# Text style
|
340
|
+
"bold" => "\33[1m", "underline" => "\33[4m", "blink" => "\33[5m", "reverse" => "\33[7m", "concealed" => "\33[8m",
|
341
|
+
# Foreground colors
|
342
|
+
"black" => "\33[30m", "red" => "\33[31m", "green" => "\33[32m", "yellow" => "\33[33m", "blue" => "\33[34m", "magenta" => "\33[35m", "cyan" => "\33[36m", "white" => "\33[37m",
|
343
|
+
# Background colors
|
344
|
+
"bg_black" => "\33[40m", "bg_red" => "\33[41m", "bg_green" => "\33[42m", "bg_yellow" => "\33[43m", "bg_blue" => "\33[44m", "bg_magenta" => "\33[45m", "bg_cyan" => "\33[46m", "bg_white" => "\33[47m"
|
345
|
+
}
|
346
|
+
|
347
|
+
@@statuses = {
|
348
|
+
:ok => '<text style="bold blue">[ <text style="bold green">OK</text> ]</text> ',
|
349
|
+
:pass => '<text style="bold blue">[<text style="bold cyan">PASS</text>]</text> ',
|
350
|
+
:fail => '<text style="bold blue">[<text style="bold red">FAIL</text>]</text> ',
|
351
|
+
:warn => '<text style="bold blue">[<text style="bold yellow">WARN</text>]</text> ',
|
352
|
+
}
|
282
353
|
end
|
283
|
-
end
|
284
|
-
|
285
|
-
# Create a new Console.
|
286
|
-
def initialize
|
287
|
-
@indent_level = 0
|
288
|
-
@show_commands = false
|
289
|
-
@show_outputs = false
|
290
|
-
@skip_commands = false
|
291
|
-
@tty_width = -1
|
292
|
-
@@indentator= " "
|
293
|
-
|
294
|
-
@@styles = {
|
295
|
-
# Default color
|
296
|
-
"default" => "\33[0m",
|
297
|
-
# Text style
|
298
|
-
"bold" => "\33[1m", "underline" => "\33[4m", "blink" => "\33[5m", "reverse" => "\33[7m", "concealed" => "\33[8m",
|
299
|
-
# Foreground colors
|
300
|
-
"black" => "\33[30m", "red" => "\33[31m", "green" => "\33[32m", "yellow" => "\33[33m", "blue" => "\33[34m", "magenta" => "\33[35m", "cyan" => "\33[36m", "white" => "\33[37m",
|
301
|
-
# Background colors
|
302
|
-
"bg_black" => "\33[40m", "bg_red" => "\33[41m", "bg_green" => "\33[42m", "bg_yellow" => "\33[43m", "bg_blue" => "\33[44m", "bg_magenta" => "\33[45m", "bg_cyan" => "\33[46m", "bg_white" => "\33[47m"
|
303
|
-
}
|
304
|
-
|
305
|
-
@@statuses = {
|
306
|
-
:ok => '<text style="bold blue">[ <text style="bold green">OK</text> ]</text> ',
|
307
|
-
:pass => '<text style="bold blue">[<text style="bold cyan">PASS</text>]</text> ',
|
308
|
-
:fail => '<text style="bold blue">[<text style="bold red">FAIL</text>]</text> ',
|
309
|
-
:warn => '<text style="bold blue">[<text style="bold yellow">WARN</text>]</text> ',
|
310
|
-
}
|
311
354
|
end
|
312
355
|
end
|
313
|
-
end
|
314
|
-
|
356
|
+
end
|
@@ -25,9 +25,7 @@
|
|
25
25
|
# THE SOFTWARE.
|
26
26
|
#
|
27
27
|
|
28
|
-
require "ostruct"
|
29
28
|
require "getoptlong"
|
30
|
-
require "CowtechLib/Console"
|
31
29
|
|
32
30
|
module Cowtech
|
33
31
|
module Lib
|
@@ -35,7 +33,7 @@ module Cowtech
|
|
35
33
|
# @author Shogun
|
36
34
|
class OptionParser
|
37
35
|
# The specified options
|
38
|
-
|
36
|
+
attr_accessor :options
|
39
37
|
|
40
38
|
# The full command line provided
|
41
39
|
attr_reader :cmdline
|
@@ -68,10 +66,10 @@ module Cowtech
|
|
68
66
|
# * <em>:required</em>: Whether the option is required
|
69
67
|
# * <em>:priority</em>: Priority for the option. Used only on the help message to sort (by increasing priority) the options.
|
70
68
|
def <<(options)
|
71
|
-
options = options.
|
69
|
+
options = [options] unless options.is_a?(Array)
|
72
70
|
|
73
71
|
options.each do |option|
|
74
|
-
@console.fatal(:msg => "Every attribute must be an Hash.") unless option.
|
72
|
+
@console.fatal(:msg => "Every attribute must be an Hash.", :dots => false) unless option.is_a?(Hash)
|
75
73
|
|
76
74
|
# Use symbols for names
|
77
75
|
option[:name] = option[:name].to_sym
|
@@ -80,7 +78,7 @@ module Cowtech
|
|
80
78
|
option[:type] ||= :string
|
81
79
|
|
82
80
|
# Check if type is valid
|
83
|
-
@console.fatal(:msg => "Invalid option type #{option[:type]} for option #{option[:name]}. Valid type are the following:\n\t#{@@valid_types.keys.join(", ")}.") unless
|
81
|
+
@console.fatal(:msg => "Invalid option type #{option[:type]} for option #{option[:name]}. Valid type are the following:\n\t#{@@valid_types.keys.join(", ")}.", :dots => false) unless @@valid_types.keys.include?(option[:type])
|
84
82
|
|
85
83
|
# Adjust the default value
|
86
84
|
case option[:type]
|
@@ -93,13 +91,13 @@ module Cowtech
|
|
93
91
|
end
|
94
92
|
|
95
93
|
# Adjust priority
|
96
|
-
option[:priority] = option[:priority].to_s.to_i unless option[:priority].is_a(Integer)
|
94
|
+
option[:priority] = option[:priority].to_s.to_i unless option[:priority].is_a?(Integer)
|
97
95
|
|
98
96
|
# Prepend dashes
|
99
|
-
option[:short] = "-" + option[:short] unless option[:short]
|
97
|
+
option[:short] = "-" + option[:short] unless option[:short] =~ /^-/
|
100
98
|
while not option[:long] =~ /^--/ do option[:long] = "-" + option[:long] end
|
101
|
-
@console.fatal(:msg
|
102
|
-
@console.fatal(:msg
|
99
|
+
@console.fatal(:msg => "Invalid short form \"#{option[:short]}\".", :dots => false) unless option[:short] =~ /^-[0-9a-z]$/i
|
100
|
+
@console.fatal(:msg => "Invalid long form \"#{option[:long]}\".", :dots => false) unless option[:long] =~ /^--([0-9a-z-]+)$/i
|
103
101
|
|
104
102
|
# Check for choices if the type is choices
|
105
103
|
if option[:type] == :choice then
|
@@ -111,16 +109,16 @@ module Cowtech
|
|
111
109
|
end
|
112
110
|
|
113
111
|
# Check that action is a block if the type is action
|
114
|
-
@console.fatal(
|
112
|
+
@console.fatal("Option \"#{option[:name]}\" of type action requires a action block.") if option[:type] == :action && (option[:action] == nil || !option[:action].is_a?(Proc.class))
|
115
113
|
|
116
114
|
# Check for uniqueness of option and its forms
|
117
|
-
@console.fatal(
|
118
|
-
@console.fatal(
|
119
|
-
@console.fatal(
|
115
|
+
@console.fatal("An option with name \"#{option[:name]}\" already exists.", :dots => false) if @inserted[:name].include?(option[:name])
|
116
|
+
@console.fatal("An option with short or long form \"#{option[:short]}\" already exists.", :dots => false) if @inserted[:short].include?(option[:short])
|
117
|
+
@console.fatal("An option with short or long form \"#{option[:long]}\" already exists.", :dots => false) if @inserted[:long].include?(option[:long])
|
120
118
|
|
121
119
|
# Save
|
122
120
|
@options[option[:name]] = option
|
123
|
-
@options_map[
|
121
|
+
@options_map[option[:long]] = option[:name]
|
124
122
|
@inserted[:name].push(option[:name])
|
125
123
|
@inserted[:short].push(option[:short])
|
126
124
|
@inserted[:long].push(option[:long])
|
@@ -132,7 +130,8 @@ module Cowtech
|
|
132
130
|
# Arguments:
|
133
131
|
# * <em>ignore_unknown</em>: Whether ignore unknown options
|
134
132
|
# * <em>ignore_unknown</em>: Whether ignore help options
|
135
|
-
def parse(
|
133
|
+
def parse(args = nil)
|
134
|
+
args ||= {}
|
136
135
|
# Create options
|
137
136
|
noat = [:bool, :action]
|
138
137
|
sopts = @options.each_value.collect do |option| [option[:long], option[:short], noat.include?(option[:type]) ? GetoptLong::NO_ARGUMENT : GetoptLong::REQUIRED_ARGUMENT] end
|
@@ -146,34 +145,34 @@ module Cowtech
|
|
146
145
|
optname = @options_map[given]
|
147
146
|
option = @options[optname]
|
148
147
|
value = nil
|
148
|
+
|
149
149
|
|
150
150
|
# VALIDATE ARGUMENT DUE TO CASE
|
151
151
|
case option[:type]
|
152
152
|
when :string then
|
153
153
|
value = arg
|
154
154
|
when :int then
|
155
|
-
if arg.strip =~ /^(-?)(\d+)$/ then value = arg.to_i(10) else @console.fatal(:msg => "Argument of option \"#{given}\" must be an integer.") end
|
155
|
+
if arg.strip =~ /^(-?)(\d+)$/ then value = arg.to_i(10) else @console.fatal(:msg => "Argument of option \"#{given}\" must be an integer.", :dots => false) end
|
156
156
|
when :float then
|
157
|
-
if arg.strip =~ /^(-?)(\d*)(\.(\d+))?$/ and arg.strip() != "." then value = arg.to_f else @console.fatal(:msg => "Argument of option \"#{given}\" must be a float.") end
|
157
|
+
if arg.strip =~ /^(-?)(\d*)(\.(\d+))?$/ and arg.strip() != "." then value = arg.to_f else @console.fatal(:msg => "Argument of option \"#{given}\" must be a float.", :dots => false) end
|
158
158
|
when :choice then
|
159
|
-
if @options[optname].choices.find_index { |choice| arg =~ choice } then value = arg else @console.fatal(:msg => "Invalid argument (invalid choice) for option \"#{given}\".")
|
159
|
+
if @options[optname].choices.find_index { |choice| arg =~ choice } then value = arg else @console.fatal(:msg => "Invalid argument (invalid choice) for option \"#{given}\".", :dots => false) end
|
160
160
|
when :list then
|
161
161
|
value = arg.split(",")
|
162
162
|
else
|
163
163
|
value = true
|
164
164
|
end
|
165
165
|
|
166
|
-
@options[optname] = value
|
166
|
+
@options[optname][:value] = value
|
167
167
|
end
|
168
168
|
rescue StandardError => exception
|
169
|
-
|
170
|
-
|
171
|
-
given = "-" * $1.length
|
169
|
+
if exception.message =~ /.+-- (.+)$/ then
|
170
|
+
given = $1
|
172
171
|
|
173
|
-
if exception.
|
174
|
-
@console.fatal(:msg => "Unknown option \"#{given}\".") unless args[:ignore_unknown]
|
175
|
-
elsif exception.
|
176
|
-
@console.fatal(:msg => "Option \"
|
172
|
+
if exception.is_a?(GetoptLong::InvalidOption) then
|
173
|
+
@console.fatal(:msg => "Unknown option \"#{given}\".", :dots => false) unless args[:ignore_unknown]
|
174
|
+
elsif exception.is_a?(GetoptLong::MissingArgument) then
|
175
|
+
@console.fatal(:msg => "Option \"-#{given}\" requires an argument.", :dots => false)
|
177
176
|
end
|
178
177
|
else
|
179
178
|
@console.fatal("Unexpected error: #{exc.message}.")
|
@@ -184,7 +183,7 @@ module Cowtech
|
|
184
183
|
@args = ARGV
|
185
184
|
|
186
185
|
# CHECK IF HELP WAS REQUESTED
|
187
|
-
if self.provided?("help") and args[:ignore_help]
|
186
|
+
if self.provided?("help") and !args[:ignore_help] then
|
188
187
|
self.print_help
|
189
188
|
exit(0)
|
190
189
|
end
|
@@ -192,10 +191,11 @@ module Cowtech
|
|
192
191
|
# NOW CHECK IF SOME REQUIRED OPTION WAS NOT SPECIFIED OR IF WE HAVE TO EXECUTE AN ACTION
|
193
192
|
@inserted[:name].each do |key|
|
194
193
|
option = @options[key]
|
194
|
+
|
195
195
|
if option[:required] == true and option[:value] == nil then
|
196
|
-
@console.fatal(:msg => "Required option \"#{opt.name}\" not specified.")
|
196
|
+
@console.fatal(:msg => "Required option \"#{opt.name}\" not specified.", :dots => false)
|
197
197
|
elsif option[:value] == true and option[:type] == :action then
|
198
|
-
|
198
|
+
option.action.call
|
199
199
|
end
|
200
200
|
end
|
201
201
|
end
|
@@ -205,6 +205,7 @@ module Cowtech
|
|
205
205
|
# * <em>name</em>: Option name
|
206
206
|
# Returns: <em>true</em> if options is defined, <em>false</em> otherwise.
|
207
207
|
def exists?(name)
|
208
|
+
name = name.to_sym
|
208
209
|
@options.keys.include?(name)
|
209
210
|
end
|
210
211
|
|
@@ -213,7 +214,8 @@ module Cowtech
|
|
213
214
|
# * <em>name</em>: Option name
|
214
215
|
# Returns: <em>true</em> if options was provided, <em>false</em> otherwise.
|
215
216
|
def provided?(name)
|
216
|
-
|
217
|
+
name = name.to_sym
|
218
|
+
(@options[name] || {})[:value] != nil
|
217
219
|
end
|
218
220
|
|
219
221
|
# Get a list of value for the requested options.
|
@@ -238,15 +240,15 @@ module Cowtech
|
|
238
240
|
# * <em>options</em>: Options list
|
239
241
|
# Returns: If a single argument is provided, only a value is returned, else an hash (name => value). If no argument is provided, return every option
|
240
242
|
def [](*options)
|
241
|
-
options = [options] unless options.
|
242
|
-
options = @options.keys if
|
243
|
+
options = [options] unless options.is_a?(Array)
|
244
|
+
options = @options.keys if options.length == 0
|
243
245
|
|
244
246
|
if options.length == 1 then
|
245
247
|
self.get(options[0])
|
246
248
|
else
|
247
249
|
rv = {}
|
248
250
|
options.each do |option|
|
249
|
-
rv[option] = self.get(option) if self.exists?(option)
|
251
|
+
rv[option.to_s] = self.get(option) if self.exists?(option)
|
250
252
|
end
|
251
253
|
rv
|
252
254
|
end
|
@@ -263,21 +265,21 @@ module Cowtech
|
|
263
265
|
if @app_name then
|
264
266
|
print "#{@app_name}"
|
265
267
|
if @app_version > 0 then print " #{@app_version}" end
|
266
|
-
if @
|
268
|
+
if @description then print " - #{@description}" end
|
267
269
|
print "\n"
|
268
270
|
end
|
269
271
|
|
270
272
|
# Print usage
|
271
273
|
if @messages["pre_usage"] then print "#{@messages["pre_usage"]}\n" end
|
272
|
-
print "#{if @usage then @usage else "Usage: #{
|
274
|
+
print "#{if @usage then @usage else "Usage: #{ARGV[0]} [OPTIONS]" end}\n"
|
273
275
|
|
274
276
|
# Print pre_options
|
275
277
|
if @messages["pre_options"] then print "#{@messages["pre_options"]}\n" end
|
276
278
|
print "\nValid options are:\n"
|
277
279
|
|
278
280
|
# Order options for printing
|
279
|
-
@sorted_opts = @inserted[
|
280
|
-
@options[first]
|
281
|
+
@sorted_opts = @inserted[:name].sort do |first, second|
|
282
|
+
@options[first][:priority] != @options[second][:priority] ? @options[first][:priority] <=> @options[second][:priority] : @inserted[:name].index(first) <=> @inserted[:name].index(second)
|
281
283
|
end
|
282
284
|
|
283
285
|
# Add options, saving max length
|
@@ -286,9 +288,8 @@ module Cowtech
|
|
286
288
|
@sorted_opts.each do |key|
|
287
289
|
opt = @options[key]
|
288
290
|
|
289
|
-
popt = "#{[opt
|
290
|
-
popt += ("=" + (if opt
|
291
|
-
|
291
|
+
popt = "#{[opt[:short], opt[:long]].join(", ")}"
|
292
|
+
popt += ("=" + (if opt[:meta] then opt[:meta] else "ARG" end)) unless [:bool, :action].include?(opt[:type])
|
292
293
|
popts[key] = popt
|
293
294
|
maxlen = popt.length if popt.length > maxlen
|
294
295
|
end
|
@@ -296,7 +297,7 @@ module Cowtech
|
|
296
297
|
# Print options
|
297
298
|
@sorted_opts.each do |key|
|
298
299
|
val = popts[key]
|
299
|
-
print "\t#{val}#{" " * (5 + (maxlen - val.length))}#{@options[key]
|
300
|
+
print "\t#{val}#{" " * (5 + (maxlen - val.length))}#{@options[key][:help]}\n"
|
300
301
|
end
|
301
302
|
|
302
303
|
# Print post_options
|
@@ -314,22 +315,23 @@ module Cowtech
|
|
314
315
|
# * <em>:pre_usage</em>: Message to print before the usage string
|
315
316
|
# * <em>:pre_options</em>: Message to print before the options list
|
316
317
|
# * <em>:post_options</em>: Message to print after the options list
|
317
|
-
def initialize(
|
318
|
-
msgs = if msgs.length > 0 then msgs[0] else {} end
|
319
|
-
|
318
|
+
def initialize(args)
|
320
319
|
# Initialize types
|
321
320
|
@@valid_types = {:bool => [], :string => [String, ""], :int => [Integer, 0], :float => [Float, 0.0], :choice => [String, ""], :list => [Array, []], :action => []}
|
322
321
|
|
323
322
|
# Copy arguments
|
324
323
|
@app_name = args[:name]
|
325
|
-
@
|
326
|
-
@
|
324
|
+
@app_version = args[:version]
|
325
|
+
@description = args[:description]
|
327
326
|
@usage = args[:usage]
|
328
|
-
|
327
|
+
|
328
|
+
# Copy messages
|
329
|
+
messages = args[:messages] || {}
|
330
|
+
if messages.is_a?(Hash) then @messages = messages else @console.fatal(:msg => "CowtechLib::OptionParser::initialize msgs argument must be an hash.") end
|
329
331
|
|
330
332
|
# Initialize variables
|
331
|
-
@console =
|
332
|
-
@inserted = {:name => [], :short => [], :long => []
|
333
|
+
@console = Console.new
|
334
|
+
@inserted = {:name => [], :short => [], :long => []}
|
333
335
|
@options = {}
|
334
336
|
@options_map = {}
|
335
337
|
@args = []
|
data/lib/cowtech-lib/script.rb
CHANGED
@@ -25,18 +25,11 @@
|
|
25
25
|
# THE SOFTWARE.
|
26
26
|
#
|
27
27
|
|
28
|
-
require "pp"
|
29
|
-
require "rexml/document"
|
30
|
-
require "rubygems"
|
31
|
-
require "open4"
|
32
|
-
require "find"
|
33
|
-
require "CowtechLib/Console"
|
34
|
-
require "CowtechLib/OptionParser"
|
35
|
-
|
36
28
|
module Cowtech
|
37
29
|
module Lib
|
38
30
|
# Class which implements a script to execute general tasks.
|
39
31
|
# @author Shogun
|
32
|
+
|
40
33
|
class Script
|
41
34
|
# Console object
|
42
35
|
attr_reader :console
|
@@ -58,25 +51,25 @@ module Cowtech
|
|
58
51
|
# * <em>pre_usage</em>: Message to print before the usage string
|
59
52
|
# * <em>pre_options</em>: Message to print before the options list
|
60
53
|
# * <em>post_options</em>: Message to print after the options list
|
61
|
-
def initialize(
|
54
|
+
def initialize(args)
|
62
55
|
@console = Console.new
|
63
|
-
@shell =
|
64
|
-
@options_parser = OptionParser.new(
|
56
|
+
@shell = Shell.new(@console)
|
57
|
+
@options_parser = OptionParser.new(args)
|
65
58
|
|
66
59
|
self.add_options()
|
67
60
|
@options_parser << [
|
68
|
-
{:name => "command-echo", :short => "-z", :long => "--command-echo", :type => :bool, :help => "Show executed commands."}
|
69
|
-
{:name => "command-show", :short => "-V", :long => "--command-show", :type => :bool, :help => "Show executed commands' output."}
|
61
|
+
{:name => "command-echo", :short => "-z", :long => "--command-echo", :type => :bool, :help => "Show executed commands."},
|
62
|
+
{:name => "command-show", :short => "-V", :long => "--command-show", :type => :bool, :help => "Show executed commands' output."},
|
70
63
|
{:name => "command-skip", :short => "-Z", :long => "--command-skip", :type => :bool, :help => "Don't really execut commands, only print them."}
|
71
64
|
]
|
72
65
|
|
73
|
-
@options_parser.parse
|
66
|
+
@options_parser.parse
|
74
67
|
|
75
68
|
@console.show_commands = @options_parser["command-echo"]
|
76
69
|
@console.show_outputs = @options_parser["command-show"]
|
77
70
|
@console.skip_commands = @options_parser["command-skip"]
|
78
71
|
|
79
|
-
self.run
|
72
|
+
self.run
|
80
73
|
end
|
81
74
|
|
82
75
|
# Execute a task, showing a message.
|
@@ -87,36 +80,41 @@ module Cowtech
|
|
87
80
|
# * <em>show_end</em>: If show message exit status
|
88
81
|
# * <em>go_up</em>: If go up one line to show exit status
|
89
82
|
# * <em>dots</em>: If show dots after message
|
90
|
-
def task(
|
91
|
-
if args
|
92
|
-
@console.
|
93
|
-
@console.
|
83
|
+
def task(args)
|
84
|
+
if args.fetch(:show_msg, true) then
|
85
|
+
@console.write(:begin => args[:msg], :dots => args[:dots]) if args.fetch(:show_msg, true)
|
86
|
+
@console.indent_set(3)
|
94
87
|
end
|
95
88
|
|
96
89
|
# Run the block
|
97
|
-
rv = yield
|
90
|
+
rv = yield
|
91
|
+
rv = :ok unless rv.is_a?(Symbol)
|
92
|
+
rv = [rv, true] unless rv.is_a?(Array)
|
98
93
|
|
99
94
|
# Show the result
|
100
|
-
|
101
|
-
|
95
|
+
if args.fetch(:show_result, true) then
|
96
|
+
@console.status(:status => rv[0], :fatal => false) if args.fetch(:show_result, true)
|
97
|
+
@console.indent_set(-3)
|
98
|
+
end
|
99
|
+
|
100
|
+
exit(1) if rv[0] != :ok && rv[1]
|
102
101
|
end
|
103
102
|
|
104
103
|
# Run the script.
|
105
104
|
#<b> MUST BY OVERRIDEN BY SUBCLASSES!</b>
|
106
105
|
def run
|
107
|
-
self.console.fatal("Script
|
106
|
+
self.console.fatal("Cowtech::Lib::Script#run must be overidden by subclasses.")
|
108
107
|
end
|
109
108
|
|
110
109
|
# Adds the command line options.
|
111
110
|
# <b>MUST BE OVERRIDEN BY SUBCLASSES!</b>
|
112
111
|
def add_options
|
113
|
-
self.console.fatal("Cowtech::Lib::Script
|
112
|
+
self.console.fatal("Cowtech::Lib::Script#add_options must be overidden by subclasses.")
|
114
113
|
end
|
115
114
|
|
116
|
-
|
117
|
-
|
118
|
-
self.new.run
|
115
|
+
def get_binding
|
116
|
+
binding
|
119
117
|
end
|
120
118
|
end
|
121
119
|
end
|
122
|
-
end
|
120
|
+
end
|
data/lib/cowtech-lib/shell.rb
CHANGED
@@ -25,12 +25,11 @@
|
|
25
25
|
# THE SOFTWARE.
|
26
26
|
#
|
27
27
|
|
28
|
-
require "rexml/document"
|
29
28
|
require "open4"
|
30
29
|
require "find"
|
31
30
|
require "fileutils"
|
32
31
|
|
33
|
-
module
|
32
|
+
module Cowtech
|
34
33
|
module Lib
|
35
34
|
# A class which provides some useful method for interaction with files and processes.
|
36
35
|
# @author Shogun
|
@@ -45,11 +44,11 @@ module CowtechLib
|
|
45
44
|
# * <em>fatal</em>: If abort on failure
|
46
45
|
#
|
47
46
|
# Returns: An object which the status attribute is the exit status of the process, and the output attribute is the output of the command
|
48
|
-
def run(
|
47
|
+
def run(args)
|
49
48
|
rv = {:status => 0, :output => []}
|
50
49
|
command = args[:command]
|
51
50
|
|
52
|
-
@console.write(:begin => args[:msg]) if args[:
|
51
|
+
@console.write(:begin => args[:msg]) if args[:show_msg]
|
53
52
|
|
54
53
|
if @console.show_commands then
|
55
54
|
@console.warn("Will run command: \"#{command}\"", :dots => false)
|
@@ -66,7 +65,8 @@ module CowtechLib
|
|
66
65
|
end
|
67
66
|
rv[:output] = rv[:output].join("\n")
|
68
67
|
|
69
|
-
self.status(rv[:status] == 0 ? :ok : :fail) if args[:show_exit]
|
68
|
+
self.status(:status => rv[:status] == 0 ? :ok : :fail, :fatal => false) if args[:show_exit]
|
69
|
+
exit(1) if args[:fatal] and rv[:status] != 0
|
70
70
|
rv
|
71
71
|
end
|
72
72
|
|
@@ -78,9 +78,9 @@ module CowtechLib
|
|
78
78
|
# * <em>codec</em>: The encoding used to open the file. <b>UNUSED FOR NOW!</b>
|
79
79
|
#
|
80
80
|
# Returns: A new <em>File</em> object
|
81
|
-
def open_file(
|
81
|
+
def open_file(args)
|
82
82
|
begin
|
83
|
-
File.new(args[:name], args[:mode] || "r" + (args[:codec]
|
83
|
+
File.new(args[:name], (args[:mode] || "r") + (args[:codec] ? ":#{args[:codec]}" : ""))
|
84
84
|
rescue Exception => e
|
85
85
|
@console.write(:error => "Unable to open file #{name}: #{e}")
|
86
86
|
nil
|
@@ -103,9 +103,9 @@ module CowtechLib
|
|
103
103
|
# * <em>:fc_symlink</em>: Check if the file is symbolic link
|
104
104
|
#
|
105
105
|
# Returns: <em>true</em> if any of tests had success, <em>false</em> otherwise
|
106
|
-
def file_check?(
|
106
|
+
def file_check?(args)
|
107
107
|
rv = false
|
108
|
-
tests = args[:tests].to_a
|
108
|
+
tests = (args[:tests] || [:exists]).to_a
|
109
109
|
|
110
110
|
if args[:file] then
|
111
111
|
rv = true
|
@@ -125,7 +125,7 @@ module CowtechLib
|
|
125
125
|
# * <em>show_error</em>: Whether show errors occurred
|
126
126
|
#
|
127
127
|
# Returns: <em>true</em> if operation had success, <em>false</em> otherwise.
|
128
|
-
def delete_files!(
|
128
|
+
def delete_files!(args)
|
129
129
|
rv = true
|
130
130
|
files = args[:files].to_a
|
131
131
|
|
@@ -135,7 +135,7 @@ module CowtechLib
|
|
135
135
|
if args[:show_errors] == true then
|
136
136
|
if e.message =~ /^Permission denied - (.+)/ then
|
137
137
|
@console.error("Cannot remove following non writable entry: #{$1}", :dots => false, :fatal => args[:fatal])
|
138
|
-
elsif e.message =~ /^No such file or directory - (.+)/
|
138
|
+
elsif e.message =~ /^No such file or directory - (.+)/ then
|
139
139
|
@console.error("Cannot remove following non existent entry: #{$1}", :dots => false, :fatal => args[:fatal])
|
140
140
|
end
|
141
141
|
end
|
@@ -167,7 +167,7 @@ module CowtechLib
|
|
167
167
|
# * <em>show_error</em>: Whether show errors occurred
|
168
168
|
#
|
169
169
|
# Returns: <em>true</em> if operation had success, <em>false</em> otherwise.
|
170
|
-
def create_directories(
|
170
|
+
def create_directories(args)
|
171
171
|
rv = true
|
172
172
|
files = args[:files].to_a
|
173
173
|
|
@@ -223,7 +223,7 @@ module CowtechLib
|
|
223
223
|
# * <em>show_error</em>: Whether show errors occurred
|
224
224
|
#
|
225
225
|
# Returns: <em>true</em> if operation had success, <em>false</em> otherwise.
|
226
|
-
def copy(
|
226
|
+
def copy(args)
|
227
227
|
rv = true
|
228
228
|
move = args[:move]
|
229
229
|
|
@@ -248,7 +248,6 @@ module CowtechLib
|
|
248
248
|
rv = false
|
249
249
|
rescue Exception => e
|
250
250
|
if args[:show_errors] then
|
251
|
-
self.error(, false)
|
252
251
|
@console.error("Cannot #{if move then "move" else "copy" end} following entries to <text style=\"bold white\">#{dest}</text>:", :dots => false)
|
253
252
|
@console.indent_region(3) do
|
254
253
|
files.each do |afile|
|
@@ -302,7 +301,7 @@ module CowtechLib
|
|
302
301
|
# * <em>show_error</em>: Whether show errors occurred
|
303
302
|
#
|
304
303
|
# Returns: <em>true</em> if operation had success, <em>false</em> otherwise.
|
305
|
-
def rename(
|
304
|
+
def rename(args)
|
306
305
|
rv = true
|
307
306
|
|
308
307
|
if src.is_a?(String) and dst.is_a?(String) then
|
@@ -322,7 +321,7 @@ module CowtechLib
|
|
322
321
|
# * <em>patterns</em>: List of requested patterns
|
323
322
|
#
|
324
323
|
# Returns: List of found files.
|
325
|
-
def find_by_pattern(
|
324
|
+
def find_by_pattern(args)
|
326
325
|
# TODO: E se patterns è vuoto?
|
327
326
|
rv = []
|
328
327
|
|
@@ -362,12 +361,18 @@ module CowtechLib
|
|
362
361
|
# * <em>extensions</em>: List of requested extensions
|
363
362
|
#
|
364
363
|
# Returns: List of found files.
|
365
|
-
def find_by_extension(
|
364
|
+
def find_by_extension(args)
|
366
365
|
args[:patterns] = (args[:extensions] || "").to_a.collect do |extension|
|
367
366
|
Regexp.new(extension + "$", Regexp::IGNORECASE)
|
368
367
|
end
|
369
368
|
|
370
|
-
self.find_by_pattern(
|
369
|
+
self.find_by_pattern(args)
|
370
|
+
end
|
371
|
+
|
372
|
+
# Creates a new shell
|
373
|
+
def initialize(console = nil)
|
374
|
+
console ||= Console.new
|
375
|
+
@console = console
|
371
376
|
end
|
372
377
|
end
|
373
378
|
end
|
data/lib/cowtech-lib/version.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 9
|
8
|
-
-
|
9
|
-
version: 1.9.
|
8
|
+
- 1
|
9
|
+
version: 1.9.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Shogun
|
@@ -16,35 +16,8 @@ cert_chain: []
|
|
16
16
|
|
17
17
|
date: 2011-02-21 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
|
-
dependencies:
|
20
|
-
|
21
|
-
name: jeweler
|
22
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
-
none: false
|
24
|
-
requirements:
|
25
|
-
- - ~>
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
segments:
|
28
|
-
- 1
|
29
|
-
- 5
|
30
|
-
- 1
|
31
|
-
version: 1.5.1
|
32
|
-
type: :development
|
33
|
-
prerelease: false
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: rcov
|
37
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
-
none: false
|
39
|
-
requirements:
|
40
|
-
- - ">="
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
segments:
|
43
|
-
- 0
|
44
|
-
version: "0"
|
45
|
-
type: :development
|
46
|
-
prerelease: false
|
47
|
-
version_requirements: *id002
|
19
|
+
dependencies: []
|
20
|
+
|
48
21
|
description: A general purpose utility library.
|
49
22
|
email: shogun_panda@me.com
|
50
23
|
executables: []
|
@@ -56,8 +29,6 @@ extra_rdoc_files:
|
|
56
29
|
- README.rdoc
|
57
30
|
files:
|
58
31
|
- .document
|
59
|
-
- Gemfile
|
60
|
-
- Gemfile.lock
|
61
32
|
- LICENSE.txt
|
62
33
|
- README.rdoc
|
63
34
|
- Rakefile
|
data/Gemfile
DELETED
data/Gemfile.lock
DELETED