require 'sequel' require 'ansi' module BuildTool # # Provide method to add and retrieve entries from the history # module History module StateHelper # ATTENTION # # Ansi::Code and Sequel don't like each other. Do not include Ansi::Code here. # Needed for both Module and Command History STARTED = 0 CANCELED_BY_USER = 1 FINISHED_SUCCESSFUL = 2 FINISHED_WITH_ERRORS = 3 def state_str case self.state when STARTED "STARTED" when CANCELED_BY_USER ANSI::Code.red { "CANCELED" } when FINISHED_SUCCESSFUL ANSI::Code.green { "SUCCESS" } when FINISHED_WITH_ERRORS ANSI::Code.red { "ERRORS" } else "#{self.state.to_s}?" end end module ClassMethods end def self.included( klass ) klass.extend ClassMethods end end # Represents a log entry for a command. class CommandLog < Sequel::Model( :command_logs ) include StateHelper # A command can have many module events one_to_many :module_logs, :order => :id def duration if self.finished_at dur = self.finished_at - self.started_at "%02d:%02d" % [ dur.to_i / 60, (dur% 60 ).to_i ] else "-----" end end # Call this if the command is finished. [:finished] will be set to Time.now, # [:state] to the given value and the object is saved. def finished( state ) self.finished_at = Time.now self.state = state save end # Call this if the command is started. [:started] will be set to Time.now, [:state] # to STARTED and the object is saved. def started self.started_at = Time.now save end # Sequel Hook # # Make sure a finished command has one of the accepted finished states. def before_update super if !self.finished_at.nil? raise StandardError, "Wrong state for finished Command" if ! [ FINISHED_SUCCESSFUL, FINISHED_WITH_ERRORS, CANCELED_BY_USER ].include? self.state end end def before_destroy self.module_logs_dataset.delete super end # Class Methods class << self # Loads the most recents entry from the database def most_recent( offset = nil ) if offset.nil? return where( "id = (SELECT MAX(id) FROM #{table_name})" ).first else return order( :id.desc ).limit( 1, offset ).first end end # def most_recent # Get the last :count issued commands # # @param [Integer] count Number of commands to return # @return [Array] List containing the last count issued commands def last( count = 50 ) order(:id.desc).limit(count).all end # Get the last :count command entries containing module :modname. def last_by_module( modname, count = 3 ) where( 'id in ( select distinct command_log_id from module_logs where module = ? )', modname ).order( :id.desc ).first( count ); end # Get all commands older than :days def older_than where( 'finished_at < ?', Date.today - 10 ) end end # ClassMethods end # Represents a module event. # # A module event is updating, compiling etc. a module. class ModuleLog < Sequel::Model( :module_logs ) include StateHelper # A module event belongs to a command many_to_one :command_log def duration if self.finished_at dur = self.finished_at - self.started_at "%02d:%02d" % [ dur.to_i / 60, (dur% 60 ).to_i ] else "-----" end end # Call this if the command is finished. [:finished] will be set to Time.now, # [:state] to the given value and the object is saved. def finished( state ) self.finished_at = Time.now self.state = state save end # Call this when the command is started. [:started] will be set to Time.now and # the object is saved. def started self.started_at = Time.now save end # Sequel Hook # # Make sure a finished command has one of the accepted finished states. def before_update super if !self.finished_at.nil? raise StandardError, "Wrong state for finished Command" if ! [ FINISHED_SUCCESSFUL, FINISHED_WITH_ERRORS, CANCELED_BY_USER ].include? self.state end end class << self end # class self end end # module BuildTool::History end # module BuildTool