rprogram 0.2.3 → 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.
data/ChangeLog.md CHANGED
@@ -1,14 +1,36 @@
1
+ ### 0.3.0 / 2011-04-08
2
+
3
+ * Merged `RProgram::Nameable` into {RProgram::Program}.
4
+ * Merged `RProgram::Options` into {RProgram::Task}.
5
+ * Renamed `RProgram::Compat` to {RProgram::System}.
6
+ * Added {RProgram::System.arch}.
7
+ * Added {RProgram::System.platform}.
8
+ * Added {RProgram::System.windows?}.
9
+ * Added {RProgram::System.ruby_1_8?}.
10
+ * Added {RProgram::System.jruby?}.
11
+ * Added {RProgram::System.sudo_path}.
12
+ * Added {RProgram::System.sudo_path=}.
13
+ * Added {RProgram::System.sudo?}.
14
+ * Added {RProgram::Sudo}.
15
+ * Added {RProgram::SudoTask}.
16
+ * Allow passing tailing [exec-options](http://rubydoc.info/stdlib/core/1.9.2/Kernel#spawn-instance_method)
17
+ to {RProgram::System.run} (only supported on Ruby 1.9).
18
+ * Allow using `IO.popen` in {RProgram::System.run} if the `:popen` option
19
+ is specified (only available on Ruby 1.9).
20
+ * Allow specifying the environment variables in {RProgram::System.run}
21
+ if the `:env` option is specified (only available on Ruby 1.9).
22
+
1
23
  ### 0.2.3 / 2011-03-30
2
24
 
3
25
  * Require env ~> 0.1, >= 0.1.2.
4
26
  * Automatically search for programs with a `.exe` suffix, when running on
5
27
  Windows.
6
- * {RProgram::Compat.find_program} and {RProgram::Compat.find_program_by_names}
28
+ * `RProgram::Compat.find_program` and `RProgram::Compat.find_program_by_names`
7
29
  now return a `Pathname` object.
8
30
 
9
31
  ### 0.2.2 / 2011-01-22
10
32
 
11
- * Deprecated {RProgram::Compat.platform}.
33
+ * Deprecated `RProgram::Compat.platform`.
12
34
  * Use `File::PATH_SEPARATOR` to separate the `PATH` environment variable
13
35
  in `RProgram::Compat.paths`.
14
36
 
@@ -18,19 +40,19 @@
18
40
 
19
41
  ### 0.2.0 / 2010-10-03
20
42
 
21
- * Added {RProgram::Nameable::ClassMethods}.
22
- * Added {RProgram::Options::ClassMethods}.
23
- * Added {RProgram::Nameable::ClassMethods#path}:
43
+ * Added `RProgram::Nameable::ClassMethods`.
44
+ * Added `RProgram::Options::ClassMethods`.
45
+ * Added `RProgram::Nameable::ClassMethods#path`:
24
46
  * {RProgram::Program.find} will default to
25
- {RProgram::Nameable::ClassMethods#path} if set.
47
+ `RProgram::Nameable::ClassMethods#path` if set.
26
48
 
27
49
  ### 0.1.8 / 2009-12-24
28
50
 
29
51
  * Allow Program to run commands under sudo:
30
- * Added {RProgram::Compat.sudo}.
31
- * Added {RProgram::Task#sudo}.
32
- * Added {RProgram::Task#sudo=}.
33
- * Added {RProgram::Task#sudo?}.
52
+ * Added `RProgram::Compat.sudo`.
53
+ * Added `RProgram::Task#sudo`.
54
+ * Added `RProgram::Task#sudo=`.
55
+ * Added `RProgram::Task#sudo?`.
34
56
  * Added {RProgram::Program#sudo}.
35
57
 
36
58
  ### 0.1.7 / 2009-09-21
@@ -46,7 +68,7 @@
46
68
 
47
69
  * Use Hoe 2.2.0.
48
70
  * Removed requirement for 'open3'.
49
- * Renamed PRogram::Compat.PATHS to `RProgram::Compat.paths`.
71
+ * Renamed `PRogram::Compat.PATHS` to `RProgram::Compat.paths`.
50
72
  * Refactored {RProgram::Option#arguments}.
51
73
  * Removed `RProgram::Option#format`.
52
74
  * Refactored {RProgram::NonOption#arguments}.
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  * [Source](http://github.com/postmodern/rprogram)
4
4
  * [Issues](http://github.com/postmodern/rprogram/issues)
5
- * [Documentation](http://rubydoc.info/gems/rprogram)
5
+ * [Documentation](http://rubydoc.info/gems/rprogram/frames)
6
6
  * [Email](mailto:postmodern.mod3 at gmail.com)
7
7
 
8
8
  ## Description
@@ -14,8 +14,12 @@ system.
14
14
 
15
15
  ## Features
16
16
 
17
- * Uses Kernel.system for safe execution of individual programs and their
18
- separate command-line arguments.
17
+ * Safely executes individual programs and their separate command-line
18
+ arguments, to prevent command or option injection.
19
+ * Supports using Ruby 1.9 [exec options](http://rubydoc.info/stdlib/core/1.9.2/Kernel#spawn-instance_method).
20
+ * Supports specifying environment variables of a process
21
+ (only available on Ruby 1.9).
22
+ * Allows running programs with `IO.popen` (only available on Ruby 1.9).
19
23
  * Allows running programs under `sudo`.
20
24
  * Provides cross-platform access to the `PATH` environment variable.
21
25
  * Supports leading/tailing non-options.
@@ -1,14 +1,12 @@
1
1
  require 'rprogram/rprogram'
2
- require 'rprogram/compat'
2
+ require 'rprogram/system'
3
3
  require 'rprogram/task'
4
- require 'rprogram/nameable'
4
+ require 'rprogram/sudo_task'
5
5
  require 'rprogram/exceptions/program_not_found'
6
6
 
7
7
  module RProgram
8
8
  class Program
9
9
 
10
- include Nameable
11
-
12
10
  # Path to the program
13
11
  attr_reader :path
14
12
 
@@ -47,6 +45,87 @@ module RProgram
47
45
  block.call(self) if block
48
46
  end
49
47
 
48
+ #
49
+ # @return [String]
50
+ # The name of the program.
51
+ #
52
+ def self.program_name
53
+ @program_name ||= nil
54
+ end
55
+
56
+ #
57
+ # @return [Array]
58
+ # The program's aliases.
59
+ #
60
+ def self.program_aliases
61
+ @program_aliases ||= []
62
+ end
63
+
64
+ #
65
+ # Combines program_name with program_aliases.
66
+ #
67
+ # @return [Array]
68
+ # Names the program is known by.
69
+ #
70
+ def self.program_names
71
+ ([program_name] + program_aliases).compact
72
+ end
73
+
74
+ #
75
+ # Sets the program name for the class.
76
+ #
77
+ # @param [String, Symbol] name
78
+ # The new program name.
79
+ #
80
+ # @example
81
+ # name_program 'ls'
82
+ #
83
+ def self.name_program(name)
84
+ @program_name = name.to_s
85
+ end
86
+
87
+ #
88
+ # Sets the program aliases for the class.
89
+ #
90
+ # @param [Array] aliases
91
+ # The new program aliases.
92
+ #
93
+ # @example
94
+ # alias_program 'vim', 'vi'
95
+ #
96
+ def self.alias_program(*aliases)
97
+ @program_aliases = aliases.map { |name| name.to_s }
98
+ end
99
+
100
+ #
101
+ # The default path of the program.
102
+ #
103
+ # @return [String, nil]
104
+ # The path to the program.
105
+ #
106
+ # @since 0.2.0
107
+ #
108
+ def self.path
109
+ @program_path
110
+ end
111
+
112
+ #
113
+ # Sets the default path to the program.
114
+ #
115
+ # @param [String] new_path
116
+ # The new path to the program.
117
+ #
118
+ # @return [String, nil]
119
+ # The path to the program.
120
+ #
121
+ # @since 0.2.0
122
+ #
123
+ def self.path=(new_path)
124
+ @program_path = if new_path
125
+ File.expand_path(new_path)
126
+ end
127
+ end
128
+
50
129
  #
51
130
  # Creates a new program object.
52
131
  #
@@ -76,7 +155,7 @@ module RProgram
76
155
  # # => nil
77
156
  #
78
157
  def self.find_with_path(path,*arguments,&block)
79
- return self.new(path,*arguments,&block) if File.file?(path)
158
+ self.new(path,*arguments,&block) if File.file?(path)
80
159
  end
81
160
 
82
161
  #
@@ -111,7 +190,9 @@ module RProgram
111
190
  #
112
191
  def self.find_with_paths(paths,*arguments,&block)
113
192
  paths.each do |path|
114
- return self.new(path,*arguments,&block) if File.file?(path)
193
+ if File.file?(path)
194
+ return self.new(path,*arguments,&block)
195
+ end
115
196
  end
116
197
  end
117
198
 
@@ -145,7 +226,7 @@ module RProgram
145
226
  #
146
227
  def self.find(*arguments,&block)
147
228
  path = self.path
148
- path ||= Compat.find_program_by_names(*self.program_names)
229
+ path ||= System.find_program_by_names(*self.program_names)
149
230
 
150
231
  unless path
151
232
  names = self.program_names.map { |name| name.dump }.join(', ')
@@ -156,11 +237,54 @@ module RProgram
156
237
  return self.new(path,*arguments,&block)
157
238
  end
158
239
 
240
+ #
241
+ # @return [String]
242
+ # The program name of the class.
243
+ #
244
+ def program_name
245
+ self.class.program_name
246
+ end
247
+
248
+ #
249
+ # @return [Array]
250
+ # The program aliases of the class.
251
+ #
252
+ def program_aliases
253
+ self.class.program_aliases
254
+ end
255
+
256
+ #
257
+ # @return [Array]
258
+ # The program names of the class.
259
+ #
260
+ def program_names
261
+ self.class.program_names
262
+ end
263
+
159
264
  #
160
265
  # Runs the program.
161
266
  #
162
- # @param [Array] args
163
- # Addition arguments to run the program with.
267
+ # @overload run(*arguments)
268
+ # Run the program with the given arguments.
269
+ #
270
+ # @param [Array] arguments
271
+ # Additional arguments to run the program with.
272
+ #
273
+ # @overload run(*arguments,options)
274
+ # Run the program with the given arguments and options.
275
+ #
276
+ # @param [Array] arguments
277
+ # Additional arguments to run the program with.
278
+ #
279
+ # @param [Hash] options
280
+ # Additional options to execute the program with.
281
+ #
282
+ # @option options [Hash{String => String}] :env
283
+ # Environment variables to execute the program with.
284
+ #
285
+ # @option options [String] :popen
286
+ # Specifies to run the program using `IO.popen` with the given
287
+ # IO mode.
164
288
  #
165
289
  # @return [true, false]
166
290
  # Specifies the exit status of the program.
@@ -171,17 +295,34 @@ module RProgram
171
295
  # # hello
172
296
  # # => true
173
297
  #
174
- # @see Kernel.system
298
+ # @see http://rubydoc.info/stdlib/core/1.9.2/Kernel#spawn-instance_method
299
+ # For acceptable options.
175
300
  #
176
- def run(*args)
177
- Compat.run(@path,*args)
301
+ def run(*arguments)
302
+ System.run(@path,*arguments)
178
303
  end
179
304
 
180
305
  #
181
306
  # Runs the program under sudo.
182
307
  #
183
- # @param [Array] args
184
- # Additional arguments to run the program with.
308
+ # @overload sudo(*arguments)
309
+ # Run the program under `sudo` with the given arguments.
310
+ #
311
+ # @param [Array] arguments
312
+ # Additional arguments to run the program with.
313
+ #
314
+ # @overload sudo(*arguments,options)
315
+ # Run the program under `sudo` with the given arguments
316
+ # and options.
317
+ #
318
+ # @param [Array] arguments
319
+ # Additional arguments to run the program with.
320
+ #
321
+ # @param [Hash] options
322
+ # Additional options to execute the program with.
323
+ #
324
+ # @option options [Hash{Symbol => Object}] :sudo
325
+ # Additional `sudo` options.
185
326
  #
186
327
  # @return [Boolean]
187
328
  # Specifies whether the program exited successfully.
@@ -191,27 +332,76 @@ module RProgram
191
332
  #
192
333
  # @since 0.1.8
193
334
  #
194
- def sudo(*args)
195
- Compat.sudo(@path,*args)
335
+ # @see http://rubydoc.info/stdlib/core/1.9.2/Kernel#spawn-instance_method
336
+ # For acceptable options.
337
+ #
338
+ # @see SudoTask
339
+ # For valid `:sudo` options.
340
+ #
341
+ def sudo(*arguments)
342
+ options = if arguments.last.kind_of?(Hash)
343
+ arguments.pop
344
+ else
345
+ {}
346
+ end
347
+
348
+ task = SudoTask.new(options.delete(:sudo) || {})
349
+ task.command = [@path] + arguments
350
+
351
+ arguments = task.arguments
352
+ arguments << options unless options.empty?
353
+
354
+ return System.sudo(*arguments)
196
355
  end
197
356
 
198
357
  #
199
358
  # Runs the program with the arguments from the given task.
200
359
  #
201
- # @param [Task] task
360
+ # @param [Task, #to_a] task
202
361
  # The task who's arguments will be used to run the program.
203
362
  #
363
+ # @param [Hash] options
364
+ # Additional options to execute the program with.
365
+ #
204
366
  # @return [true, false]
205
367
  # Specifies the exit status of the program.
206
368
  #
207
- # @see Kernel.system
369
+ # @see #run
208
370
  #
209
- def run_task(task)
210
- if task.sudo?
211
- return sudo(*(task.arguments))
212
- else
213
- return run(*(task.arguments))
214
- end
371
+ def run_task(task,options={})
372
+ arguments = task.arguments
373
+ arguments << options unless options.empty?
374
+
375
+ return run(*arguments)
376
+ end
377
+
378
+ #
379
+ # Runs the program under `sudo` with the arguments from the given task.
380
+ #
381
+ # @param [Task, #to_a] task
382
+ # The task who's arguments will be used to run the program.
383
+ #
384
+ # @param [Hash] options
385
+ # Spawn options for the program to be ran.
386
+ #
387
+ # @yield [sudo]
388
+ # If a block is given, it will be passed the sudo task.
389
+ #
390
+ # @yieldparam [SudoTask] sudo
391
+ # The sudo tasks.
392
+ #
393
+ # @return [true, false]
394
+ # Specifies the exit status of the program.
395
+ #
396
+ # @see #sudo
397
+ #
398
+ # @since 0.3.0
399
+ #
400
+ def sudo_task(task,options={},&block)
401
+ arguments = task.arguments
402
+ arguments << options unless options.empty?
403
+
404
+ return sudo(*arguments,&block)
215
405
  end
216
406
 
217
407
  #
@@ -0,0 +1,14 @@
1
+ require 'rprogram/program'
2
+
3
+ module RProgram
4
+ #
5
+ # Represents the `sudo` executable.
6
+ #
7
+ # @since 0.3.0
8
+ #
9
+ class Sudo < Program
10
+
11
+ name_program 'sudo'
12
+
13
+ end
14
+ end
@@ -0,0 +1,68 @@
1
+ require 'rprogram/task'
2
+
3
+ module RProgram
4
+ #
5
+ # Represents the options for `sudo`.
6
+ #
7
+ # ## Sudo options:
8
+ #
9
+ # * `-A` - `sudo.ask_password`
10
+ # * `-b` - `sudo.background`
11
+ # * `-C` - `sudo.close_from`
12
+ # * `-E` - `sudo.preserve_env`
13
+ # * `-e` - `sudo.edit`
14
+ # * `-g` - `sudo.group`
15
+ # * `-H` - `sudo.home`
16
+ # * `-h` - `sudo.help`
17
+ # * `-i` - `sudo.simulate_initial_login`
18
+ # * `-k` - `sudo.kill`
19
+ # * `-K` - `sudo.sure_kill`
20
+ # * `-L` - `sudo.list_defaults`
21
+ # * `-l` - `sudo.list`
22
+ # * `-n` - `sudo.non_interactive`
23
+ # * `-P` - `sudo.preserve_group`
24
+ # * `-p` - `sudo.prompt`
25
+ # * `-r` - `sudo.role`
26
+ # * `-S` - `sudo.stdin`
27
+ # * `-s` - `sudo.shell`
28
+ # * `-t` - `sudo.type`
29
+ # * `-U` - `sudo.other_user`
30
+ # * `-u` - `sudo.user`
31
+ # * `-V` - `sudo.version`
32
+ # * `-v` - `sudo.validate`
33
+ #
34
+ # * `[command]` - `sudo.command`
35
+ #
36
+ # @since 0.3.0
37
+ #
38
+ class SudoTask < Task
39
+
40
+ short_option :name => :ask_password, :flag => '-A'
41
+ short_option :name => :background, :flag => '-b'
42
+ short_option :name => :close_from, :flag => '-C'
43
+ short_option :name => :preserve_env, :flag => '-E'
44
+ short_option :name => :edit, :flag => '-e'
45
+ short_option :name => :group, :flag => '-g'
46
+ short_option :name => :home, :flag => '-H'
47
+ short_option :name => :help, :flag => '-h'
48
+ short_option :name => :simulate_initial_login, :flag => '-i'
49
+ short_option :name => :kill, :flag => '-k'
50
+ short_option :name => :sure_kill, :flag => '-K'
51
+ short_option :name => :list_defaults, :flag => '-L'
52
+ short_option :name => :list, :flag => '-l'
53
+ short_option :name => :non_interactive, :flag => '-n'
54
+ short_option :name => :preserve_group, :flag => '-P'
55
+ short_option :name => :prompt, :flag => '-p'
56
+ short_option :name => :role, :flag => '-r'
57
+ short_option :name => :stdin, :flag => '-S'
58
+ short_option :name => :shell, :flag => '-s'
59
+ short_option :name => :type, :flag => '-t'
60
+ short_option :name => :other_user, :flag => '-U'
61
+ short_option :name => :user, :flag => '-u'
62
+ short_option :name => :version, :flag => '-V'
63
+ short_option :name => :validate, :flag => '-v'
64
+
65
+ non_option :tailing => true, :name => :command
66
+
67
+ end
68
+ end