dotanuki 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,6 @@
1
1
  *.gem
2
2
  .bundle
3
+ .yardoc
3
4
  Gemfile.lock
4
- pkg/*
5
+ pkg
6
+ doc
data/README.md CHANGED
@@ -6,17 +6,17 @@ failed commands.
6
6
 
7
7
  Examples
8
8
  ========
9
- In the following example, if the mkdir fails, none of the other commands will
9
+ In the following example, if the `mkdir` fails, none of the other commands will
10
10
  be executed.
11
11
 
12
- class Foo
13
- include 'dotanuki'
12
+ class Example
13
+ include Dotanuki
14
14
 
15
15
  def test
16
16
  commands = [
17
17
  "mkdir /tmp/foo",
18
- "cd /tmp/foo",
19
- "cp /etc/hosts ."
18
+ "cp /etc/hosts /tmp/foo",
19
+ "cp /etc/passwd /tmp/foo"
20
20
  ]
21
21
 
22
22
  result = execute(commands)
@@ -25,3 +25,16 @@ be executed.
25
25
  end
26
26
  end
27
27
  end
28
+
29
+ It can also be used with a `guard` block, which will raise an `ExecError` if a command fails.
30
+
31
+ class Example
32
+ include Dotanuki
33
+ def test
34
+ guard do
35
+ execute "mkdir /tmp/foo"
36
+ execute "cp /etc/hosts /tmp/foo"
37
+ execute "cp /etc/passwd /tmp/foo"
38
+ end
39
+ end
40
+ end
@@ -1,3 +1,4 @@
1
1
  module Dotanuki
2
- VERSION = "0.0.3"
2
+ # gem version
3
+ VERSION = "0.0.4"
3
4
  end
data/lib/dotanuki.rb CHANGED
@@ -1,17 +1,40 @@
1
1
  require 'popen4'
2
2
 
3
+ # Module intented to be included into classes which execute system commands
4
+ # @author Martin Englund
3
5
  module Dotanuki
4
6
 
5
- # thrown when an execution error occurs
7
+ # Error raised when an execution error occurs
6
8
  class ExecError < StandardError
7
- def initialize(msg)
8
- super(msg)
9
+ # Create a new ExecError
10
+ #
11
+ # @param [String] message error message
12
+ def initialize(message)
13
+ super(message)
9
14
  end
10
15
  end
11
16
 
12
- # class for the result of an execution of one or more commands
17
+ # Result of one or more command executions
13
18
  class ExecResult
14
- attr_reader :stdout, :stderr, :status, :failed_index
19
+
20
+ # Array of stdout from each command executed
21
+ # @return [Array]
22
+ attr_reader :stdout
23
+
24
+ # Array of stderr from each command executed
25
+ # @return [Array]
26
+ attr_reader :stderr
27
+
28
+ # Exit status of the command that failed, nil if the command was not found
29
+ # and 0 if all commands succeeded
30
+ #
31
+ # @return [Fixnum]
32
+ attr_reader :status
33
+
34
+ # Index of the command that failed, or nil if all commands succeeded
35
+ # @return [Fixnum]
36
+ attr_reader :failed_index
37
+
15
38
  def initialize
16
39
  @stdout = []
17
40
  @stderr = []
@@ -19,7 +42,7 @@ module Dotanuki
19
42
  @failed_index = nil
20
43
  end
21
44
 
22
- # Returns true if the command has failed
45
+ # Returns true if a command has failed
23
46
  def failed?
24
47
  status != 0
25
48
  end
@@ -29,15 +52,17 @@ module Dotanuki
29
52
  stderr[@failed_index]
30
53
  end
31
54
 
55
+ # Add the result of a command execution
32
56
  def add(stdout, stderr, status)
33
57
  @stdout << stdout
34
58
  @stderr << stderr
35
- @status = status
36
59
  if status.nil? || status != 0
60
+ @status = status
37
61
  @failed_index = @stdout.size - 1
38
62
  end
39
63
  end
40
64
 
65
+ # Add another [ExecResult] to this
41
66
  def <<(result)
42
67
  raise ArgumentError unless result.is_a?(ExecResult)
43
68
  # TODO merge correctly
@@ -45,24 +70,30 @@ module Dotanuki
45
70
  end
46
71
  end
47
72
 
73
+ # Default options for executing commands
74
+ DEFAULT_OPTIONS = {:on_error => :exception}
75
+
76
+ # @param [Hash] options the options for error handling
77
+ # @option options [Symbol] :on_error How to handle errors,
78
+ # can be either `:exception` or `:silent`
48
79
  def initialize(options={})
49
- @defaults = {}
50
- @defaults[:on_error] = :exception
51
- @defaults.merge!(options)
80
+ @defaults = DEFAULT_OPTIONS.merge(options)
52
81
  end
53
82
 
54
- # Execute commands in a block and return an array of ExecResult
83
+ # Execute commands wrapped in a block
55
84
  #
85
+ # @param [Hash] options (see #guard)
86
+ # @return [ExecResult]
56
87
  # @example
57
88
  # guard do
58
89
  # execute "uname -a"
59
90
  # execute "ls /does/not/exist"
60
91
  # end
61
- #
62
- # TODO this is not thread safe
92
+ # @note this method isn't thread safe
63
93
  def guard(options={}, &block)
64
94
  opts = @defaults.merge(options)
65
95
  validate_options(opts)
96
+ # TODO this is not thread safe
66
97
  @guard = ExecResult.new
67
98
  yield
68
99
  clear_guard
@@ -72,14 +103,18 @@ module Dotanuki
72
103
  result
73
104
  end
74
105
 
75
- # commands can be a string or an array of strings
106
+ # Execute one or more commands
107
+ #
108
+ # @param [String, Array] commands string or array containing the command to be executed
109
+ # @param [Hash] options (see #guard)
110
+ # @return [ExecResult]
76
111
  def execute(commands, options={})
77
112
  validate_options(options)
78
113
 
79
114
  result = ExecResult.new
80
115
 
81
116
  [commands].flatten.each do |command|
82
- stdout, stderr, exit_status = _execute(command, options)
117
+ stdout, stderr, exit_status = _execute(command)
83
118
  result.add(stdout, stderr, exit_status)
84
119
  if options[:on_error] == :exception || @guard
85
120
  if exit_status.nil?
@@ -98,7 +133,12 @@ module Dotanuki
98
133
  return result
99
134
  end
100
135
 
101
- def _execute(command, options={})
136
+ # Execute a single command
137
+ #
138
+ # @param [String] command string containing the command to be executed
139
+ # @return [String, String, Fixnum] standard out, standard error and exit
140
+ # status of the command
141
+ def _execute(command)
102
142
  stdout = stderr = ""
103
143
 
104
144
  status =
@@ -110,6 +150,9 @@ module Dotanuki
110
150
  return stdout, stderr, status ? status.exitstatus : status
111
151
  end
112
152
 
153
+ # Validates options for Dotanuki#execute or Dotanuki#guard
154
+ #
155
+ # @raise [ArgumentError] if an unknown option is given
113
156
  def validate_options(options)
114
157
  options.each do |option, value|
115
158
  if option == :on_error && ! [:exception, :silent].include?(value)
@@ -121,6 +164,7 @@ module Dotanuki
121
164
 
122
165
  private
123
166
 
167
+ # TODO this is not thread safe
124
168
  def clear_guard
125
169
  result = @guard
126
170
  @guard = nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dotanuki
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -14,7 +14,7 @@ default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: popen4
17
- requirement: &2157101940 !ruby/object:Gem::Requirement
17
+ requirement: &2161180600 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *2157101940
25
+ version_requirements: *2161180600
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: rspec
28
- requirement: &2157101500 !ruby/object:Gem::Requirement
28
+ requirement: &2161180020 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *2157101500
36
+ version_requirements: *2161180020
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: metric_fu
39
- requirement: &2157100960 !ruby/object:Gem::Requirement
39
+ requirement: &2161179480 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,7 +44,7 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *2157100960
47
+ version_requirements: *2161179480
48
48
  description: A command executioner which doesn't blindly stumble on when a command
49
49
  fails'
50
50
  email: