Skip to content

Commit 1d3c542

Browse files
committed
feat: output type only accept IO or Array(IO)
- idea from branch v0.1 - use subclass of Process::Status as Err type
1 parent a8dcd0d commit 1d3c542

File tree

4 files changed

+44
-31
lines changed

4 files changed

+44
-31
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
dependencies:
1111
exec:
1212
github: initdc/exec.cr
13-
version: 0.2.2
13+
version: 0.2.3
1414
```
1515
1616
2. Run `shards install`

shard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: exec
2-
version: 0.2.2
2+
version: 0.2.3
33

44
authors:
55
- initdc <initd@outlook.com>

spec/exec_spec.cr

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ describe Exec do
55
Exec.run("sudo apt update")
66
end
77

8+
it "not print but also get stdout" do
9+
case r = Exec.run("uname", output: File.open(File::NULL, "w"))
10+
when String
11+
r.should eq "Linux\n"
12+
else
13+
r.exit_code.should_not eq 0
14+
end
15+
16+
case r = Exec.run("unamea", output: File.open(File::NULL, "w"))
17+
when String
18+
r.should eq "Linux\n"
19+
else
20+
r.stdout.should eq ""
21+
r.exit_code.should eq 127
22+
end
23+
end
24+
825
it "return 0" do
926
Exec.code("uname").should eq 0
1027
end
@@ -37,7 +54,7 @@ describe Exec do
3754
else
3855
r.stdout.chomp.should eq "good"
3956
r.stderr.chomp.should eq "bad"
40-
r.status.exit_code.should eq 1
57+
r.exit_code.should eq 1
4158
end
4259
end
4360

@@ -57,7 +74,9 @@ describe Exec do
5774

5875
it "log to file" do
5976
tempfile = File.tempfile("test_", ".log")
60-
Exec.run("uname", output: File.open(tempfile.path, "a+"))
77+
File.open(tempfile.path, "a+") do |io|
78+
Exec.run("uname", output: io)
79+
end
6180

6281
tempfile.gets_to_end.should eq "Linux\n"
6382
tempfile.delete

src/exec.cr

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,34 @@
11
class Exec < Process
2-
VERSION = "0.2.2"
2+
VERSION = "0.2.3"
33

4-
# https://github.com/crystal-lang/crystal/blob/1.19.1/src/compiler/crystal/macros/macros.cr#L68
5-
record Err, stdout : String, stderr : String, status : Process::Status
4+
class Err < ::Process::Status
5+
getter stdout : String
6+
getter stderr : String
7+
8+
{% if flag?(:win32) %}
9+
# :nodoc:
10+
def initialize(@exit_status : UInt32, @stdout : String, @stderr : String)
11+
end
12+
{% else %}
13+
# :nodoc:
14+
def initialize(@exit_status : Int32, @stdout : String, @stderr : String)
15+
end
16+
{% end %}
17+
end
618

719
def self.run(command : String, args = nil, env : Env = nil, clear_env : Bool = false, shell : Bool = true,
8-
input : Stdio = Redirect::Inherit, output : Stdio = Redirect::Inherit, error : Stdio = Redirect::Inherit, chdir : Path | String? = nil) : String | Err
20+
input : IO = STDIN, output : IO | Array(IO) = STDOUT, error : IO | Array(IO) = STDERR, chdir : Path | String? = nil) : String | Err
921
output_strio = String::Builder.new
1022
error_strio = String::Builder.new
11-
12-
output_writer = if output.is_a?(Redirect)
13-
output == Redirect::Close ? output : IO::MultiWriter.new(STDOUT, output_strio)
14-
else
15-
output != STDOUT ? IO::MultiWriter.new(STDOUT, output, output_strio) : IO::MultiWriter.new(STDOUT, output_strio)
16-
end
17-
18-
error_writer = if error.is_a?(Redirect)
19-
error == Redirect::Close ? error : IO::MultiWriter.new(STDERR, error_strio)
20-
else
21-
error != STDERR ? IO::MultiWriter.new(STDERR, error, error_strio) : IO::MultiWriter.new(STDERR, error_strio)
22-
end
23+
output_writer = output.is_a?(Array) ? IO::MultiWriter.new(output + output_strio) : IO::MultiWriter.new(output, output_strio)
24+
error_writer = error.is_a?(Array) ? IO::MultiWriter.new(error + error_strio) : IO::MultiWriter.new(error, error_strio)
2325

2426
status = new(command, args, env, clear_env, shell, input, output_writer, error_writer, chdir).wait
2527
$? = status
2628

27-
output.close unless output.is_a?(Redirect) || output == STDOUT
28-
error.close unless error.is_a?(Redirect) || error == STDERR
29-
output_strio.close
30-
error_strio.close
31-
32-
case status.success?
33-
when true
34-
output_strio.to_s
35-
else
36-
Err.new(output_strio.to_s, error_strio.to_s, status)
37-
end
29+
output_writer.close
30+
error_writer.close
31+
status.success? ? output_strio.to_s : Err.new(status.@exit_status, output_strio.to_s, error_strio.to_s)
3832
end
3933

4034
def self.code(command : String, args = nil, env : Env = nil, clear_env : Bool = false, shell : Bool = true,

0 commit comments

Comments
 (0)