module CLAide::Executable

Module which provides support for running executables.

In a class it can be used as:

extend Executable
executable :git

This will create two methods `git` and `git!` both accept a command but the latter will raise on non successful executions. The methods return the output of the command.

Public Class Methods

execute_command(exe, command, raise_on_failure) click to toggle source

Executes the given command. Displays output if in verbose mode.

@param [String] bin

The binary to use.

@param [Array<#to_s>] command

The command to send to the binary.

@param [Bool] raise_on_failure

Whether it should raise if the command fails.

@raise If the executable could not be located.

@raise If the command fails and the `raise_on_failure` is set to true.

@return [String] the output of the command (STDOUT and STDERR).

@todo Find a way to display the live output of the commands.

# File lib/claide/executable.rb, line 50
def self.execute_command(exe, command, raise_on_failure)
  bin = `which #{exe}`.strip
  raise Informative, "Unable to locate `#{exe}`" if bin.empty?

  require 'open4'
  require 'shellwords'

  command = command.map(&:to_s)
  full_command = \
    "#{bin.shellescape} #{command.map(&:shellescape).join(' ')}"

  # if Config.instance.verbose?
  # UI.message("$ #{full_command}")
  # stdout, stderr = Indenter.new(STDOUT), Indenter.new(STDERR)
  # else
  stdout, stderr = Indenter.new, Indenter.new
  # end

  options = { :stdout => stdout, :stderr => stderr, :status => true }
  status  = Open4.spawn(bin, command, options)
  output  = stdout.join("\n") + stderr.join("\n")
  unless status.success?
    if raise_on_failure
      raise Informative, "#{full_command}\n\n#{output}"
    else
      UI.message("[!] Failed: #{full_command}".red)
    end
  end
  output
end

Public Instance Methods

executable(name) click to toggle source

Creates the methods for the executable with the given name.

@param [Symbol] name

the name of the executable.

@return [void]

# File lib/claide/executable.rb, line 21
def executable(name)
  define_method(name) do |*command|
    Executable.execute_command(name, Array(command).flatten, false)
  end

  define_method(name.to_s + '!') do |*command|
    Executable.execute_command(name, Array(command).flatten, true)
  end
end