Class: Shellany::Sheller

Inherits:
Object
  • Object
show all
Defined in:
lib/shellany/sheller.rb

Overview

The Guard sheller abstract the actual subshell calls and allow easier stubbing.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Sheller

Creates a new Guard::Sheller object.

Parameters:

  • args (String)

    a command to run in a subshell

  • args (Array<String>)

    an array of command parts to run in a subshell

  • args (*String)

    a list of command parts to run in a subshell



16
17
18
19
20
# File 'lib/shellany/sheller.rb', line 16

def initialize(*args)
  fail ArgumentError, "no command given" if args.empty?
  @command = args
  @ran = false
end

Instance Attribute Details

#statusObject (readonly)

Returns the value of attribute status.



8
9
10
# File 'lib/shellany/sheller.rb', line 8

def status
  @status
end

Class Method Details

._shellize_if_needed(args) ⇒ Object

Only needed on JRUBY, because MRI properly detects ‘;’ and metachars



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/shellany/sheller.rb', line 128

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

._system_with_capture(*args) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/shellany/sheller.rb', line 110

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

._system_with_no_capture(*args) ⇒ Object



103
104
105
106
107
108
# File 'lib/shellany/sheller.rb', line 103

def self._system_with_no_capture(*args)
  Kernel.system(*args)
  result = $?
  errors = (result == 0) || "Guard failed to run: #{args.inspect}"
  [result, nil, errors]
end

.run(*args) ⇒ Object

Shortcut for new(command).run



24
25
26
# File 'lib/shellany/sheller.rb', line 24

def self.run(*args)
  new(*args).run
end

.stderr(*args) ⇒ Object

Shortcut for new(command).run.stderr



36
37
38
# File 'lib/shellany/sheller.rb', line 36

def self.stderr(*args)
  new(*args).stderr
end

.stdout(*args) ⇒ Object

Shortcut for new(command).run.stdout



30
31
32
# File 'lib/shellany/sheller.rb', line 30

def self.stdout(*args)
  new(*args).stdout
end

.system(*args) ⇒ Object

No output capturing

NOTE: ‘$stdout.puts system(’cls’)‘ on Windows won’t work like it does for on systems with ansi terminals, so we need to be able to call Kernel.system directly.



99
100
101
# File 'lib/shellany/sheller.rb', line 99

def self.system(*args)
  _system_with_no_capture(*args)
end

Instance Method Details

#ok?Boolean

Returns true if the command succeeded, false otherwise.

Returns:

  • (Boolean)

    whether or not the command succeeded



68
69
70
71
72
# File 'lib/shellany/sheller.rb', line 68

def ok?
  run unless ran?

  @status && @status.success?
end

#ran?Boolean

Returns true if the command has already been run, false otherwise.

Returns:

  • (Boolean)

    whether or not the command has already been run



60
61
62
# File 'lib/shellany/sheller.rb', line 60

def ran?
  @ran
end

#runBoolean

Runs the command.

Returns:

  • (Boolean)

    whether or not the command succeeded.



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/shellany/sheller.rb', line 44

def run
  unless ran?
    status, output, errors = self.class._system_with_capture(*@command)
    @ran = true
    @stdout = output
    @stderr = errors
    @status = status
  end

  ok?
end

#stderrString

Returns the command’s error output.

Returns:

  • (String)

    the command output



88
89
90
91
92
# File 'lib/shellany/sheller.rb', line 88

def stderr
  run unless ran?

  @stderr
end

#stdoutString

Returns the command’s output.

Returns:

  • (String)

    the command output



78
79
80
81
82
# File 'lib/shellany/sheller.rb', line 78

def stdout
  run unless ran?

  @stdout
end