coulis 0.2.0 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/coulis.rb +55 -8
  2. data/test/coulis_test.rb +90 -0
  3. 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, :bin, :timeout, :no_double_dash
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
- q = ""
152
- q = "'" if args[0].to_s[0..0] != "'"
153
- full_arg = [ definition || arg_name , "#{q}#{args[0]}#{q}" ]
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, args[1])
190
+ insert_arg(full_arg, opts)
156
191
  # delete doublon
157
- if args[1] && args[1].has_key?(:uniq)
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
- @args.insert(index+1, arg)
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: 23
4
+ hash: 29
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 0
10
- version: 0.2.0
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-03 00:00:00 Z
18
+ date: 2012-07-04 00:00:00 Z
19
19
  dependencies: []
20
20
 
21
21
  description: Simple but powerful CLI Wrapper