dotanuki 0.0.3 → 0.0.4

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