class Raykit::Command

Functionality to support executing and logging system commands

def self.parse(json)

def self.parse(json)
    cmd=Command.new('')
    cmd.from_hash(JSON.parse(json))
    cmd
end

def elapsed_str()

def elapsed_str()
    if(elapsed < 1.0)
        "%.0f" % (elapsed) + "s"
    else
        "%.0f" % (elapsed) + "s"
    end
end

def from_hash(hash)

def from_hash(hash)
    @command = hash["command"]
    @directory=hash["directory"]
    @timeout=hash["timeout"]
    @start_time=hash["start_time"]
    @elapsed=hash["elapsed"]
    @output=hash["output"]
    @error=hash["error"]
    @exitstatus=hash["exitstatus"]
end

def init_defaults

def init_defaults 
    @timeout=0
    @directory = Dir.pwd
    @output = ''
    @error = ''
    @exitstatus = 0
end

def initialize(command,timeout=0)

def initialize(command,timeout=0)
    @@commands=Array.new
    init_defaults
    @command=command
    @timeout=timeout
    if(@command.length > 0)
        run
    end
    self
end

def run()

def run() 
    @start_time = Time.now
    timer = Timer.new
    if(@timeout == 0)
        @output,@error,process_status = Open3.capture3(@command) 
        @exitstatus=process_status.exitstatus
    else
        Open3.popen3(@command, :chdir=>@directory) { |stdin,stdout,stderr,thread|
            tick=2
            pid = thread.pid
            start = Time.now
            elapsed = Time.now-start
            while (elapsed) < @timeout and thread.alive?
                Kernel.select([stdout,stderr], nil, nil, tick)
                begin
                    @output << stdout.read_nonblock(BUFFER_SIZE)
                    @error << stderr.read_nonblock(BUFFER_SIZE)
                rescue IO::WaitReadable
                rescue EOFError
                    @exitstatus=thread.value.exitstatus
                    break
                end
                elapsed = Time.now-start
            end
            if thread.alive?
                if(Gem.win_platform?)
                    `taskkill /f /pid #{pid}`
                else
                    Process.kill("TERM", pid)
                end
                @exitstatus=5
            else
                @exitstatus=thread.value.exitstatus
            end
          }
    end
    @elapsed = timer.elapsed
    if(@exitstatus == 0)
        LOG.log('Raykit.Command',Logger::Severity::INFO,JSON.generate(to_hash))
    else
        LOG.log('Raykit.Command',Logger::Severity::ERROR,JSON.generate(to_hash))
    end
    @@commands.insert(-1,self)
end

def summary

def summary
    checkmark="\u2713"
    warning="\u26A0"
    error="\u0058"
    symbol=Rainbow(checkmark.encode('utf-8')).green
    symbol=Rainbow(error.encode('utf-8')).red if(@exitstatus!=0)
    puts symbol + "  " + elapsed_str.rjust(4) + " " + Rainbow(@command).yellow + " (#{@directory})"
end

def to_hash()

def to_hash()
    hash = Hash.new
    hash[:command] = @command
    hash[:directory] = @directory
    hash[:timeout] = @timeout
    hash[:start_time] = @start_time
    hash[:elapsed] = @elapsed
    hash[:output] = @output
    hash[:error] = @error
    hash[:exitstatus] = @exitstatus
    hash
end