diff --git a/lib/thor/actions.rb b/lib/thor/actions.rb index d932fb6da..cc57d94ae 100644 --- a/lib/thor/actions.rb +++ b/lib/thor/actions.rb @@ -258,13 +258,18 @@ def run(command, config = {}) return if options[:pretend] - result = config[:capture] ? `#{command}` : system(command.to_s) + env_splat = [config[:env]] if config[:env] - if config[:abort_on_failure] - success = config[:capture] ? $?.success? : result - abort unless success + if config[:capture] + result, status = Open3.capture2e(*env_splat, command.to_s) + success = status.success? + else + result = system(*env_splat, command.to_s) + success = result end + abort if config[:abort_on_failure] && !success + result end diff --git a/spec/actions_spec.rb b/spec/actions_spec.rb index c46468ce4..a8f1f7d68 100644 --- a/spec/actions_spec.rb +++ b/spec/actions_spec.rb @@ -291,29 +291,41 @@ def file end end - describe "aborting on failure" do + describe "when pretending" do + it "doesn't execute the command" do + runner = MyCounter.new([1], %w(--pretend)) + expect(runner).not_to receive(:system) + runner.run("ls", :verbose => false) + end + end + + describe "when not capturing" do it "aborts when abort_on_failure is given and command fails" do expect { action :run, "false", :abort_on_failure => true }.to raise_error(SystemExit) end - it "suceeds when abort_on_failure is given and command succeeds" do + it "succeeds when abort_on_failure is given and command succeeds" do expect { action :run, "true", :abort_on_failure => true }.not_to raise_error end + it "supports env option" do + expect { action :run, "echo $BAR", :env => { "BAR" => "foo" } }.to output("foo\n").to_stdout_from_any_process + end + end + + describe "when capturing" do it "aborts when abort_on_failure is given, capture is given and command fails" do expect { action :run, "false", :abort_on_failure => true, :capture => true }.to raise_error(SystemExit) end - it "suceeds when abort_on_failure is given and command succeeds" do + it "succeeds when abort_on_failure is given and command succeeds" do expect { action :run, "true", :abort_on_failure => true, :capture => true }.not_to raise_error end - end - describe "when pretending" do - it "doesn't execute the command" do - runner = MyCounter.new([1], %w(--pretend)) - expect(runner).not_to receive(:system) - runner.run("ls", :verbose => false) + it "supports env option" do + silence(:stdout) do + expect(runner.run "echo $BAR", :env => { "BAR" => "foo" }, :capture => true).to eq("foo\n") + end end end end @@ -367,8 +379,8 @@ def file end it "captures the output when :capture is given" do - expect(runner).to receive(:`).with("thor foo bar") - action(:thor, "foo", "bar", :capture => true) + expect(runner).to receive(:run).with("list", hash_including(:capture => true)) + action :thor, :list, :capture => true end end end