From d39470063641ed817b2fb46370df09159492684c Mon Sep 17 00:00:00 2001 From: Sergei Gerasenko Date: Tue, 24 Feb 2026 23:26:16 +0000 Subject: [PATCH 1/3] Allow reading the command and status in the exception --- lib/rubyshell/error.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/rubyshell/error.rb b/lib/rubyshell/error.rb index 1ae8128..5f6120e 100644 --- a/lib/rubyshell/error.rb +++ b/lib/rubyshell/error.rb @@ -2,6 +2,8 @@ module RubyShell class CommandError < StandardError + attr_reader :command, :status + def initialize(command:, stdout: "", stderr: "", status: "", message: nil) @command = command @stdout = stdout From 15586fad2414d198977c6f323e7a48f5debd9b7e Mon Sep 17 00:00:00 2001 From: Sergei Gerasenko Date: Wed, 25 Feb 2026 16:46:32 +0000 Subject: [PATCH 2/3] Add spec test --- spec/error_spec.rb | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 spec/error_spec.rb diff --git a/spec/error_spec.rb b/spec/error_spec.rb new file mode 100755 index 0000000..351b3fd --- /dev/null +++ b/spec/error_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require_relative "../lib/rubyshell/error" +require_relative "../lib/rubyshell" + +RSpec.describe RubyShell::CommandError do + let(:command) { "ls -z" } + let(:stderr) { "ls: illegal option -- z" } + let(:status) { 1 } + + subject(:error) do + described_class.new( + command: command, + stderr: stderr, + status: status + ) + end + + describe "#initialize" do + it "stores the command, stderr, and status" do + expect(error.command).to eq(command) + expect(error.status).to eq(status) + end + + it "uses stderr as the exception message by default" do + expect(error.message).to eq(stderr) + end + + it "falls back to stdout if stderr is empty" do + msg = "Everything is fine" + err = described_class.new(command: "echo", stdout: msg, stderr: "") + expect(err.message).to eq(msg) + end + + it "prioritizes an explicit message if provided" do + err = described_class.new(command: "x", message: "Custom Overide") + expect(err.message).to eq("Custom Overide") + end + end +end From 8b1fdaa6deba74a44f511612ab1e21b434999254 Mon Sep 17 00:00:00 2001 From: Sergei Gerasenko Date: Mon, 2 Mar 2026 18:55:17 +0000 Subject: [PATCH 3/3] Revise test --- spec/command_error_spec.rb | 18 +++++++++++++++++ spec/error_spec.rb | 40 -------------------------------------- 2 files changed, 18 insertions(+), 40 deletions(-) create mode 100755 spec/command_error_spec.rb delete mode 100755 spec/error_spec.rb diff --git a/spec/command_error_spec.rb b/spec/command_error_spec.rb new file mode 100755 index 0000000..a32f033 --- /dev/null +++ b/spec/command_error_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +RSpec.describe RubyShell::CommandError do + let(:cmd) { "false" } + let(:error_instance) do + sh.send(cmd.to_sym) + raise "sh.#{cmd} did not raise RubyShell::CommandError as expected" + rescue described_class => e + e + end + + describe "Error object API" do + it "stores the command, stderr, and status" do + expect(error_instance.command).to eq("false") + expect(error_instance.status.to_s).to match(/exit 1/) + end + end +end diff --git a/spec/error_spec.rb b/spec/error_spec.rb deleted file mode 100755 index 351b3fd..0000000 --- a/spec/error_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -require_relative "../lib/rubyshell/error" -require_relative "../lib/rubyshell" - -RSpec.describe RubyShell::CommandError do - let(:command) { "ls -z" } - let(:stderr) { "ls: illegal option -- z" } - let(:status) { 1 } - - subject(:error) do - described_class.new( - command: command, - stderr: stderr, - status: status - ) - end - - describe "#initialize" do - it "stores the command, stderr, and status" do - expect(error.command).to eq(command) - expect(error.status).to eq(status) - end - - it "uses stderr as the exception message by default" do - expect(error.message).to eq(stderr) - end - - it "falls back to stdout if stderr is empty" do - msg = "Everything is fine" - err = described_class.new(command: "echo", stdout: msg, stderr: "") - expect(err.message).to eq(msg) - end - - it "prioritizes an explicit message if provided" do - err = described_class.new(command: "x", message: "Custom Overide") - expect(err.message).to eq("Custom Overide") - end - end -end