#!/usr/bin/python -O
# Copyright 1999-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id: /var/cvsroot/gentoo-src/portage/bin/dispatch-conf,v 1.7.2.10 2005/05/12 15:20:22 jstubbs Exp $

#
# 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

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' and ((os.system( "which rcs >/dev/null 2>&1" ) == 256)
                                                 or (os.system( "which ci >/dev/null 2>&1" ) == 256)
                                                 or (os.system( "which co >/dev/null 2>&1" ) == 256) 
                                                 or (os.system( "which rcsmerge >/dev/null 2>&1" ) == 256)):
            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':
                    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'])
