Skip to content

Commit 0b45b61

Browse files
committed
Use the shell to run Mix.Shell.cmd commands
1 parent 24c6623 commit 0b45b61

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

lib/mix/lib/mix/shell.ex

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ defmodule Mix.Shell do
3838
is shared accross different shells.
3939
"""
4040
def cmd(command, callback) do
41-
port = Port.open({ :spawn, to_char_list(command) },
41+
port = Port.open({ :spawn, shell_command(command) },
4242
[:stream, :binary, :exit_status, :hide, :use_stdio, :stderr_to_stdout])
4343
do_cmd(port, callback)
4444
end
@@ -52,4 +52,21 @@ defmodule Mix.Shell do
5252
status
5353
end
5454
end
55+
56+
# Finding shell command logic from :os.cmd in OTP
57+
# https://github.com/erlang/otp/blob/8deb96fb1d017307e22d2ab88968b9ef9f1b71d0/lib/kernel/src/os.erl#L184
58+
defp shell_command(command) do
59+
command = to_char_list(command)
60+
61+
case :os.type do
62+
{ :unix, _ } ->
63+
%c(sh -c '#{command}')
64+
{ :win32, osname } ->
65+
case { System.getenv("COMSPEC"), osname } do
66+
{ false, :windows } -> 'command.com /c #{command}'
67+
{ false, _ } -> 'cmd /c #{command}'
68+
{ false, cmd } -> '#{cmd} /c #{command}'
69+
end
70+
end
71+
end
5572
end

lib/mix/test/mix/shell_test.exs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
Code.require_file "../test_helper.exs", __DIR__
2+
3+
defmodule Mix.ShellTest do
4+
use MixTest.Case
5+
6+
test "shell process" do
7+
Mix.shell.info "abc"
8+
Mix.shell.error "def"
9+
assert_received { :mix_shell, :info, ["abc"] }
10+
assert_received { :mix_shell, :error, ["def"] }
11+
12+
self <- { :mix_shell_input, :yes?, true }
13+
assert Mix.shell.yes?("hello?")
14+
assert_received { :mix_shell, :yes?, ["hello?"] }
15+
16+
assert Mix.shell.cmd("echo first") == 0
17+
assert_received { :mix_shell, :run, ["first\n"] }
18+
end
19+
20+
test "shell io" do
21+
import ExUnit.CaptureIO
22+
23+
Mix.shell(Mix.Shell.IO)
24+
assert Mix.shell == Mix.Shell.IO
25+
26+
assert capture_io(fn -> Mix.shell.info "abc" end) ==
27+
"abc\n"
28+
29+
assert capture_io(:stderr, fn -> Mix.shell.error "def" end) ==
30+
(IO.ANSI.escape "%{red,bright}def") <> "\n"
31+
32+
capture_io("Yes", fn -> assert Mix.shell.yes?("hello?") end)
33+
34+
assert capture_io(fn -> assert Mix.shell.cmd("echo first") == 0 end) ==
35+
"first\n"
36+
after
37+
Mix.shell(Mix.Shell.Process)
38+
end
39+
40+
test "shell cmd" do
41+
assert Mix.shell.cmd("echo first && echo second") == 0
42+
assert_received { :mix_shell, :run, ["first\nsecond\n"] }
43+
end
44+
end

0 commit comments

Comments
 (0)