#!/usr/bin/python -O
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

#
# dispatch-conf -- Integrate modified configs, post-emerge
#
#  Jeremy Wohl (http://igmus.org)
#
# TODO
#  dialog menus
#

from stat import *
from random import *
import os, shutil, sys, string, re, commands, atexit
sys.path = ["/usr/lib/portage/pym"]+sys.path

import portage, dispatch_conf
from portage_exec import find_binary

FIND_EXTANT_CONFIGS  = "find %s/ -iname '._cfg????_*' | sed -e 's://:/:g'"
DIFF_CONTENTS        = 'diff -Nu %s %s'
DIFF_CVS_INTERP      = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "# .Header:.*"'
DIFF_WSCOMMENTS      = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "^[-+]#" | grep -v "^[-+][:space:]*$"'

# We need a secure scratch dir and python does silly verbose errors on the use of tempnam
oldmask = os.umask(0077)
SCRATCH_DIR = None
while SCRATCH_DIR is None:
    try:
        mydir = "/tmp/dispatch-conf."
        for x in range(0,8):
            if int(random() * 3) == 0:
                mydir += chr(int(65+random()*26.0))
            elif int(random() * 2) == 0:
                mydir += chr(int(97+random()*26.0))
            else:
                mydir += chr(int(48+random()*10.0))
        if os.path.exists(mydir):
            continue
        os.mkdir(mydir)
        SCRATCH_DIR = mydir
    except OSError, e:
        if e.errno != 17:
            raise
os.umask(oldmask)

# Ensure the scratch dir is deleted
def cleanup(mydir=SCRATCH_DIR):
    shutil.rmtree(mydir)
atexit.register(cleanup)

MANDATORY_OPTS  = [ 'archive-dir', 'diff', 'replace-cvs', 'replace-wscomments', 'merge' ]

class dispatch:
    options = {}

    def grind (self, config_paths):
        confs = []
        count = 0


        self.options = dispatch_conf.read_config(MANDATORY_OPTS)

        if self.options.has_key("log-file"):
            if os.path.isfile(self.options["log-file"]):
                shutil.copy(self.options["log-file"], self.options["log-file"] + '.old')
            if os.path.isfile(self.options["log-file"]) \
               or not os.path.exists(self.options["log-file"]):
                open(self.options["log-file"], 'w').close() # Truncate it
                os.chmod(self.options["log-file"], 0600)
        else:
            self.options["log-file"] = "/dev/null"

        #
        # Build list of extant configs
        #

        for path in config_paths.split ():
            if not os.path.exists (path):
                continue

            confs += self.massage (os.popen (FIND_EXTANT_CONFIGS % (path,)).readlines ())

        if self.options['use-rcs'] == 'yes':
            for rcs_util in ("rcs", "ci", "co", "rcsmerge"):
                if not find_binary(rcs_util):
                    print >> sys.stderr, \
                        'dispatch-conf: Error finding all RCS utils and " + \
                        "use-rcs=yes in config; fatal'
                    return False


        #
        # Remove new configs identical to current
        #                  and
        # Auto-replace configs a) whose differences are simply CVS interpolations,
        #                  or  b) whose differences are simply ws or comments,
        #                  or  c) in paths now unprotected by CONFIG_PROTECT_MASK,
        #

        def f (conf):
            mrgconf = re.sub(r'\._cfg', '._mrg', conf['new'])
            archive = os.path.join(self.options['archive-dir'], conf['current'].lstrip('/'))
            if self.options['use-rcs'] == 'yes':
                mrgfail = dispatch_conf.rcs_archive(archive, conf['current'], conf['new'], mrgconf)
            else:
                mrgfail = dispatch_conf.file_archive(archive, conf['current'], conf['new'], mrgconf)
            if os.path.exists(archive + '.dist'):
                unmodified = len(commands.getoutput(DIFF_CONTENTS % (conf['current'], archive + '.dist'))) == 0
            else:
                unmodified = 0
            if os.path.exists(mrgconf):
                if mrgfail or len(commands.getoutput(DIFF_CONTENTS % (conf['new'], mrgconf))) == 0:
                    os.unlink(mrgconf)
                    newconf = conf['new']
                else:
                    newconf = mrgconf
            else:
                newconf = conf['new']

            same_file = len(commands.getoutput (DIFF_CONTENTS   % (conf ['current'], newconf))) == 0
            same_cvs  = len(commands.getoutput (DIFF_CVS_INTERP % (conf ['current'], newconf))) == 0
            same_wsc  = len(commands.getoutput (DIFF_WSCOMMENTS % (conf ['current'], newconf))) == 0

            # Do options permit?
            same_cvs = same_cvs and self.options['replace-cvs'] == 'yes'
            same_wsc = same_wsc and self.options['replace-wscomments'] == 'yes'
            unmodified = unmodified and self.options['replace-unmodified'] == 'yes'

            if same_file:
                os.unlink (conf ['new'])
                self.post_process(conf['current'])
                if os.path.exists(mrgconf):
                    os.unlink(mrgconf)
                return False
            elif unmodified or same_cvs or same_wsc or conf ['dir'] in portage.settings ['CONFIG_PROTECT_MASK'].split ():
                self.replace(newconf, conf['current'])
                self.post_process(conf['current'])
                if newconf == mrgconf:
                    os.unlink(conf['new'])
                elif os.path.exists(mrgconf):
                    os.unlink(mrgconf)
                return False
            else:
                return True

        confs = filter (f, confs)

        #
        # Interactively process remaining
        #

        for conf in confs:
            count = count + 1

            newconf = conf['new']
            mrgconf = re.sub(r'\._cfg', '._mrg', newconf)
            if os.path.exists(mrgconf):
                newconf = mrgconf
            show_new_diff = 0

            while 1:
                if show_new_diff:
                    os.system((self.options['diff']) % (conf['new'], mrgconf))
                    show_new_diff = 0
                else:
                    os.system((self.options['diff']) % (conf['current'], newconf))

                print
                print '>> (%i of %i) -- %s' % (count, len(confs), conf ['current'])
                print '>> q quit, h help, n next, e edit-new, z zap-new, u use-new\n   m merge, t toggle-merge, l look-merge: ',

                c = getch ()

                if c == 'q':
                    sys.exit (0)
                if c == 'h':
                    self.do_help ()
                    continue
                elif c == 't':
                    if newconf == mrgconf:
                        newconf = conf['new']
                    elif os.path.exists(mrgconf):
                        newconf = mrgconf
                    continue
                elif c == 'n':
                    break
                elif c == 'm':
                    merged = SCRATCH_DIR+"/"+os.path.basename(conf['current'])
                    print
                    ret = os.system (self.options['merge'] % (merged, conf ['current'], newconf))
                    if ret:
                        print "Failure running 'merge' command"
                        continue
                    shutil.copyfile(merged, mrgconf)
                    os.remove(merged)
                    mystat = os.lstat(conf['new'])
                    os.chmod(mrgconf, mystat[ST_MODE])
                    os.chown(mrgconf, mystat[ST_UID], mystat[ST_GID])
                    newconf = mrgconf
                    continue
                elif c == 'l':
                    show_new_diff = 1
                    continue
                elif c == 'e':
                    if not os.environ.has_key('EDITOR'):
                        os.environ['EDITOR']='nano'
                    os.system(os.environ['EDITOR'] + ' ' + newconf)
                    continue
                elif c == 'z':
                    os.unlink(conf['new'])
                    if os.path.exists(mrgconf):
                        os.unlink(mrgconf)
                    break
                elif c == 'u':
                    self.replace(newconf, conf ['current'])
                    self.post_process(conf['current'])
                    if newconf == mrgconf:
                        os.unlink(conf['new'])
                    elif os.path.exists(mrgconf):
                        os.unlink(mrgconf)
                    break
                else:
                    continue


    def replace (self, newconf, curconf):
        """Replace current config with the new/merged version.  Also logs
        the diff of what changed into the configured log file."""
        os.system((DIFF_CONTENTS % (curconf, newconf)) + '>>' + self.options["log-file"])
        try:
            shutil.copyfile(newconf, curconf)
            os.remove(newconf)
        except (IOError, os.error), why:
            print >> sys.stderr, 'dispatch-conf: Error renaming %s to %s: %s; fatal' % \
                  (newconf, curconf, str(why))


    def post_process(self, curconf):
        archive = os.path.join(self.options['archive-dir'], curconf.lstrip('/'))
        if self.options['use-rcs'] == 'yes':
            dispatch_conf.rcs_archive_post_process(archive)
        else:
            dispatch_conf.file_archive_post_process(archive)


    def massage (self, newconfigs):
        """Sort, rstrip, remove old versions, break into triad hash.

        Triad is dictionary of current (/etc/make.conf), new (/etc/._cfg0003_make.conf)
        and dir (/etc).

        We keep ._cfg0002_conf over ._cfg0001_conf and ._cfg0000_conf.
        """
        h = {}

        newconfigs.sort ()

        for nconf in newconfigs:
            nconf = nconf.rstrip ()
            conf  = re.sub (r'\._cfg\d+_', '', nconf)
            dir   = re.match (r'^(.+)/', nconf).group (1)

            if h.has_key (conf):
                mrgconf = re.sub(r'\._cfg', '._mrg', h[conf]['new'])
                if os.path.exists(mrgconf):
                    os.unlink(mrgconf)
                os.unlink(h[conf]['new'])

            h [conf] = { 'current' : conf, 'dir' : dir, 'new' : nconf }

        configs = h.values ()
        configs.sort (lambda a, b: cmp(a ['current'], b ['current']))

        return configs


    def do_help (self):
        print; print

        print '  u -- update current config with new config and continue'
        print '  z -- zap (delete) new config and continue'
        print '  n -- skip to next config, leave all intact'
        print '  e -- edit new config'
        print '  m -- interactively merge current and new configs'
        print '  l -- look at diff between pre-merged and merged configs'
        print '  t -- toggle new config between merged and pre-merged state'
        print '  h -- this screen'
        print '  q -- quit'

        print; print 'press any key to return to diff...',

        getch ()


def getch ():
    # from ASPN - Danny Yoo
    #
    import sys, tty, termios

    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(sys.stdin.fileno())
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch


# run
d = dispatch ()

if len(sys.argv) > 1:
    # for testing
    d.grind (string.join (sys.argv [1:]))
else:
    d.grind (portage.settings ['CONFIG_PROTECT'])
