dotanuki 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|