command-runner 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +10 -0
- data/lib/command/runner/backends/backticks.rb +16 -17
- data/lib/command/runner/backends/fake.rb +1 -0
- data/lib/command/runner/backends/spawn.rb +9 -15
- data/lib/command/runner/exceptions.rb +4 -0
- data/lib/command/runner/message.rb +17 -0
- data/lib/command/runner/version.rb +1 -1
- data/lib/command/runner.rb +30 -2
- data/spec/backticks_spec.rb +2 -7
- data/spec/messenger_spec.rb +11 -0
- metadata +1 -1
data/README.md
CHANGED
@@ -49,6 +49,16 @@ line.pass
|
|
49
49
|
|
50
50
|
but defaults to the best one.
|
51
51
|
|
52
|
+
If you run a command that doesn't exist on the machine...
|
53
|
+
|
54
|
+
```Ruby
|
55
|
+
line = Command::Runner.new("some-non-existant-command", "")
|
56
|
+
|
57
|
+
line.pass.no_command? # => true
|
58
|
+
```
|
59
|
+
|
60
|
+
it'll tell you.
|
61
|
+
|
52
62
|
## Compatibility
|
53
63
|
It works on
|
54
64
|
|
@@ -18,6 +18,7 @@ module Command
|
|
18
18
|
|
19
19
|
# Run the given command and arguments, in the given environment.
|
20
20
|
#
|
21
|
+
# @raise [Errno::ENOENT] if the command doesn't exist.
|
21
22
|
# @param command [String] the command to run.
|
22
23
|
# @param arguments [String] the arguments to pass to the
|
23
24
|
# command.
|
@@ -31,24 +32,22 @@ module Command
|
|
31
32
|
start_time = nil
|
32
33
|
end_time = nil
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end_time = Time.now
|
39
|
-
end
|
40
|
-
|
41
|
-
Message.new :process_id => $?.pid,
|
42
|
-
:exit_code => $?.exitstatus,
|
43
|
-
:finished => true,
|
44
|
-
:time => (end_time - start_time).abs,
|
45
|
-
:env => env,
|
46
|
-
:options => {},
|
47
|
-
:stdout => output,
|
48
|
-
:line => [command, arguments].join(' '),
|
49
|
-
:executed => true,
|
50
|
-
:status => $?
|
35
|
+
with_modified_env(env) do
|
36
|
+
start_time = Time.now
|
37
|
+
output << `#{command} #{arguments}`
|
38
|
+
end_time = Time.now
|
51
39
|
end
|
40
|
+
|
41
|
+
Message.new :process_id => $?.pid,
|
42
|
+
:exit_code => $?.exitstatus,
|
43
|
+
:finished => true,
|
44
|
+
:time => (end_time - start_time).abs,
|
45
|
+
:env => env,
|
46
|
+
:options => {},
|
47
|
+
:stdout => output,
|
48
|
+
:line => [command, arguments].join(' '),
|
49
|
+
:executed => true,
|
50
|
+
:status => $?
|
52
51
|
end
|
53
52
|
|
54
53
|
private
|
@@ -5,7 +5,10 @@ module Command
|
|
5
5
|
# Spawns a process using ruby's Process.spawn.
|
6
6
|
class Spawn < Fake
|
7
7
|
|
8
|
-
#
|
8
|
+
# Returns whether or not this backend is available on this
|
9
|
+
# platform.
|
10
|
+
#
|
11
|
+
# @return [Boolean]
|
9
12
|
def self.available?
|
10
13
|
Process.respond_to?(:spawn) && !(RUBY_PLATFORM == "java" && RUBY_VERSION =~ /\A1\.9/)
|
11
14
|
end
|
@@ -17,6 +20,7 @@ module Command
|
|
17
20
|
|
18
21
|
# Run the given command and arguments, in the given environment.
|
19
22
|
#
|
23
|
+
# @raise [Errno::ENOENT] if the command doesn't exist.
|
20
24
|
# @param (see Fake#call)
|
21
25
|
# @return (see Fake#call)
|
22
26
|
def call(command, arguments, env = {}, options = {})
|
@@ -24,13 +28,14 @@ module Command
|
|
24
28
|
stderr_r, stderr_w = IO.pipe
|
25
29
|
stdout_r, stdout_w = IO.pipe
|
26
30
|
stdin_r, stdin_w = IO.pipe
|
31
|
+
clean_exceptions = options.delete(:clean_exceptions) || false
|
27
32
|
|
33
|
+
if options[:input]
|
34
|
+
stdin_w.write(options.delete(:input))
|
35
|
+
end
|
28
36
|
new_options = options.merge(:in => stdin_r,
|
29
37
|
:out => stdout_w, :err => stderr_w)
|
30
38
|
|
31
|
-
if new_options[:input]
|
32
|
-
stdin_w.write(new_options.delete(:input))
|
33
|
-
end
|
34
39
|
stdin_w.close
|
35
40
|
|
36
41
|
line = [command, arguments].join(' ')
|
@@ -56,17 +61,6 @@ module Command
|
|
56
61
|
:executed => true,
|
57
62
|
:status => status
|
58
63
|
end
|
59
|
-
|
60
|
-
rescue Errno::ENOENT => e
|
61
|
-
Message.new :exit_code => 127,
|
62
|
-
:finished => true,
|
63
|
-
:time => -1,
|
64
|
-
:env => {},
|
65
|
-
:options => {},
|
66
|
-
:stdout => "",
|
67
|
-
:stderr => e.message,
|
68
|
-
:line => line,
|
69
|
-
:executed => false
|
70
64
|
end
|
71
65
|
|
72
66
|
# Spawn the given process, in the environment with the
|
@@ -5,6 +5,15 @@ module Command
|
|
5
5
|
# its exit code, process id, and even time it took to run.
|
6
6
|
class Message
|
7
7
|
|
8
|
+
# For when a message is created for a NoCommandError.
|
9
|
+
#
|
10
|
+
# @param line [String] the line that was executed, but gave a
|
11
|
+
# +Errno::ENOENT+ error.
|
12
|
+
# @ return [Message]
|
13
|
+
def self.error(line)
|
14
|
+
Message.new(:line => line, :exit_code => 127)
|
15
|
+
end
|
16
|
+
|
8
17
|
# Initialize the message with the given data about the process.
|
9
18
|
#
|
10
19
|
# @param data [Hash] the data about the process.
|
@@ -58,6 +67,14 @@ module Command
|
|
58
67
|
exit_code != 0
|
59
68
|
end
|
60
69
|
|
70
|
+
# Whether or not the command existed; or, if the exit code
|
71
|
+
# is 127.
|
72
|
+
#
|
73
|
+
# @return [Boolean]
|
74
|
+
def no_command?
|
75
|
+
exit_code == 127
|
76
|
+
end
|
77
|
+
|
61
78
|
# @!attribute [r] exit_code
|
62
79
|
# The code the process exited with.
|
63
80
|
#
|
data/lib/command/runner.rb
CHANGED
@@ -52,6 +52,8 @@ module Command
|
|
52
52
|
# The options the messenger was initialized with.
|
53
53
|
#
|
54
54
|
# @return [Hash]
|
55
|
+
# @!parse
|
56
|
+
# attr_reader :options
|
55
57
|
def options
|
56
58
|
@options.dup.freeze
|
57
59
|
end
|
@@ -59,7 +61,7 @@ module Command
|
|
59
61
|
# Gets the backend to be used by the messenger. If it is not defined
|
60
62
|
# on the instance, it'll get the class default.
|
61
63
|
#
|
62
|
-
# @see
|
64
|
+
# @see Runner.backend
|
63
65
|
# @return [#call] a backend to use.
|
64
66
|
def backend
|
65
67
|
@backend || self.class.backend
|
@@ -83,8 +85,34 @@ module Command
|
|
83
85
|
|
84
86
|
# Runs the command and arguments with the given interpolations;
|
85
87
|
# defaults to no interpolations.
|
88
|
+
#
|
89
|
+
# @note This method may not raise a {NoCommandError} and instead
|
90
|
+
# return a {Message} with the error code +127+, even if the
|
91
|
+
# command doesn't exist.
|
92
|
+
# @raise [NoCommandError] on no command.
|
93
|
+
# @param interops [Hash<Symbol, Object>] the interpolations to
|
94
|
+
# make.
|
95
|
+
# @param options [Hash<Symbol, Object>] the options for the
|
96
|
+
# backend.
|
97
|
+
# @return [Message]
|
98
|
+
def pass!(interops = {}, options = {})
|
99
|
+
backend.call(*[contents(interops), options.delete(:env) || {}, options].flatten)
|
100
|
+
|
101
|
+
rescue Errno::ENOENT
|
102
|
+
raise NoCommandError, @command
|
103
|
+
end
|
104
|
+
|
105
|
+
# Runs the command and arguments with the given interpolations;
|
106
|
+
# defaults to no interpolations. Calls {#pass!}, but does not
|
107
|
+
# raise an error.
|
108
|
+
#
|
109
|
+
# @param (see #pass!)
|
110
|
+
# @return (see #pass!)
|
86
111
|
def pass(interops = {}, options = {})
|
87
|
-
|
112
|
+
pass! interops, options
|
113
|
+
|
114
|
+
rescue NoCommandError
|
115
|
+
Message.error(:line => contents(interops))
|
88
116
|
end
|
89
117
|
|
90
118
|
# The command line being run by the runner. Interpolates the
|
data/spec/backticks_spec.rb
CHANGED
@@ -10,12 +10,7 @@ describe Command::Runner::Backends::Backticks do
|
|
10
10
|
value.should be_executed
|
11
11
|
end
|
12
12
|
|
13
|
-
it "
|
14
|
-
|
15
|
-
value = subject.call("sleep", "0.5")
|
16
|
-
end_time = Time.now
|
17
|
-
|
18
|
-
(end_time - start_time).should be_within((1.0/100)).of(0)
|
19
|
-
value.time.should be_within(0.1).of(0.5)
|
13
|
+
it "gives the correct time" do
|
14
|
+
subject.call("sleep", "0.5").time.should be_within(0.1).of(0.5)
|
20
15
|
end
|
21
16
|
end
|
data/spec/messenger_spec.rb
CHANGED
@@ -57,4 +57,15 @@ describe Command::Runner do
|
|
57
57
|
Command::Runner.best_backend.should be_instance_of Command::Runner::Backends::PosixSpawn
|
58
58
|
end
|
59
59
|
end
|
60
|
+
|
61
|
+
context "running bad commands" do
|
62
|
+
let(:command) { "some-non-existant-command" }
|
63
|
+
let(:arguments) { "" }
|
64
|
+
|
65
|
+
it "raises exceptions on non-existant commands" do
|
66
|
+
subject.backend = Command::Runner::Backends::Backticks.new
|
67
|
+
|
68
|
+
subject.pass.should be_no_command
|
69
|
+
end
|
70
|
+
end
|
60
71
|
end
|