coulis 0.2.0 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/coulis.rb +55 -8
- data/test/coulis_test.rb +90 -0
- metadata +4 -4
data/lib/coulis.rb
CHANGED
@@ -2,7 +2,8 @@ require "timeout"
|
|
2
2
|
|
3
3
|
class Coulis
|
4
4
|
class << self
|
5
|
-
attr_accessor :_definitions, :
|
5
|
+
attr_accessor :_definitions, :_safe_args, :_help
|
6
|
+
attr_accessor :bin, :timeout, :no_double_dash, :safe_mode
|
6
7
|
|
7
8
|
def exec(*args, &block)
|
8
9
|
self.new.exec *args, &block
|
@@ -16,6 +17,10 @@ class Coulis
|
|
16
17
|
@bin = p.to_s
|
17
18
|
end
|
18
19
|
|
20
|
+
def _safe_mode(bool=true)
|
21
|
+
@safe_mode = bool
|
22
|
+
end
|
23
|
+
|
19
24
|
def _timeout(t)
|
20
25
|
@timeout = t
|
21
26
|
end
|
@@ -27,6 +32,30 @@ class Coulis
|
|
27
32
|
def adef(name, option=nil, &block)
|
28
33
|
(@_definitions||={})[name.to_sym] = (option || block )
|
29
34
|
end
|
35
|
+
|
36
|
+
def help(help_arg="--help")
|
37
|
+
return @_help if @_help && !@_help.empty?
|
38
|
+
|
39
|
+
@_help = options { @args = [help_arg] }.
|
40
|
+
exec.split("\n").map(&:strip)
|
41
|
+
end
|
42
|
+
|
43
|
+
def _safe_args(&block)
|
44
|
+
return @_safe_args if @_safe_args
|
45
|
+
@_safe_args ||= []
|
46
|
+
if block_given?
|
47
|
+
@_safe_args = instance_eval(&block)
|
48
|
+
else
|
49
|
+
help.each do |l|
|
50
|
+
args = l.scan(/(\-{1,2}[\w\-]+)[\W]/)
|
51
|
+
unless args.empty?
|
52
|
+
args.each{|a| @_safe_args << a.to_s}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
return @_safe_args.uniq!
|
58
|
+
end
|
30
59
|
end
|
31
60
|
|
32
61
|
attr_accessor :args
|
@@ -148,13 +177,19 @@ class Coulis
|
|
148
177
|
return self
|
149
178
|
end
|
150
179
|
|
151
|
-
|
152
|
-
|
153
|
-
|
180
|
+
if args[0].is_a?(Hash) # no value but options
|
181
|
+
full_arg = [ definition || arg_name ]
|
182
|
+
opts = args[0]
|
183
|
+
else
|
184
|
+
q = ""
|
185
|
+
q = "'" if args[0].to_s[0..0] != "'"
|
186
|
+
full_arg = [ definition || arg_name , "#{q}#{args[0]}#{q}" ]
|
187
|
+
opts = args[1]
|
188
|
+
end
|
154
189
|
|
155
|
-
insert_arg(full_arg,
|
190
|
+
insert_arg(full_arg, opts)
|
156
191
|
# delete doublon
|
157
|
-
if
|
192
|
+
if opts && opts.has_key?(:uniq)
|
158
193
|
uniq_arg(definition || arg_name)
|
159
194
|
end
|
160
195
|
self
|
@@ -167,7 +202,17 @@ class Coulis
|
|
167
202
|
self
|
168
203
|
end
|
169
204
|
|
205
|
+
def safe_arg?(argname)
|
206
|
+
# help parsing issue, so safe mode is off
|
207
|
+
return true if(self.class._safe_args || []).empty?
|
208
|
+
!self.class._safe_args.find{|a| a.to_s == argname.to_s}.nil?
|
209
|
+
end
|
210
|
+
|
170
211
|
def insert_arg(arg, opts=nil)
|
212
|
+
if self.class.safe_mode || (opts && opts[:safe] == true)
|
213
|
+
return unless safe_arg?(arg[0])
|
214
|
+
end
|
215
|
+
|
171
216
|
if !opts
|
172
217
|
@args << arg
|
173
218
|
return self
|
@@ -175,10 +220,12 @@ class Coulis
|
|
175
220
|
|
176
221
|
if arg_to_find = opts[:before] || opts[:after]
|
177
222
|
found = @args.find{|a|
|
178
|
-
a[0] == self.class._definitions[arg_to_find.to_sym] || arg_to_find
|
223
|
+
a[0] == (self.class._definitions[arg_to_find.to_sym] || arg_to_find)
|
179
224
|
}
|
225
|
+
|
180
226
|
if found && index = @args.index(found)
|
181
|
-
|
227
|
+
index+=1 if opts[:after]
|
228
|
+
@args.insert(index, arg)
|
182
229
|
end
|
183
230
|
else
|
184
231
|
@args << arg
|
data/test/coulis_test.rb
CHANGED
@@ -2,6 +2,8 @@ require "test/unit"
|
|
2
2
|
require "coulis"
|
3
3
|
|
4
4
|
class Ls < Coulis
|
5
|
+
_safe_args { help.to_s.match(/ls \[-([\w]+)\]/)[1].chars.to_a }
|
6
|
+
|
5
7
|
adef :all, "-a"
|
6
8
|
adef :human, "-h"
|
7
9
|
adef :full, "-a -h"
|
@@ -13,6 +15,7 @@ class FFMpeg < Coulis
|
|
13
15
|
end
|
14
16
|
|
15
17
|
class Ping < Coulis
|
18
|
+
_safe_args { ["-c"] }
|
16
19
|
_bin `whereis ping`.strip
|
17
20
|
adef :count, "-c"
|
18
21
|
end
|
@@ -25,6 +28,10 @@ class NSLookup < Coulis
|
|
25
28
|
end
|
26
29
|
end
|
27
30
|
|
31
|
+
class Curl < Coulis
|
32
|
+
_safe_mode
|
33
|
+
end
|
34
|
+
|
28
35
|
class SimpleCliTest < Test::Unit::TestCase
|
29
36
|
def teardown
|
30
37
|
#Ls.new.reset
|
@@ -33,6 +40,9 @@ class SimpleCliTest < Test::Unit::TestCase
|
|
33
40
|
|
34
41
|
def test_shit
|
35
42
|
#p Ls.options { full }
|
43
|
+
ls = Ls.options {
|
44
|
+
all :uniq => true
|
45
|
+
}
|
36
46
|
end
|
37
47
|
|
38
48
|
def test_default_bin
|
@@ -243,4 +253,84 @@ class SimpleCliTest < Test::Unit::TestCase
|
|
243
253
|
ffmpeg.input "video2.mp4", :before => "-y", :uniq => true
|
244
254
|
assert_equal "ffmpeg -i 'video2.mp4' -y 'out.avi'", ffmpeg.command
|
245
255
|
end
|
256
|
+
|
257
|
+
def test_arg_with_no_value_but_options
|
258
|
+
ls = Ls.options {
|
259
|
+
human
|
260
|
+
all :before => :human
|
261
|
+
}
|
262
|
+
assert_equal "ls -a -h", ls.command
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_list_safe_args
|
266
|
+
args = Ls._safe_args
|
267
|
+
assert_instance_of Array, args
|
268
|
+
assert args.size > 0
|
269
|
+
#p args
|
270
|
+
|
271
|
+
args = FFMpeg._safe_args
|
272
|
+
assert_instance_of Array, args
|
273
|
+
assert args.size > 0
|
274
|
+
#p args
|
275
|
+
|
276
|
+
args = Ping._safe_args
|
277
|
+
assert_instance_of Array, args
|
278
|
+
assert args.size > 0
|
279
|
+
#p args
|
280
|
+
|
281
|
+
args = Curl._safe_args
|
282
|
+
assert_instance_of Array, args
|
283
|
+
assert args.size > 0
|
284
|
+
#p args
|
285
|
+
end
|
286
|
+
|
287
|
+
def test_safe_mode_is_true_per_arg
|
288
|
+
ffmpeg = FFMpeg.options {
|
289
|
+
input "video.mp4"
|
290
|
+
nonexistingarg "nio", :safe => true
|
291
|
+
}
|
292
|
+
ffmpeg.fake_arg :safe => true
|
293
|
+
ffmpeg.fake_but_ok
|
294
|
+
|
295
|
+
args = [["nope1", "1"], ["nope2", "2"], ["-y", "output.avi"]]
|
296
|
+
args.each{|k,v| ffmpeg.send(k,v, :safe => true)}
|
297
|
+
assert_equal "ffmpeg -i 'video.mp4' -fake_but_ok -y 'output.avi'", ffmpeg.command
|
298
|
+
|
299
|
+
ping = Ping.options {
|
300
|
+
count 2, :safe => true
|
301
|
+
nope "no", :safe => true
|
302
|
+
nope2 "no2"
|
303
|
+
}
|
304
|
+
assert_equal "/sbin/ping -c '2' --nope2 'no2'", ping.command
|
305
|
+
end
|
306
|
+
|
307
|
+
def test_safe_mode_is_true_per_class
|
308
|
+
FFMpeg._safe_mode
|
309
|
+
ffmpeg = FFMpeg.options {
|
310
|
+
input "video.mp4"
|
311
|
+
nonexistingarg "nio"
|
312
|
+
}
|
313
|
+
assert_equal "ffmpeg -i 'video.mp4'", ffmpeg.command
|
314
|
+
|
315
|
+
curl = Curl.options {
|
316
|
+
request "POST"
|
317
|
+
data "test=ok"
|
318
|
+
url "http://mysite.com/test"
|
319
|
+
fake_arg "ok"
|
320
|
+
}
|
321
|
+
|
322
|
+
assert_equal "curl --request 'POST' --data 'test=ok' --url 'http://mysite.com/test'", curl.command
|
323
|
+
end
|
324
|
+
|
325
|
+
def test_safe_mode_is_off_if_help_parsing_issue
|
326
|
+
FFMpeg._safe_args = nil
|
327
|
+
FFMpeg._help = "ffmpeg help broken"
|
328
|
+
FFMpeg._safe_mode
|
329
|
+
|
330
|
+
ffmpeg = FFMpeg.options {
|
331
|
+
input "video.mp4"
|
332
|
+
nonexistingarg "nio"
|
333
|
+
}
|
334
|
+
assert_equal "ffmpeg -i 'video.mp4' -nonexistingarg 'nio'", ffmpeg.command
|
335
|
+
end
|
246
336
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coulis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 5
|
10
|
+
version: 0.2.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Bruno Celeste
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-07-
|
18
|
+
date: 2012-07-04 00:00:00 Z
|
19
19
|
dependencies: []
|
20
20
|
|
21
21
|
description: Simple but powerful CLI Wrapper
|