coulis 0.2.0 → 0.2.5

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