module Freshen::Executable

This module allows you to execute shell commands without terminating the current ruby process.

Public Class Methods

command_string(command, *args) click to toggle source

Get the full command string for a command and it's arguments.

Example:

>> Freshen::Executable.command_string :gem, :update
=> "gem update"
# File lib/freshen/executable.rb, line 18
def self.command_string(command, *args)
  args ||= []
  args.unshift(command)
  args.join(' ')
end

Protected Instance Methods

execute(command, *args) { |success, result| ... } click to toggle source

Execute a shell command.

If you provide a block

Arguments:

command: (String)
args: (Splat)

Example:

>> execute :gem, :update
=> nil
# File lib/freshen/executable.rb, line 37
def execute(command, *args, &block)
  freshening = ("freshen" == caller_locations(1,1)[0].label)
  cleaning = ("cleanup" == caller_locations(1,1)[0].label)
  
  if Freshen.cli?
    if freshening or cleaning
      puts "#{String.prefix.blue} #{Executable.command_string(command, *args)}"
    end
  end
  
    read, write = IO.pipe
    result = ""
              
  duration = Time.duration_of do
      begin
              pid = fork do
                      read.close
                      _execute(write, command, *args)
              end
                        
      Process.wait(pid)
      
              write.close
                        
              while buffer = read.gets
                      result += buffer
                      result += "\n"
              end
      ensure
              read.close unless read.closed?
              write.close unless write.closed?
      end
  end

  duration_string = (" %.2f sec" % duration) if duration
              
    $stdout.flush
  
  success = $?.success?
  
  yield success, result if block_given?
  
  if freshening or cleaning
    if success
      puts "#{String.checkmark.green}#{duration_string.green}" if Freshen.cli?
    else
      puts "#{String.ballot.red}#{duration_string.red}" if Freshen.cli?
      
      raise ExecutableError.new(self.class.name, command, *args)
    end
  end
  
  return success
end

Private Instance Methods

_execute(output, command, *args) click to toggle source

Execute a shell command using the specified output pipe.

This method should not be used directly.

Arguments:

output: (IO)
command: (String)
args: (Splat)

Example:

>> read, write = IO.pipe
>> _execute(write, :pwd)
# File lib/freshen/executable.rb, line 106
def _execute(output, command, *args)
    $stdout.reopen(output)
    $stderr.reopen(output)
  
  output.close
              
    command = command.to_s
  args.collect!(&:to_s)
              
    exec(command, *args) rescue nil
              
    exit! 1
end