Commit 11d150bb authored by Fabio Pelosin's avatar Fabio Pelosin

[Executable] Cleaned up implementation.

parent 709137d9
require 'open4'
module Pod
# 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 later will raise on non successful executions. The methods return the
# output of the command.
#
module Executable
class Indenter < ::Array
include Config::Mixin
attr_accessor :indent
attr_accessor :io
# Creates the methods for the executable with the given name.
#
# @param [Symbol] name
# the name of the executable.
#
# @raise If the executable could not be located.
#
# @return [void]
#
def executable(name)
bin = `which #{name}`.strip
raise Informative, "Unable to locate the executable `#{name}`" if bin.empty?
def initialize(io = nil)
@io = io
@indent = ' ' * UI.indentation_level
define_method(name) do |command|
Executable.execute_command(bin, command, false)
end
def <<(value)
super
ensure
@io << "#{ indent }#{ value }" if @io
define_method(name.to_s + "!") do |command|
Executable.execute_command(bin, command, true)
end
end
# TODO
# Executes the given command displaying it if in verbose mode.
#
# @param [String] bin
# The binary to use.
#
# @param [String] command
# The command to send to the binary.
#
# @param [Bool] raise_on_failure
# Whether it should raise if the command fails.
#
# @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.
#
def self.execute_command(bin, command, raise_on_failure = false)
bin = `which #{bin}`.strip
if bin.empty?
raise Informative, "Unable to locate the executable `#{name}'"
end
full_command = "#{bin} #{command}"
if Config.instance.verbose?
UI.message("$ #{full_command}")
stdout, stderr = Indenter.new(STDOUT), Indenter.new(STDERR)
else
stdout, stderr = Indenter.new, Indenter.new
end
status = Open4.spawn(full_command, :stdout => stdout, :stderr => stderr, :status => true)
output = stdout.join("\n") + stderr.join("\n") # TODO will this suffice?
options = {:stdout => stdout, :stderr => stderr, :status => true}
status = Open4.spawn(full_command, options)
output = stdout.join("\n") + stderr.join("\n")
unless status.success?
if raise_on_failure
raise Informative, "#{name} #{command}\n\n#{output}"
......@@ -48,43 +77,41 @@ module Pod
output
end
#-------------------------------------------------------------------------#
def executable(name)
bin = `which #{name}`.strip
base_method = "base_" << name.to_s
define_method(base_method) do |command, should_raise|
if bin.empty?
raise Informative, "Unable to locate the executable `#{name}'"
end
full_command = "#{bin} #{command}"
if Config.instance.verbose?
UI.message("$ #{full_command}")
stdout, stderr = Indenter.new(STDOUT), Indenter.new(STDERR)
else
stdout, stderr = Indenter.new, Indenter.new
end
status = Open4.spawn(full_command, :stdout => stdout, :stderr => stderr, :status => true)
# Helper class that allows to write to an {IO} instance taking into account
# the UI indentation lever.
#
class Indenter < ::Array
include Config::Mixin
output = stdout.join("\n") + stderr.join("\n") # TODO will this suffice?
unless status.success?
if should_raise
raise Informative, "#{name} #{command}\n\n#{output}"
else
UI.message("[!] Failed: #{full_command}".red)
end
end
output
end
# @return [Fixnum] The indentation level of the UI.
#
attr_accessor :indent
define_method(name) do |command|
Executable.execute_command(name, command, false)
end
# @return [IO] the {IO} to which the output should be printed.
#
attr_accessor :io
define_method(name.to_s + "!") do |command|
Executable.execute_command(name, command, true)
# @param [IO] io @see io
#
def initialize(io = nil)
@io = io
@indent = ' ' * UI.indentation_level
end
private name
# Stores a portion of the output and prints it to the {IO} instance.
#
# @param [String] value
# the output to print.
#
# @return [void]
#
def <<(value)
super
ensure
@io << "#{ indent }#{ value }" if @io
end
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment