command-runner 0.2.1 → 0.3.0
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/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
|