Class: Mattock::CommandLine
- Inherits:
-
Object
- Object
- Mattock::CommandLine
show all
- Defined in:
- lib/mattock/command-line.rb,
lib/mattock/testing/record-commands.rb,
lib/mattock/testing/mock-command-line.rb,
lib/mattock/command-line/command-run-result.rb
Defined Under Namespace
Classes: CommandRunResult
Constant Summary
collapse
- @@commands =
[]
Class Attribute Summary collapse
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
-
#background ⇒ Object
Run a command in parallel with the parent process - will kill it if it outlasts us.
-
#collect_result(pid, host_stdout, host_stderr) ⇒ Object
-
#command ⇒ Object
-
#complete(pid, out, err) ⇒ Object
-
#copy_stream_to(from, to) ⇒ Object
-
#execute ⇒ Object
If I wasn’t worried about writing my own limited shell, I’d say e.g.
-
#initialize(executable, *options) {|_self| ... } ⇒ CommandLine
constructor
A new instance of CommandLine.
-
#kill_process(pid) ⇒ Object
-
#must_succeed! ⇒ Object
-
#options_composition ⇒ Object
-
#original_execute ⇒ Object
If I wasn’t worried about writing my own limited shell, I’d say e.g.
-
#redirect_from(path, stream) ⇒ Object
-
#redirect_stderr(path) ⇒ Object
-
#redirect_stdin(path) ⇒ Object
-
#redirect_stdout(path) ⇒ Object
-
#redirect_to(stream, path) ⇒ Object
-
#replace_us ⇒ Object
-
#report(message, newline = true) ⇒ Object
-
#run ⇒ Object
-
#set_env(name, value) ⇒ Object
-
#spawn_process ⇒ Object
-
#spin_off ⇒ Object
Run a command in the background.
-
#string_format ⇒ Object
-
#succeeds? ⇒ Boolean
-
#verbose ⇒ Object
Constructor Details
#initialize(executable, *options) {|_self| ... } ⇒ CommandLine
Returns a new instance of CommandLine.
29
30
31
32
33
34
35
36
|
# File 'lib/mattock/command-line.rb', line 29
def initialize(executable, *options)
@output_stream = self.class.output_stream || $stderr
@executable = executable
@options = options
@redirections = []
@env = {}
yield self if block_given?
end
|
Class Attribute Details
.command_recording_path ⇒ Object
Returns the value of attribute command_recording_path.
15
16
17
|
# File 'lib/mattock/testing/record-commands.rb', line 15
def command_recording_path
@command_recording_path
end
|
.output_stream ⇒ Object
Returns the value of attribute output_stream.
26
27
28
|
# File 'lib/mattock/command-line.rb', line 26
def output_stream
@output_stream
end
|
Instance Attribute Details
#env ⇒ Object
Also known as:
command_environment
Returns the value of attribute env.
38
39
40
|
# File 'lib/mattock/command-line.rb', line 38
def env
@env
end
|
#executable ⇒ Object
Returns the value of attribute executable.
38
39
40
|
# File 'lib/mattock/command-line.rb', line 38
def executable
@executable
end
|
#name ⇒ Object
Returns the value of attribute name.
38
39
40
|
# File 'lib/mattock/command-line.rb', line 38
def name
@name
end
|
#options ⇒ Object
Returns the value of attribute options.
38
39
40
|
# File 'lib/mattock/command-line.rb', line 38
def options
@options
end
|
#output_stream ⇒ Object
Returns the value of attribute output_stream.
38
39
40
|
# File 'lib/mattock/command-line.rb', line 38
def output_stream
@output_stream
end
|
#redirections ⇒ Object
Returns the value of attribute redirections.
39
40
41
|
# File 'lib/mattock/command-line.rb', line 39
def redirections
@redirections
end
|
Class Method Details
.define_chain_op(opname, klass) ⇒ Object
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# File 'lib/mattock/command-line.rb', line 6
def define_chain_op(opname, klass)
define_method(opname) do |other|
unless CommandLine === other
other = CommandLine.new(*[*other])
end
chain = nil
if klass === self
chain = self
else
chain = klass.new
chain.add(self)
end
chain.add(other)
end
end
|
.define_op(opname) ⇒ Object
.emit_recording ⇒ Object
21
22
23
24
25
26
27
28
29
30
31
|
# File 'lib/mattock/testing/record-commands.rb', line 21
def emit_recording
io = $stderr
if command_recording_path
io = File.open(command_recording_path, "w")
else
io.puts "Set MATTOCK_CMDREC to write to a path"
end
@@commands.each do |pair|
io.puts "[/#{pair[0]}/, #{[pair[1].exit_code, pair[1].streams].inspect}]"
end
end
|
.execute(*args) ⇒ Object
28
29
30
|
# File 'lib/mattock/testing/mock-command-line.rb', line 28
def self.execute(*args)
fail "Command line executed in specs without 'expect_command' or 'expect_some_commands'"
end
|
Instance Method Details
#background ⇒ Object
Run a command in parallel with the parent process - will kill it if it outlasts us
134
135
136
137
138
139
140
141
|
# File 'lib/mattock/command-line.rb', line 134
def background
pid, out, err = spawn_process
Process.detach(pid)
at_exit do
kill_process(pid)
end
return pid, out, err
end
|
#collect_result(pid, host_stdout, host_stderr) ⇒ Object
111
112
113
114
115
116
|
# File 'lib/mattock/command-line.rb', line 111
def collect_result(pid, host_stdout, host_stderr)
result = CommandRunResult.new(pid, self)
result.streams = {1 => host_stdout, 2 => host_stderr}
result.wait
return result
end
|
#command ⇒ Object
56
57
58
|
# File 'lib/mattock/command-line.rb', line 56
def command
([executable] + options_composition + @redirections).join(" ")
end
|
#complete(pid, out, err) ⇒ Object
147
148
149
150
|
# File 'lib/mattock/command-line.rb', line 147
def complete(pid, out, err)
kill_process(pid)
collect_result(pid, out, err)
end
|
#copy_stream_to(from, to) ⇒ Object
78
79
80
|
# File 'lib/mattock/command-line.rb', line 78
def copy_stream_to(from, to)
@redirections << "#{from}>&#{to}"
end
|
#execute ⇒ Object
If I wasn’t worried about writing my own limited shell, I’d say e.g. Pipeline would be an explicit chain of pipes… which is probably as originally intended :/
121
122
123
|
# File 'lib/mattock/command-line.rb', line 121
def execute
collect_result(*spawn_process)
end
|
#kill_process(pid) ⇒ Object
143
144
145
|
# File 'lib/mattock/command-line.rb', line 143
def kill_process(pid)
Process.kill("INT", pid)
end
|
#must_succeed! ⇒ Object
170
171
172
|
# File 'lib/mattock/command-line.rb', line 170
def must_succeed!
run.must_succeed!
end
|
#options_composition ⇒ Object
66
67
68
|
# File 'lib/mattock/command-line.rb', line 66
def options_composition
options
end
|
#original_execute ⇒ Object
If I wasn’t worried about writing my own limited shell, I’d say e.g. Pipeline would be an explicit chain of pipes… which is probably as originally intended :/
6
7
8
|
# File 'lib/mattock/testing/record-commands.rb', line 6
def execute
collect_result(*spawn_process)
end
|
#redirect_from(path, stream) ⇒ Object
74
75
76
|
# File 'lib/mattock/command-line.rb', line 74
def redirect_from(path, stream)
@redirections << "#{stream}<#{path}"
end
|
#redirect_stderr(path) ⇒ Object
86
87
88
|
# File 'lib/mattock/command-line.rb', line 86
def redirect_stderr(path)
redirect_to(2, path)
end
|
#redirect_stdin(path) ⇒ Object
90
91
92
|
# File 'lib/mattock/command-line.rb', line 90
def redirect_stdin(path)
redirect_from(path, 0)
end
|
#redirect_stdout(path) ⇒ Object
82
83
84
|
# File 'lib/mattock/command-line.rb', line 82
def redirect_stdout(path)
redirect_to(1, path)
end
|
#redirect_to(stream, path) ⇒ Object
70
71
72
|
# File 'lib/mattock/command-line.rb', line 70
def redirect_to(stream, path)
@redirections << "#{stream}>#{path}"
end
|
#replace_us ⇒ Object
94
95
96
97
98
|
# File 'lib/mattock/command-line.rb', line 94
def replace_us
output_steeam.puts "Ceding execution to: "
output_stream.puts string_format
Process.exec(command_environment, command)
end
|
#report(message, newline = true) ⇒ Object
152
153
154
|
# File 'lib/mattock/command-line.rb', line 152
def report(message, newline=true)
output_stream.print(message + (newline ? "\n" : ""))
end
|
#run ⇒ Object
156
157
158
159
160
161
162
163
164
|
# File 'lib/mattock/command-line.rb', line 156
def run
report string_format + " ", false
result = execute
report "=> #{result.exit_code}"
report result.format_streams if verbose
return result
ensure
report "" if verbose
end
|
#set_env(name, value) ⇒ Object
43
44
45
46
|
# File 'lib/mattock/command-line.rb', line 43
def set_env(name, value)
command_environment[name] = value
return self
end
|
#spawn_process ⇒ Object
100
101
102
103
104
105
106
107
108
109
|
# File 'lib/mattock/command-line.rb', line 100
def spawn_process
host_stdout, cmd_stdout = IO.pipe
host_stderr, cmd_stderr = IO.pipe
pid = Process.spawn(command_environment, command, :out => cmd_stdout, :err => cmd_stderr)
cmd_stdout.close
cmd_stderr.close
return pid, host_stdout, host_stderr
end
|
#spin_off ⇒ Object
Run a command in the background. The command can survive the caller
126
127
128
129
130
|
# File 'lib/mattock/command-line.rb', line 126
def spin_off
pid, out, err = spawn_process
Process.detach(pid)
return pid, out, err
end
|
60
61
62
63
64
|
# File 'lib/mattock/command-line.rb', line 60
def string_format
(command_environment.map do |key, value|
[key, value].join("=")
end + [command]).join(" ")
end
|
#succeeds? ⇒ Boolean
166
167
168
|
# File 'lib/mattock/command-line.rb', line 166
def succeeds?
run.succeeded?
end
|
#verbose ⇒ Object
48
49
50
|
# File 'lib/mattock/command-line.rb', line 48
def verbose
::Rake.verbose && ::Rake.verbose != ::Rake::FileUtilsExt::DEFAULT
end
|