class Shellany::Sheller
calls and allow easier stubbing.
The Guard sheller abstract the actual subshell
def self._shellize_if_needed(args)
def self._shellize_if_needed(args) return args unless RUBY_PLATFORM == "java" return args unless args.size == 1 return args unless /[;<>]/ =~ args.first # NOTE: Sheller was originally meant for Guard (which basically only uses # UNIX commands anyway) and JRuby doesn't support options to # Kernel.system (and doesn't automatically shell when there's a # metacharacter in the command). # # So ... I'm assuming /bin/sh exists - if not, PRs are welcome, # because I have no clue what to do if /bin/sh doesn't exist. # (use ENV["RUBYSHELL"] ? Detect cmd.exe ?) ["/bin/sh", "-c", args.first] end
def self._system_with_capture(*args)
def self._system_with_capture(*args) # We use popen3, because it started working on recent versions # of JRuby, while JRuby doesn't handle options to Kernel.system args = _shellize_if_needed(args) stdout, stderr, status = nil Open3.popen3(*args) do |_stdin, _stdout, _stderr, _thr| stdout = _stdout.read stderr = _stderr.read status = _thr.value end [status, stdout, stderr] rescue Errno::ENOENT, IOError => e [nil, nil, "Guard::Sheller failed (#{e.inspect})"] end
def self._system_with_no_capture(*args)
def self._system_with_no_capture(*args) Kernel.system(*args) result = $? errors = (result == 0) || "Guard failed to run: #{args.inspect}" [result, nil, errors] end
def self.run(*args)
Shortcut for new(command).run
def self.run(*args) new(*args).run end
def self.stderr(*args)
Shortcut for new(command).run.stderr
def self.stderr(*args) new(*args).stderr end
def self.stdout(*args)
Shortcut for new(command).run.stdout
def self.stdout(*args) new(*args).stdout end
def self.system(*args)
it does for on systems with ansi terminals, so we need to be
NOTE: `$stdout.puts system('cls')` on Windows won't work like
No output capturing
def self.system(*args) _system_with_no_capture(*args) end
def initialize(*args)
-
args
(*String
) -- a list of command parts to run in a subshell -
args
(Array
) -- an array of command parts to run in a subshell -
args
(String
) -- a command to run in a subshell
def initialize(*args) fail ArgumentError, "no command given" if args.empty? @command = args @ran = false end
def ok?
-
(Boolean)
- whether or not the command succeeded
def ok? run unless ran? @status && @status.success? end
def ran?
-
(Boolean)
- whether or not the command has already been run
def ran? @ran end
def run
-
(Boolean)
- whether or not the command succeeded.
def run unless ran? status, output, errors = self.class._system_with_capture(*@command) @ran = true @stdout = output @stderr = errors @status = status end ok? end
def stderr
-
(String)
- the command output
def stderr run unless ran? @stderr end
def stdout
-
(String)
- the command output
def stdout run unless ran? @stdout end