runnable 0.2.4 → 0.3.0

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 (5) hide show
  1. data/README.markdown +41 -36
  2. data/VERSION +1 -1
  3. data/lib/runnable.rb +231 -213
  4. data/runnable.gemspec +4 -3
  5. metadata +61 -22
data/README.markdown CHANGED
@@ -5,10 +5,17 @@ A Ruby gem that allow programmer to control UNIX system commands as a Ruby class
5
5
  All you have to do is to create a class named exactly as command and make it
6
6
  inherit from class Runnable.
7
7
 
8
- class LS < Runnable
8
+ class LS
9
+ include Runnable
9
10
  end
10
11
 
11
12
  That gives you the basics to control the execution of ```ls``` command.
13
+ You can overwrite the name of the command by using the ```executes``` macro:
14
+ class MyLs
15
+ include Runnable
16
+
17
+ executes :ls
18
+ end
12
19
 
13
20
  Now you can create an instance like this:
14
21
 
@@ -23,53 +30,51 @@ for some important information about the command and its process. Entire
23
30
  documentation of this gem can be generated using ```yardoc```. To do this use
24
31
  ```rake doc```.
25
32
 
26
- ## Return values
27
- Runnable has two special methods which are called at the end of a command execution.
28
- ```:finish``` if commands finalized in a correct way and ```:fail``` if an error
29
- ocurred. In case something went wrong and a ```:fail``` method is called, Runnable
30
- also provide an array containing the command return value as the parameter of a
31
- SystemCallError exception and optionally others exceptions ocurred at runtime.
33
+ ## Custom output and exceptions
34
+ Runnable parse a set of user defined regular expresion to set up the command return
35
+ values.
32
36
 
33
37
  This is an example of how we can receive the return value of a command:
34
38
 
35
- class LS < Runnable
39
+ class Nmap
40
+ include Runnable
41
+
42
+ executes :nmap
36
43
 
37
- def finish
38
- puts "Everything went better than expected :)"
39
- end
44
+ define_command( :scan, :blocking => true ) { |ip, subnet| "-sP #{ip}/#{subnet}" }
45
+ scan_processors(
46
+ :exceptions => { /^Illegal netmask value/ => ArgumentError },
47
+ :outputs => { /Nmap scan report for (.*)/ => :ip }
48
+ )
49
+ end
40
50
 
41
- def failed( exceptions )
42
- puts "Something went wrong :("
43
- exceptions.each do |exception|
44
- puts exception.message
45
- end
46
- end
51
+ Nmap.new.scan("192.168.1.1", "24") # should return an array with the ips
47
52
 
48
- end
53
+ Runnable can also raise custom exceptions, using the previously Nmap defined class:
54
+ Nmap.new.scan("192.168.1.1", "1000")
55
+ Will raise an ArgumentError exception.
56
+ Note that Runnable will also raise an exception if the command returned value is not 0.
49
57
 
50
- my_command = LS.new
51
- my_command.run
58
+ ## Background usage
59
+ Runnable can be used with background process:
52
60
 
53
- ## Custom exceptions
54
- As we saw in previous chapter, if a command execution does not ends
55
- succesfully, Runnable fires a ```:fail``` event whit an exceptions array. We can
56
- add exceptions to that array based on the output of command. For example, we
57
- can controll that parameters passed to a command are valids if we know the
58
- command output for an invalid parameters.
61
+ class Ping
62
+ include Runnable
59
63
 
60
- First we have to do is override the method ```exceptions``` defined in runnable
61
- as follows
64
+ define_command( :goping, :blocking => false) { "-c5 www.google.es" }
62
65
 
63
- class LS < Runnable
64
- def exceptions
65
- { /ls: (invalid option.*)/ => ArgumentError }
66
- end
66
+ goping_processors(
67
+ :outputs => { /64 bytes from .* time=(.*) ms/ => :time }
68
+ )
67
69
  end
68
70
 
69
- ```exceptions``` method should return a hash containing a regular expression
70
- which will be match against the command output, and a value which will be the
71
- exception added to exception array. This means that if the command output match
72
- the regular expression, a new exception will be include in ```:fail``` event parameter.
71
+ p = Ping.new
72
+ p.goping
73
+
74
+ while p.running?
75
+ p p.output[:time]
76
+ sleep 1
77
+ end
73
78
 
74
79
  # About
75
80
  Runnable is a gem developed by [NoSoloSoftware](http://nosolosoftware.biz).
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.4
1
+ 0.3.0
data/lib/runnable.rb CHANGED
@@ -24,14 +24,97 @@ require 'fileutils'
24
24
  # you are able to start, define params and send signals (like kill, or stop)
25
25
  #
26
26
  # @example Usage:
27
- # class LS < Runnable
27
+ # class LS
28
+ # include Runnable
29
+ #
30
+ # executes :ls
28
31
  # command_style :extended
29
32
  # end
30
33
  #
31
34
  # ls = LS.new
32
35
  # ls.alh
33
36
  # ls.run
34
- class Runnable
37
+ module Runnable
38
+ def self.included(klass)
39
+ klass.extend ClassMethods
40
+ end
41
+
42
+ module ClassMethods
43
+ # Define the command to be executed
44
+ # @return [nil]
45
+ # @param [Symbol] command Command to be executed
46
+ def executes( cmd )
47
+ define_method( :command ) { cmd }
48
+ end
49
+
50
+ # Define the parameter style to be used.
51
+ # @return [nil]
52
+ def command_style( style )
53
+ define_method( :command_style ) { style }
54
+ end
55
+
56
+ # Create a user definde command
57
+ # @return [nil]
58
+ # @param [Symbol] name The user defined command name
59
+ # @param [Hash] options Options.
60
+ # @option options :blocking (false) Describe if the execution is blocking or non-blocking
61
+ # @option options :log_path (false) Path used to store logs # (dont store logs if no path specified)
62
+ def define_command( name, opts = {}, &block )
63
+ blocking = opts[:blocking] || false
64
+ log_path = opts[:log_path] || false
65
+
66
+ commands[name] = { :blocking => blocking }
67
+
68
+ define_method( name ) do |*args|
69
+ run name, block.call(*args), log_path
70
+ join if blocking
71
+ end
72
+ end
73
+
74
+ # Generic command processor. It allows to define generic processors used in all the
75
+ # user defined commands
76
+ # @param [Hash] opts Processing options
77
+ # @option opts :outputs (nil) Output processing Hash (regexp => output)
78
+ # @option opts :exceptions (nil) Exceptions processing Hash (regexp => exception)
79
+ def processors( opts = nil )
80
+ if opts.is_a? Hash
81
+ @processors = opts
82
+ else
83
+ @processors ||= Hash.new
84
+ end
85
+ end
86
+
87
+ # Method missing processing for the command processors
88
+ def method_missing( name, *opts )
89
+ raise NoMethodError.new( name.to_s ) unless name.to_s =~ /([a-z]*)_([a-z]*)/
90
+
91
+ # command_processors
92
+ if $2 == "processors"
93
+ commands[$1.to_sym][:outputs] = opts.first[:outputs]
94
+ commands[$1.to_sym][:exceptions] = opts.first[:exceptions]
95
+ end
96
+ end
97
+
98
+ # @group Accessors for the module class variables
99
+
100
+ # Returns the user defined commands
101
+ # @return [Hash] commands User defined commands
102
+ def commands
103
+ @commands ||= Hash.new
104
+ end
105
+
106
+ # Returns the list of runnable instances by pid
107
+ # @return [Hash] list of runnable instances by pid
108
+ def processes
109
+ @processes ||= Hash.new
110
+ end
111
+
112
+ # Processes writer
113
+ def processes=( value )
114
+ @processes = value
115
+ end
116
+ end
117
+
35
118
  # Process id.
36
119
  attr_reader :pid
37
120
  # Process owner.
@@ -41,137 +124,54 @@ class Runnable
41
124
  # Directory where process was called from.
42
125
  attr_reader :pwd
43
126
 
44
- # Input file
45
- attr_accessor :input
127
+ # Process output
128
+ attr_reader :output
46
129
 
47
- # Set the output file
48
- attr_accessor :output
130
+ # Process options
131
+ attr_accessor :options
132
+ # Process log output
133
+ attr_accessor :log_path
49
134
 
50
135
  # Metaprogramming part of the class
51
-
52
- # Define the parameter style to be used.
53
- # @return [nil]
54
- def self.command_style( style )
55
- define_method( :command_style ) do
56
- style
57
- end
58
- end
59
-
136
+
60
137
  # Parameter style used for the command.
61
138
  # @return [Symbol] Command style.
62
139
  def command_style
63
140
  :gnu
64
141
  end
65
142
 
66
- # List of runnable instances running on the system order by pid.
67
- @@processes = Hash.new
143
+ # Default command to be executed
144
+ # @return [String] Command to be executed
145
+ def command
146
+ self.class.to_s.split( "::" ).last.downcase
147
+ end
68
148
 
69
149
  # Constant to calculate cpu usage.
70
150
  HERTZ = 100
71
151
 
72
- # Create a new instance of a runnable command.
73
- # @param [Hash] option_hash Options.
74
- # @option option_hash :delete_log (true) Delete the log after execution.
75
- # @option option_hash :command_options ("") Command options.
76
- # @option option_hash :log_path ("/var/log/runnable") Path for the log files.
77
- def initialize( option_hash = {} )
78
- # keys :delete_log
79
- # :command_options
80
- # :log_path
81
-
82
- # If we have the command class in a namespace, we need to remove
83
- # the namespace name
84
- @command = self.class.to_s.split( "::" ).last.downcase
85
-
86
- # Set the default command option
87
- # Empty by default
88
- option_hash[:command_options] ||= ""
89
- @options = option_hash[:command_options]
90
-
91
- # Set the log path
92
- # Default path is "/var/log/runnable"
93
- option_hash[:log_path] ||= "/var/log/runnable/"
94
- @log_path = option_hash[:log_path]
95
-
96
- # Set the delete_log option
97
- # true by default
98
- if option_hash[:delete_log] == nil
99
- @delete_log = true
100
- else
101
- @delete_log = option_hash[:delete_log]
102
- end
103
-
104
- # Store input options
105
- @input = String.new
106
-
107
- # Store output options
108
- @output = String.new
109
-
110
- # Standar Outputs
111
- @std_output = {
112
- :out => "",
113
- :err => ""
114
- }
115
-
116
- # @todo: checks that command is in the PATH
117
- # ...
118
-
119
- # we dont set the pid, because we dont know until run
120
- @pid = nil
121
- @excep_array = []
122
-
123
-
124
- # Metaprogramming part
125
- # Create a new instance of the parser class
126
- @command_line_interface = Object.const_get( command_style.to_s.capitalize.to_sym ).new
127
- # End Metaprogramming part
128
-
129
- #End of initialize instance variables
130
-
131
- create_log_directory
132
- end
133
-
134
152
  # Start the execution of the command.
135
153
  # @return [nil]
136
- def run
154
+ def run(name = nil, opts = nil, log_path = nil)
155
+ return false if @pid
137
156
  # Create a new mutex
138
157
  @pid_mutex = Mutex.new
158
+
159
+ # Log path should be an instance variable to avoid a mess
160
+ @log_path = log_path || @log_path
139
161
 
140
162
  # Create pipes to redirect Standar I/O
141
163
  out_rd, out_wr = IO.pipe
142
164
  # Redirect Error I/O
143
165
  err_rd, err_wr = IO.pipe
144
-
166
+
145
167
  # Reset exceptions array to not store exceptions for
146
168
  # past executions
147
- @excep_array = []
148
-
149
- # Set up the command line
150
- command = []
151
- #command << @command
152
- command << @input.to_s
153
- command << @options.to_s
154
- command << @command_line_interface.parse
155
- command << @output.to_s
156
- #command = command.join( " " )
157
- command.flatten!
158
-
159
- command = command.select do |value|
160
- !value.to_s.strip.empty?
161
- end
162
- =begin
163
- # Debugging purpose
164
- puts "I: #{@input}"
165
- puts "OP: #{@options}"
166
- puts "CLI: #{@command_line_interface.parse}"
167
- puts "O: #{@output}"
168
- puts "C: #{command}"
169
- =end
170
- #@pid = Process.spawn( command, { :out => out_wr, :err => err_wr } )
171
- @pid = Process.spawn( @command, *command, { :out => out_wr, :err => err_wr } )
169
+ command_argument = opts ? opts.split(" ") : compose_command
170
+
171
+ @pid = Process.spawn( command.to_s, *command_argument, { :out => out_wr, :err => err_wr } )
172
172
 
173
173
  # Include instance in class variable
174
- @@processes[@pid] = self
174
+ self.class.processes[@pid] = self
175
175
 
176
176
  # Prepare the process info file to be read
177
177
  file_status = File.open( "/proc/#{@pid}/status" ).read.split( "\n" )
@@ -179,46 +179,36 @@ class Runnable
179
179
  @owner = file_status[6].split( " " )[1]
180
180
  # Group: Read the Group owner from /proc/@pid/status
181
181
  @group = file_status[7].split( " " )[1]
182
-
182
+
183
183
  # Set @output_thread with new threads
184
184
  # wich execute the input/ouput loop
185
- create_logs(:out => [out_wr, out_rd], :err => [err_wr, err_rd])
186
-
187
- # Create a new thread to avoid blocked processes
188
- @run_thread = Thread.new do
189
- # Wait to get the pid process even if it has finished
190
- Process.wait( @pid, Process::WUNTRACED )
185
+ stream_info = {
186
+ :out => [out_wr, out_rd],
187
+ :err => [err_wr, err_rd]
188
+ }
189
+
190
+ if name
191
+ cmd_info = self.class.commands[name]
192
+ stream_processors = {
193
+ :outputs => cmd_info[:outputs],
194
+ :exceptions => cmd_info[:exceptions]
195
+ }
196
+ end
191
197
 
192
- # Wait each I/O thread
193
- @output_threads.each { |thread| thread.join }
194
- # Delete log if its necesary
195
- delete_log
198
+ output_threads = process_streams( stream_info, stream_processors )
199
+
200
+ # Create a new thread to avoid blocked processes
201
+ @run_thread = threaded_process(@pid, output_threads)
196
202
 
197
- # Get the exit code from command
198
- exit_status = $?.exitstatus
199
-
200
- # In case of error add an Exception to the @excep_array
201
- @excep_array << SystemCallError.new( exit_status ) if exit_status != 0
202
-
203
- # Call methods according to the exit code
204
- if @excep_array.empty?
205
- finish
206
- else
207
- failed( @excep_array )
208
- end
209
-
210
- # This instance is finished and we remove it
211
- @@processes.delete( @pid )
212
- end
213
-
214
203
  # Satuts Variables
215
204
  # PWD: Current Working Directory get by /proc/@pid/cwd
216
205
  # @rescue If a fast process is runned there isn't time to get
217
206
  # the correct PWD. If the readlink fails, we retry, if the process still alive
218
207
  # until the process finish.
208
+
219
209
  begin
220
- @pwd = File.readlink( "/proc/#{@pid}/cwd" )
221
- rescue
210
+ @pwd ||= File.readlink( "/proc/#{@pid}/cwd" )
211
+ rescue Errno::ENOENT
222
212
  # If cwd is not available rerun @run_thread
223
213
  if @run_thread.alive?
224
214
  #If it is alive, we retry to get cwd
@@ -228,6 +218,8 @@ class Runnable
228
218
  #If process has terminated, we set pwd to current working directory of ruby
229
219
  @pwd = Dir.getwd
230
220
  end
221
+ rescue #Errno::EACCESS
222
+ @pwd = Dir.getwd
231
223
  end
232
224
  end
233
225
 
@@ -257,6 +249,7 @@ class Runnable
257
249
  # @return [nil]
258
250
  def join
259
251
  @run_thread.join if @run_thread.alive?
252
+ @output unless @output.empty?
260
253
  end
261
254
 
262
255
  # Check if prcess is running on the system.
@@ -268,13 +261,25 @@ class Runnable
268
261
  # Standar output of command
269
262
  # @return [String] Standar output
270
263
  def std_out
271
- @std_output[:out]
264
+ @std_out ||= ""
272
265
  end
273
266
 
274
267
  # Standar error output of the command
275
268
  # @return [String] Standar error output
276
269
  def std_err
277
- @std_output[:err]
270
+ @std_err ||= ""
271
+ end
272
+
273
+ # Sets the command input to be passed to the command execution
274
+ # @param [String] opt Command input
275
+ def input=( opt )
276
+ @command_input = opt
277
+ end
278
+
279
+ # Sets the command output to be passed to the command execution
280
+ # @param [String] opt Command output
281
+ def output=( opt )
282
+ @command_output = opt
278
283
  end
279
284
 
280
285
  # Calculate the estimated memory usage in Kb.
@@ -315,7 +320,6 @@ class Runnable
315
320
  # Seconds is Zero!
316
321
  0
317
322
  end
318
-
319
323
  end
320
324
 
321
325
  # Estimated bandwidth in kb/s.
@@ -354,6 +358,8 @@ class Runnable
354
358
  # @param [Block] block Block code in method
355
359
  # @return [nil]
356
360
  def method_missing( method, *params, &block )
361
+ @command_line_interface ||= Object.const_get( command_style.to_s.capitalize.to_sym ).new
362
+
357
363
  if params.length > 1
358
364
  super( method, params, block )
359
365
  else
@@ -363,8 +369,7 @@ class Runnable
363
369
  # @see parse_hash for more information
364
370
  parse_hash( params[0] )
365
371
  else
366
- @command_line_interface.add_param( method.to_s,
367
- params != nil ? params.join(",") : nil )
372
+ @command_line_interface.add_param( method.to_s, params != nil ? params.join(",") : nil )
368
373
  end
369
374
  end
370
375
  end
@@ -375,39 +380,6 @@ class Runnable
375
380
  @@processes
376
381
  end
377
382
 
378
- # @abstract
379
- # Returns a hash of regular expressions and exceptions associated to them.
380
- # Command output is match against those regular expressions, if it does match
381
- # an appropiate exception is included in the return value of execution.
382
- # @note This method should be overwritten in child classes.
383
- # @example Usage:
384
- # class ls < Runnable
385
- # def exceptions
386
- # { /ls: (invalid option.*)/ => ArgumentError }
387
- # end
388
- # end
389
- #
390
- # @return [Hash] Using regular expressions as keys and exceptions that should
391
- # be raised as values.
392
- def exceptions
393
- {}
394
- end
395
-
396
- # @abstract
397
- # Method called when command ends with no erros.
398
- # This method is a hook so it should be overwritten in child classes.
399
- # @return [nil]
400
- def finish
401
- end
402
-
403
- # @abstract
404
- # Method called when command executions fail.
405
- # This method is a hook so it should be overwritten in child classes.
406
- # @param [Array] exceptions Array containing exceptions raised during the command execution.
407
- # @return [nil]
408
- def failed( exceptions )
409
- end
410
-
411
383
  # Send the desired signal to the command.
412
384
  # @param [Symbol] Signal to be send to the command.
413
385
  # @todo raise ESRCH if pid is not in system
@@ -437,50 +409,24 @@ class Runnable
437
409
  end
438
410
 
439
411
  protected
440
- # Redirect command I/O to log files.
412
+ # Process the command I/O.
441
413
  # These files are located in /var/log/runnable.
442
414
  # @param [Hash] Outputs options.
443
415
  # @option outputs stream [Symbol] Stream name.
444
416
  # @option outputs pipes [IO] I/O stream to be redirected.
445
- # @return [nil]
446
- def create_logs( outputs = {} )
447
- # Create an empty file for logging
448
- FileUtils.touch "#{@log_path}#{@command}_#{@pid}.log"
417
+ # @return [Array] output_threads Array containing the output processing threads
418
+ def process_streams( output_streams = {}, stream_processors = nil )
419
+ @output = Hash.new
420
+ @std_output = Hash.new
449
421
 
450
- @output_threads = []
422
+ output_threads = []
451
423
  # for each io stream we create a thread wich read that
452
424
  # stream and write it in a log file
453
- outputs.each do |output_name, pipes|
454
- @output_threads << Thread.new do
455
- pipes[0].close
456
-
457
- @std_output[output_name] = ""
458
-
459
- pipes[1].each_line do |line|
460
- @std_output[output_name] << line
461
-
462
- File.open("#{@log_path}#{@command}_#{@pid}.log", "a") do |log_file|
463
- log_file.puts( "[#{Time.new.inspect} || [STD#{output_name.to_s.upcase} || [#{@pid}]] #{line}" )
464
- end
465
- # Match custom exceptions
466
- # if we get a positive match, add it to the exception array
467
- # in order to inform the user of what had happen
468
- exceptions.each do | reg_expr, value |
469
- @excep_array<< value.new( $1 ) if reg_expr =~ line
470
- end
471
- end
472
- end
425
+ output_streams.collect do |output_name, pipes|
426
+ threaded_output_processor(output_name, pipes, stream_processors)
473
427
  end
474
428
  end
475
429
 
476
- def create_log_directory
477
- Dir.mkdir( @log_path ) unless Dir.exist?( @log_path )
478
- end
479
-
480
- def delete_log
481
- File.delete( "#{@log_path}#{@command}_#{@pid}.log" ) if @delete_log == true
482
- end
483
-
484
430
  # Expand a parameter hash calling each key as method and value as param
485
431
  # forcing method misssing to be called.
486
432
  # @param [Hash] hash Parameters to be expand and included in command execution
@@ -488,10 +434,82 @@ class Runnable
488
434
  def parse_hash( hash )
489
435
  hash.each do |key, value|
490
436
  # Add the param parsed to command_line_interface
491
- @command_line_interface.add_param(
492
- key.to_s,
493
- value != nil ? value.to_s : nil
494
- )
437
+ @command_line_interface.add_param( key.to_s, value != nil ? value.to_s : nil )
495
438
  end
496
439
  end
440
+
441
+ private
442
+
443
+ def save_log(output_name, line)
444
+ Dir.mkdir( @log_path ) unless Dir.exist?( @log_path )
445
+
446
+ File.open("#{@log_path}/#{self.command}_#{@pid}.log", "a") do |log_file|
447
+ log_file.puts( "[#{Time.new.inspect} || [STD#{output_name.to_s.upcase} || [#{@pid}]] #{line}" )
448
+ end
449
+ end
450
+
451
+ def compose_command
452
+ @command_line_interface ||= Object.const_get( command_style.to_s.capitalize.to_sym ).new
453
+
454
+ [ @command_input.to_s,
455
+ @options.to_s,
456
+ @command_line_interface.parse,
457
+ @command_output.to_s
458
+ ].select do |value|
459
+ !value.to_s.strip.empty?
460
+ end.flatten.select{|x| !x.empty?}
461
+ end
462
+
463
+ def threaded_process(pid, output_threads)
464
+ Thread.new do
465
+ # Wait to get the pid process even if it has finished
466
+ Process.wait( pid, Process::WUNTRACED )
467
+
468
+ # Wait each I/O thread
469
+ output_threads.each { |thread| thread.join }
470
+
471
+ # Get the exit code from command
472
+ exit_status = $?.exitstatus
473
+
474
+ # This instance is finished and we remove it
475
+ self.class.processes.delete( pid )
476
+ @pid = nil
477
+
478
+ # In case of error add an Exception to the @excep_array
479
+ raise SystemCallError.new( exit_status ) if exit_status != 0
480
+ end
481
+ end
482
+
483
+ def threaded_output_processor(output_name, pipes, stream_processors)
484
+ exception_processors = stream_processors.is_a?(Hash) ? stream_processors[:exceptions] : {}
485
+ exception_processors.merge!(self.class.processors[:exceptions] || {})
486
+
487
+ output_processors = stream_processors.is_a?(Hash) ? stream_processors[:outputs] : {}
488
+ output_processors.merge!(self.class.processors[:output] || {})
489
+
490
+ Thread.new do
491
+ pipes[0].close
492
+
493
+ pipes[1].each_line do |line|
494
+ ( output_name == :err ? self.std_err : self.std_out ) << line
495
+
496
+ save_log(output_name, line) if @log_path
497
+
498
+ # Match custom exceptions
499
+ # if we get a positive match, raise the exception
500
+ exception_processors.each do | reg_expr, value |
501
+ raise value.new( line ) if reg_expr =~ line
502
+ end
503
+
504
+ # Match custom outputs
505
+ # if we get a positive match, add it to the outputs array
506
+ output_processors.each do | reg_expr, value |
507
+ @output[value] ||= Array.new
508
+ @output[value] << $1 if reg_expr =~ line
509
+ end
510
+
511
+ end
512
+ end
513
+ end
514
+
497
515
  end
data/runnable.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{runnable}
8
- s.version = "0.2.4"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Rafael García", "Luis Ciudad", "Pedro Navajas", "Javier Aranda"]
12
- s.date = %q{2011-10-27}
12
+ s.date = %q{2012-01-17}
13
13
  s.description = %q{Convert a executable command in a Ruby-like class you are able to start, define params and send signals (like kill, or stop)}
14
14
  s.email = ["rgarcia@nosolosoftware.biz", "lciudad@nosolosoftware.biz", "pnavajas@nosolosoftware.biz", "jaranda@nosolosoftware.biz"]
15
15
  s.extra_rdoc_files = [
@@ -28,10 +28,11 @@ Gem::Specification.new do |s|
28
28
  s.homepage = %q{http://github.com/nosolosoftware/runnable}
29
29
  s.licenses = ["GPL-3"]
30
30
  s.require_paths = ["lib"]
31
- s.rubygems_version = %q{1.6.2}
31
+ s.rubygems_version = %q{1.3.7}
32
32
  s.summary = %q{A Ruby gem for execute and control system commands}
33
33
 
34
34
  if s.respond_to? :specification_version then
35
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
35
36
  s.specification_version = 3
36
37
 
37
38
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
metadata CHANGED
@@ -1,86 +1,121 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: runnable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
5
- prerelease:
4
+ version: 0.3.0
5
+ segments:
6
+ - 0
7
+ - 3
8
+ - 0
9
+ prerelease: false
10
+ segments_generated: true
6
11
  platform: ruby
7
12
  authors:
8
13
  - Rafael García
9
14
  - Luis Ciudad
10
15
  - Pedro Navajas
11
16
  - Javier Aranda
12
- autorequire:
17
+ autorequire: !!null
13
18
  bindir: bin
14
19
  cert_chain: []
15
- date: 2011-10-27 00:00:00.000000000 +02:00
16
- default_executable:
20
+ date: 2012-01-17 00:00:00.000000000 +01:00
21
+ default_executable: !!null
17
22
  dependencies:
18
23
  - !ruby/object:Gem::Dependency
19
24
  name: rake
20
- requirement: &21080560 !ruby/object:Gem::Requirement
25
+ requirement: &32400380 !ruby/object:Gem::Requirement
21
26
  none: false
22
27
  requirements:
23
28
  - - ! '>='
24
29
  - !ruby/object:Gem::Version
25
30
  version: 0.8.7
31
+ segments:
32
+ - 0
33
+ - 8
34
+ - 7
35
+ segments_generated: true
26
36
  type: :development
27
37
  prerelease: false
28
- version_requirements: *21080560
38
+ version_requirements: *32400380
29
39
  - !ruby/object:Gem::Dependency
30
40
  name: yard
31
- requirement: &21079240 !ruby/object:Gem::Requirement
41
+ requirement: &32398960 !ruby/object:Gem::Requirement
32
42
  none: false
33
43
  requirements:
34
44
  - - ! '>='
35
45
  - !ruby/object:Gem::Version
36
46
  version: 0.6.8
47
+ segments:
48
+ - 0
49
+ - 6
50
+ - 8
51
+ segments_generated: true
37
52
  type: :development
38
53
  prerelease: false
39
- version_requirements: *21079240
54
+ version_requirements: *32398960
40
55
  - !ruby/object:Gem::Dependency
41
56
  name: rspec
42
- requirement: &21076920 !ruby/object:Gem::Requirement
57
+ requirement: &32397820 !ruby/object:Gem::Requirement
43
58
  none: false
44
59
  requirements:
45
60
  - - ! '>='
46
61
  - !ruby/object:Gem::Version
47
62
  version: 2.5.0
63
+ segments:
64
+ - 2
65
+ - 5
66
+ - 0
67
+ segments_generated: true
48
68
  type: :development
49
69
  prerelease: false
50
- version_requirements: *21076920
70
+ version_requirements: *32397820
51
71
  - !ruby/object:Gem::Dependency
52
72
  name: cucumber
53
- requirement: &21075340 !ruby/object:Gem::Requirement
73
+ requirement: &32396420 !ruby/object:Gem::Requirement
54
74
  none: false
55
75
  requirements:
56
76
  - - ! '>='
57
77
  - !ruby/object:Gem::Version
58
78
  version: 0.10.2
79
+ segments:
80
+ - 0
81
+ - 10
82
+ - 2
83
+ segments_generated: true
59
84
  type: :development
60
85
  prerelease: false
61
- version_requirements: *21075340
86
+ version_requirements: *32396420
62
87
  - !ruby/object:Gem::Dependency
63
88
  name: jeweler
64
- requirement: &21070000 !ruby/object:Gem::Requirement
89
+ requirement: &32388060 !ruby/object:Gem::Requirement
65
90
  none: false
66
91
  requirements:
67
92
  - - ! '>='
68
93
  - !ruby/object:Gem::Version
69
94
  version: 1.6.0
95
+ segments:
96
+ - 1
97
+ - 6
98
+ - 0
99
+ segments_generated: true
70
100
  type: :development
71
101
  prerelease: false
72
- version_requirements: *21070000
102
+ version_requirements: *32388060
73
103
  - !ruby/object:Gem::Dependency
74
104
  name: bluecloth
75
- requirement: &21067180 !ruby/object:Gem::Requirement
105
+ requirement: &32386220 !ruby/object:Gem::Requirement
76
106
  none: false
77
107
  requirements:
78
108
  - - ! '>='
79
109
  - !ruby/object:Gem::Version
80
110
  version: 2.1.0
111
+ segments:
112
+ - 2
113
+ - 1
114
+ - 0
115
+ segments_generated: true
81
116
  type: :development
82
117
  prerelease: false
83
- version_requirements: *21067180
118
+ version_requirements: *32386220
84
119
  description: Convert a executable command in a Ruby-like class you are able to start,
85
120
  define params and send signals (like kill, or stop)
86
121
  email:
@@ -105,7 +140,7 @@ has_rdoc: true
105
140
  homepage: http://github.com/nosolosoftware/runnable
106
141
  licenses:
107
142
  - GPL-3
108
- post_install_message:
143
+ post_install_message: !!null
109
144
  rdoc_options: []
110
145
  require_paths:
111
146
  - lib
@@ -117,17 +152,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
117
152
  version: '0'
118
153
  segments:
119
154
  - 0
120
- hash: -599557484973593353
155
+ segments_generated: true
156
+ hash: -3646317310813273179
121
157
  required_rubygems_version: !ruby/object:Gem::Requirement
122
158
  none: false
123
159
  requirements:
124
160
  - - ! '>='
125
161
  - !ruby/object:Gem::Version
126
162
  version: '0'
163
+ segments:
164
+ - 0
165
+ segments_generated: true
127
166
  requirements: []
128
- rubyforge_project:
129
- rubygems_version: 1.6.2
130
- signing_key:
167
+ rubyforge_project: !!null
168
+ rubygems_version: 1.3.7
169
+ signing_key: !!null
131
170
  specification_version: 3
132
171
  summary: A Ruby gem for execute and control system commands
133
172
  test_files: []