lib/process_executer/errors.rb
# frozen_string_literal: true # rubocop:disable Layout/LineLength module ProcessExecuter # Base class for all ProcessExecuter::Command errors # # It is recommended to rescue `ProcessExecuter::Error` to catch any # runtime error raised by this gem unless you need more specific error handling. # # Custom errors are arranged in the following class hierarchy: # # ```text # ::StandardError # └─> Error # ├─> CommandError # │ ├─> FailedError # │ └─> SignaledError # │ └─> TimeoutError # └─> ProcessIOError # ``` # # | Error Class | Description | # | --- | --- | # | `Error` | This catch-all error serves as the base class for other custom errors. | # | `CommandError` | A subclass of this error is raised when there is a problem executing a command. | # | `FailedError` | Raised when the command exits with a non-zero status code. | # | `SignaledError` | Raised when the command is terminated as a result of receiving a signal. This could happen if the process is forcibly terminated or if there is a serious system error. | # | `TimeoutError` | This is a specific type of `SignaledError` that is raised when the command times out and is killed via the SIGKILL signal. Raised when the operation takes longer than the specified timeout duration (if provided). | # | `ProcessIOError` | Raised when an error was encountered reading or writing to the command's subprocess. | # # @example Rescuing any error # begin # ProcessExecuter.run_command('git', 'status') # rescue ProcessExecuter::Error => e # puts "An error occurred: #{e.message}" # end # # @example Rescuing a timeout error # begin # timeout_after = 0.1 # seconds # ProcessExecuter.run_command('sleep', '1', timeout_after:) # rescue ProcessExecuter::TimeoutError => e # Catch the more specific error first! # puts "Command took too long and timed out: #{e}" # rescue ProcessExecuter::Error => e # puts "Some other error occured: #{e}" # end # # @api public # class Error < ::StandardError; end # Raised when a command fails or exits because of an uncaught signal # # The command executed, status, stdout, and stderr are available from this # object. # # The Gem will raise a more specific error for each type of failure: # # * {FailedError}: when the command exits with a non-zero status # * {SignaledError}: when the command exits because of an uncaught signal # * {TimeoutError}: when the command times out # # @api public # class CommandError < ProcessExecuter::Error # Create a CommandError object # # @example # `exit 1` # set $? appropriately for this example # result = ProcessExecuter::Result.new(%w[git status], $?, 'stdout', 'stderr') # error = ProcessExecuter::CommandError.new(result) # error.to_s #=> '["git", "status"], status: pid 89784 exit 1, stderr: "stderr"' # # @param result [Result] The result of the command including the command, # status, stdout, and stderr # def initialize(result) @result = result super(error_message) end # The human readable representation of this error # # @example # error.error_message #=> '["git", "status"], status: pid 89784 exit 1, stderr: "stderr"' # # @return [String] # def error_message "#{result.command}, status: #{result}, stderr: #{result.stderr.inspect}" end # @attribute [r] result # # The result of the command including the command, its status and its output # # @example # error.result #=> #<ProcessExecuter::Result:0x00007f9b1b8b3d20> # # @return [Result] # attr_reader :result end # Raised when the command returns a non-zero exitstatus # # @api public # class FailedError < ProcessExecuter::CommandError; end # Raised when the command exits because of an uncaught signal # # @api public # class SignaledError < ProcessExecuter::CommandError; end # Raised when the command takes longer than the configured timeout_after # # @example # result.timed_out? #=> true # # @api public # class TimeoutError < ProcessExecuter::SignaledError; end # Raised when the output of a command can not be read # # @api public # class ProcessIOError < ProcessExecuter::Error; end end # rubocop:enable Layout/LineLength