dotanuki 0.0.1 → 0.0.2
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/.autotest +2 -0
- data/.rspec +2 -0
- data/Rakefile +11 -1
- data/lib/dotanuki.rb +57 -20
- data/lib/dotanuki/version.rb +1 -1
- data/spec/dotanuki_spec.rb +40 -30
- metadata +4 -2
data/.autotest
ADDED
data/.rspec
ADDED
data/Rakefile
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
require 'bundler'
|
2
|
-
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
require 'metric_fu'
|
4
4
|
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
8
|
+
t.rspec_opts = "--color"
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "run autotest"
|
12
|
+
task :autotest do
|
13
|
+
system "autotest"
|
14
|
+
end
|
data/lib/dotanuki.rb
CHANGED
@@ -12,51 +12,80 @@ module Dotanuki
|
|
12
12
|
# class for the result of an execution of one or more commands
|
13
13
|
class ExecResult
|
14
14
|
attr_reader :stdout, :stderr, :status, :failed_index
|
15
|
-
def initialize
|
16
|
-
@stdout =
|
17
|
-
@stderr =
|
18
|
-
@status =
|
19
|
-
@failed_index =
|
15
|
+
def initialize
|
16
|
+
@stdout = []
|
17
|
+
@stderr = []
|
18
|
+
@status = 0
|
19
|
+
@failed_index = nil
|
20
20
|
end
|
21
21
|
|
22
|
+
# Returns true if the command has failed
|
22
23
|
def failed?
|
23
24
|
status != 0
|
24
25
|
end
|
25
26
|
|
27
|
+
# Returns stderr for the command that failed
|
26
28
|
def fail_message
|
27
29
|
stderr[@failed_index]
|
28
30
|
end
|
31
|
+
|
32
|
+
def add(stdout, stderr, status)
|
33
|
+
@stdout << stdout
|
34
|
+
@stderr << stderr
|
35
|
+
@status = status
|
36
|
+
if status.nil? || status != 0
|
37
|
+
@failed_index = @stdout.size - 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def <<(result)
|
42
|
+
raise ArgumentError unless result.is_a?(ExecResult)
|
43
|
+
add(result.stdout, result.stderr, result.status)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Execute commands in a block and return an array of ExecResult
|
48
|
+
#
|
49
|
+
# @example
|
50
|
+
# guard do
|
51
|
+
# execute "uname -a"
|
52
|
+
# execute "ls /does/not/exist"
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# TODO this is not thread safe
|
56
|
+
def guard(options={}, &block)
|
57
|
+
@guard = ExecResult.new
|
58
|
+
yield
|
59
|
+
clear_guard
|
60
|
+
rescue ExecError => e
|
61
|
+
puts "guard on duty"
|
62
|
+
clear_guard
|
29
63
|
end
|
30
64
|
|
31
65
|
# commands can be a string or an array of strings
|
32
66
|
def execute(commands, options={})
|
33
67
|
validate_options(options)
|
34
68
|
|
35
|
-
|
36
|
-
stderr = []
|
37
|
-
exit_status = 0
|
38
|
-
failed = nil
|
39
|
-
index = 0
|
69
|
+
result = ExecResult.new
|
40
70
|
|
41
71
|
[commands].flatten.each do |command|
|
42
|
-
|
43
|
-
stdout
|
44
|
-
|
45
|
-
exit_status = ex
|
46
|
-
if options[:on_error] == :exception
|
72
|
+
stdout, stderr, exit_status = _execute(command, options)
|
73
|
+
result.add(stdout, stderr, exit_status)
|
74
|
+
if options[:on_error] == :exception || @guard
|
47
75
|
if exit_status.nil?
|
76
|
+
@guard << result if @guard
|
48
77
|
raise ExecError, "#{command}: command not found"
|
49
78
|
elsif exit_status != 0
|
50
|
-
|
79
|
+
@guard << result if @guard
|
80
|
+
raise ExecError, stderr
|
51
81
|
end
|
52
82
|
elsif exit_status.nil? || exit_status != 0
|
53
|
-
failed = index
|
54
83
|
break
|
55
84
|
end
|
56
|
-
index += 1
|
57
85
|
end
|
86
|
+
@guard << result if @guard
|
58
87
|
|
59
|
-
return
|
88
|
+
return result
|
60
89
|
end
|
61
90
|
|
62
91
|
def _execute(command, options={})
|
@@ -74,9 +103,17 @@ module Dotanuki
|
|
74
103
|
def validate_options(options)
|
75
104
|
options.each do |option, value|
|
76
105
|
if option == :on_error && value != :exception
|
77
|
-
raise ArgumentError, "illegal value for option #{option}: #{value}"
|
106
|
+
raise ArgumentError, "illegal value for option #{option}: #{value}"
|
78
107
|
end
|
79
108
|
raise ArgumentError, "illegal option: #{option}" if option != :on_error
|
80
109
|
end
|
81
110
|
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def clear_guard
|
115
|
+
result = @guard
|
116
|
+
@guard = nil
|
117
|
+
result
|
118
|
+
end
|
82
119
|
end
|
data/lib/dotanuki/version.rb
CHANGED
data/spec/dotanuki_spec.rb
CHANGED
@@ -1,14 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Dotanuki do
|
4
|
-
|
5
|
-
class C
|
6
|
-
include Dotanuki
|
7
|
-
end
|
8
|
-
|
9
|
-
before :all do
|
10
|
-
@c = C.new
|
11
|
-
end
|
4
|
+
include Dotanuki
|
12
5
|
|
13
6
|
NON_EXISTING_PATH = "/not/an/existing/program"
|
14
7
|
COMMAND_NOT_FOUND = NON_EXISTING_PATH
|
@@ -17,101 +10,118 @@ describe Dotanuki do
|
|
17
10
|
EXISTING_PATH = "/"
|
18
11
|
EXISTING_COMMAND = "ls -d #{EXISTING_PATH}"
|
19
12
|
|
13
|
+
describe "guard" do
|
14
|
+
it "should collect all output" do
|
15
|
+
guard do
|
16
|
+
execute("id")
|
17
|
+
execute("ls")
|
18
|
+
end.stdout.size.should == 2
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should stop when one item fails" do
|
22
|
+
guard do
|
23
|
+
execute("id")
|
24
|
+
execute("ls /asd")
|
25
|
+
execute("uname -n")
|
26
|
+
end.failed_index.should == 1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
20
30
|
describe "execute" do
|
21
|
-
|
31
|
+
|
22
32
|
describe "missing command" do
|
23
33
|
it "should stop on first" do
|
24
|
-
r =
|
34
|
+
r = execute([COMMAND_NOT_FOUND, EXISTING_COMMAND])
|
25
35
|
r.failed_index.should == 0
|
26
36
|
end
|
27
37
|
|
28
38
|
it "should stop on last" do
|
29
|
-
r =
|
39
|
+
r = execute([EXISTING_COMMAND, COMMAND_NOT_FOUND])
|
30
40
|
r.failed_index.should == 1
|
31
41
|
end
|
32
42
|
|
33
43
|
it "should return nil when not found" do
|
34
|
-
|
44
|
+
execute([EXISTING_COMMAND, COMMAND_NOT_FOUND]).status.should be_nil
|
35
45
|
end
|
36
46
|
|
37
47
|
it "should return nil when not found" do
|
38
|
-
|
48
|
+
execute([COMMAND_NOT_FOUND, EXISTING_COMMAND]).status.should be_nil
|
39
49
|
end
|
40
50
|
end
|
41
51
|
|
42
52
|
describe "failing command" do
|
43
53
|
|
44
54
|
it "should stop when the first fails" do
|
45
|
-
r =
|
55
|
+
r = execute([COMMAND_FAILED, "id", "id"])
|
46
56
|
r.failed_index.should == 0
|
47
57
|
r.status.should_not == 0
|
48
58
|
end
|
49
59
|
|
50
60
|
it "should stop on failure" do
|
51
|
-
r =
|
61
|
+
r = execute(["id", COMMAND_FAILED, "id"])
|
52
62
|
r.failed_index.should == 1
|
53
63
|
r.status.should_not == 0
|
54
64
|
end
|
55
65
|
|
56
66
|
it "should stop when the last fails" do
|
57
|
-
r =
|
67
|
+
r = execute(["id", "id", COMMAND_FAILED])
|
58
68
|
r.failed_index.should == 2
|
59
69
|
r.status.should_not == 0
|
60
70
|
end
|
61
71
|
|
62
72
|
it "should not return 0" do
|
63
|
-
|
73
|
+
execute(COMMAND_FAILED).status.should_not == 0
|
64
74
|
end
|
65
75
|
|
66
76
|
it "should capture stderr" do
|
67
|
-
r =
|
77
|
+
r = execute(COMMAND_FAILED)
|
68
78
|
r.stderr[0].should == "ls: #{NON_EXISTING_PATH}: No such file or directory"
|
69
79
|
end
|
70
80
|
|
71
81
|
end
|
72
82
|
|
73
83
|
it "should return 0 when the command succeeds" do
|
74
|
-
|
84
|
+
execute("ls -d /").status.should == 0
|
75
85
|
end
|
76
|
-
|
86
|
+
|
77
87
|
it "should execute all commands in an array" do
|
78
|
-
r =
|
88
|
+
r = execute(["id", "ls -d /", "id"])
|
79
89
|
r.status.should == 0
|
80
90
|
r.stdout.size.should == 3
|
81
91
|
r.stderr.size.should == 3
|
82
92
|
end
|
83
|
-
|
93
|
+
|
84
94
|
it "should execute a single command" do
|
85
|
-
r =
|
95
|
+
r = execute("echo 'bar'")
|
86
96
|
r.status.should == 0
|
87
97
|
r.stdout.should == ["bar"]
|
88
98
|
r.stderr.should == [""]
|
89
99
|
end
|
90
|
-
|
100
|
+
|
91
101
|
it "should execute a single command" do
|
92
|
-
|
102
|
+
_execute("echo 'foo'").should == ["foo", "", 0]
|
93
103
|
end
|
94
104
|
|
95
105
|
describe "with exception option should throw an exception" do
|
96
106
|
it "on missing command" do
|
97
|
-
lambda {
|
107
|
+
lambda { execute(COMMAND_NOT_FOUND, {:on_error => :exception}) }.should raise_error Dotanuki::ExecError, "#{NON_EXISTING_PATH}: command not found"
|
98
108
|
end
|
99
109
|
|
100
110
|
it "exception failing" do
|
101
|
-
lambda {
|
111
|
+
lambda { execute(COMMAND_FAILED, {:on_error => :exception}) }.should raise_error Dotanuki::ExecError, "ls: #{NON_EXISTING_PATH}: No such file or directory"
|
102
112
|
end
|
103
113
|
end
|
104
114
|
|
105
115
|
it "should raise an error on invalid options" do
|
106
|
-
lambda {
|
116
|
+
lambda { execute(COMMAND_NOT_FOUND, {:on_error => :asd}) }.should raise_error ArgumentError
|
107
117
|
end
|
108
118
|
|
109
119
|
it "should raise an error on invalid option argument" do
|
110
|
-
lambda {
|
120
|
+
lambda { execute(COMMAND_NOT_FOUND, {:asd => :asd}) }.should raise_error ArgumentError
|
111
121
|
end
|
112
122
|
|
113
123
|
it "should supply correct info on a failing command" do
|
114
|
-
r =
|
124
|
+
r = execute("ls /asd")
|
115
125
|
r.failed?.should be_true
|
116
126
|
r.fail_message.should_not be_empty
|
117
127
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: dotanuki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Martin Englund
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-06-01 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -34,7 +34,9 @@ extensions: []
|
|
34
34
|
extra_rdoc_files: []
|
35
35
|
|
36
36
|
files:
|
37
|
+
- .autotest
|
37
38
|
- .gitignore
|
39
|
+
- .rspec
|
38
40
|
- Gemfile
|
39
41
|
- LICENSE
|
40
42
|
- README.md
|