# Part of the A-A-P recipe executive: printing messages

# Copyright (C) 2002-2003 Stichting NLnet Labs
# Permission to copy and use this file is specified in the file COPYING.
# If this file is missing you can find it here: http://www.a-a-p.org/COPYING


# All messages are written into a log file.
# Only selected messages are printed.

# It's OK to import * from this file.

import string
import os
import os.path
import sys

import Global
from Error import *

# Message types:
msgt_note = "note"              # note message
msgt_warning = "warning"        # warning message (def)
msgt_error = "error"            # error message (def)
msgt_system = "system"          # executed system command (def)
msgt_result = "result"          # result of :sys command
msgt_info = "info"              # informational message (def)
msgt_extra = "extra"            # extra informational message
msgt_changedir = "changedir"    # changing directories
msgt_depend = "depend"          # message about dependencies
msgt_log = "log"                # log messages
msgt_all = "all"                # all messages
msgt_print = "print"            # :print message

# Message modes:
msgm_normal = 0                 # print message "Aap: msg\n"
msgm_start = 1                  # print message "Aap: msg"
msgm_cont = 2                   # print message "msg"

# File for logging message.  Is opened only after the main recipe is located.
logfile = None

# Full path of the file used for logging.
logname = None

def msg_startlog(recdict):
    """Open the logfile.  Can only be done after locating the main recipe file
       and changing to it's directory."""
    from Util import assert_aap_dir, in_aap_dir

    # Do not create a log if the only target is "cleanALL".
    if (len(Global.cmd_args.targets) == 1
                                 and Global.cmd_args.targets[0] == "cleanALL"):
        return

    # Need the "AAPDIR" directory.
    if not assert_aap_dir(recdict):
        return

    # Rename the old files if aap/log already exists.  log8 -> log9, log7 ->
    # log8, ..., log1 -> log2, log -> log1
    log_name = in_aap_dir("log")
    if os.path.exists(log_name):
        i = 8
        while i >= 0:
            if i == 0:
                src = log_name
            else:
                src = in_aap_dir("log%d" % i)
            if os.path.exists(src):
                dst = in_aap_dir("log%d" % (i + 1))
                # May have to delete the destination file log9.
                if i == 8:
                    from Util import try_delete
                    try_delete(dst)
                try:
                    os.rename(src, dst)
                except StandardError, e:
                    print _('Warning: Could not rename "%s" to "%s"') % (src, dst)
                    break
            i = i - 1

    # Open aap/log
    global logfile
    try:
        logfile = open(log_name, "w")
    except StandardError, e:
        print _("Warning: Cannot open log file for writing: "), str(e)
    else:
        # Turn into an absolute name, we may use chdir.
        global logname
        logname = os.path.abspath(log_name)


def msg_logname():
    """Return the name of the log file."""
    return logname


def msg_stoplog():
    """Stop using a logfile.  Used just before finishing the work."""
    global logfile, logname
    if logfile:
        logfile.close()
        logfile = None
        logname = None


def msg_msg(recdict, msg, type, mode = msgm_normal, rpstack = None):
    """
    Generic function to print a message "msg" of type "type".
    All messages are written in the log file (if it exists).
    A message is displayed if its type is in the MESSAGE variable.
    The optional "rpstack" can be used to prepend the recipe position to the
    message.
    """
    if rpstack:
        from Process import get_recipe_msg
        msg = get_recipe_msg(rpstack) + msg

    doprint = 0
    if not recdict:
        doprint = 1
    else:
        from Util import get_var_val_int
        m = get_var_val_int(recdict, "MESSAGE")
        if (m is None
                or string.find(m, type) >= 0
                or string.find(m, msgt_all) >= 0):
            doprint = 1
    if doprint:
        if mode == msgm_normal:
            print "Aap: " + msg
        elif mode == msgm_start:
            print "Aap: " + msg,
            sys.stdout.flush()
        else:
            print msg,
            sys.stdout.flush()
    _log(msg, type, mode = mode)

def _log(msg, type, mode = msgm_normal):
    if logfile:
        try:
            if mode == msgm_normal:
                logfile.write("%s:\t%s\n" % (type, msg))
            elif mode == msgm_start:
                logfile.write("%s:\t%s" % (type, msg))
            else:
                logfile.write(msg)
        except IOError, e:
            raise UserError, _('Error while writing to log file: ') + str(e)

def msg_note(recdict, msg, mode = msgm_normal, rpstack = None):
    """Print a note message."""
    msg_msg(recdict, msg, msgt_note, mode = mode, rpstack = rpstack)

def msg_warning(recdict, msg, mode = msgm_normal, rpstack = None):
    """Print a warning message."""
    msg_msg(recdict, msg, msgt_warning, mode = mode, rpstack = rpstack)

def msg_error(recdict, msg, mode = msgm_normal, rpstack = None):
    """Print an error message."""
    msg_msg(recdict, msg, msgt_error, mode = mode, rpstack = rpstack)

def msg_system(recdict, msg, mode = msgm_normal, rpstack = None):
    """Print an executed system command."""
    if len(msg) and msg[-1] == '\n':
        msg = msg[:-1]      # remove trailing newline
    msg_msg(recdict, msg, msgt_system, mode = mode, rpstack = rpstack)

def msg_result(recdict, msg, mode = msgm_normal, rpstack = None):
    """Print an executed system command."""
    if len(msg) and msg[-1] == '\n':
        msg = msg[:-1]      # remove trailing newline
    msg_msg(recdict, msg, msgt_result, mode = mode, rpstack = rpstack)

def msg_info(recdict, msg, mode = msgm_normal, rpstack = None):
    """Print an informational message."""
    msg_msg(recdict, msg, msgt_info, mode = mode, rpstack = rpstack)

def msg_skip(line_nr, recdict, cmd):
    """Print a message about a skipped command."""
    # Try expanding variables in the command.  If this fails use the unexpanded
    # command.
    from Util import Expand
    from Commands import expand
    try:
        s = expand(line_nr, recdict, cmd, Expand(0, Expand.quote_aap))
    except:
        s = cmd
    msg_info(recdict, _('skip line %d: %s') % (line_nr, s))

def msg_extra(recdict, msg, mode = msgm_normal, rpstack = None):
    """Print an extra informational message."""
    msg_msg(recdict, msg, msgt_extra, mode = mode, rpstack = rpstack)

def msg_changedir(recdict, dir):
    """Print a message about changing directories."""
    # Note: This message is not translated, so that a parser
    # for the messages isn't confused by various languages.
    msg_msg(recdict, "Entering directory `%s'" % dir, msgt_changedir)

def msg_depend(recdict, msg, level = None):
    """Print a message about dependencies."""
    if level:
        msg = ("%d - " % level) + msg
    msg_msg(recdict, msg, msgt_depend)

def msg_log(recdict, msg, mode = msgm_normal, rpstack = None):
    """Log a message only, never printed."""
    if rpstack:
        from Process import get_recipe_msg
        msg = get_recipe_msg(rpstack) + msg
    _log(msg, msgt_log, mode = mode)

def msg_print(msg):
    """Print a message always, and log it."""
    print msg
    _log(msg, msgt_print)


def msg_init(recdict):
    """Set the MESSAGE variable according to the command line arguments.
       Skip this when it's already set from the command line."""
    from Util import get_var_val_int
    if get_var_val_int(recdict, "MESSAGE") is None:
        if Global.cmd_args.has_option("silent"):
            recdict["MESSAGE"] = msgt_error
        elif Global.cmd_args.has_option("verbose"):
            recdict["MESSAGE"] = msgt_all
        else:
            recdict["MESSAGE"] = (msgt_error + "," + msgt_warning + ","
                                               + msgt_system + "," + msgt_info)

# vim: set sw=4 et sts=4 tw=79 fo+=l:
