#!/usr/bin/python
#
# pkgorder
#
# Copyright (C) 2005,2006,2007,2008,2009  Red Hat, Inc.  All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Author(s): Paul Nasrat <pnasrat@redhat.com>
#            Jesse Keating <jkeating@redhat.com>
#

import os.path
import glob
import rpm
import rpmUtils
import shutil
import string
import sys
import yum

sys.path.append("/usr/lib/anaconda")
sys.path.append("/usr/lib/booty")

import anaconda_log
import logging
logger = logging.getLogger("anaconda")
handler = logging.StreamHandler()
handler.setLevel(logging.ERROR)
logger.addHandler(handler)

from optparse import OptionParser
import yum

class PackageOrderer(yum.YumBase):
    def __init__(self, arch=None):
        yum.YumBase.__init__(self)
        self._arch = arch

    def _transactionDataFactory(self):
        return yum.transactioninfo.SortableTransactionData()

    def doFileLogSetup(self, uid, logfile):
        pass

    def doLoggingSetup(self, *args, **kwargs):
        pass

    def setup(self, fn="/etc/yum.conf", root="/", excludes=[]):
        self.doConfigSetup(fn, root, init_plugins = False)
        self.conf.cache = 0
#         if hasattr(self.repos, 'sqlite'):
#             self.repos.sqlite = False
#             self.repos._selectSackType()
        exclude = self.conf.exclude
        exclude.extend(excludes)
        self.conf.exclude = exclude
        cachedir = yum.misc.getCacheDir()
        self.repos.setCacheDir(cachedir) 
        self.repos.setCache(0) 
        self.doRepoSetup()

        self.doSackSetup(rpmUtils.arch.getArchList(self._arch))
        self.doTsSetup()
        self.doGroupSetup()
        self.repos.populateSack('enabled', 'filelists')

    def getDownloadPkgs(self):
        pass

#XXX: sigh
processed = {}
def processTransaction(ds):
    del ds.ts
    ds.initActionTs()
    ds.populateTs(keepold=0)
    ds.ts.check()
    ds.ts.order()
    for (hdr, path) in ds.ts.ts.getKeys():
        fname = os.path.basename(path)
        fpattern = "%s*" % fname.rsplit('.', 2)[0]
        printMatchingPkgs(fpattern)

def printMatchingPkgs(fpattern):
    global processed

    if os.path.isdir("%s/%s/RPMS" % (toppath, product)):
        matches = glob.glob("%s/%s/RPMS/%s" % (toppath, product, fpattern))
    elif os.path.isdir("%s/%s" %(toppath, product)):
        matches = glob.glob("%s/%s/%s" % (toppath, product, fpattern))
    else:
        matches = glob.glob("%s/%s" % (toppath, fpattern))

    for match in matches:
        mname = os.path.basename(match)
        if processed.has_key(mname): continue
        processed[mname] = True
        print mname

def addPackages(ds, pkgLst):
    ds.initActionTs()
    for pkg in pkgLst:
        try:
            ds.install(pattern=pkg)
        except yum.Errors.InstallError, e:
            print >> sys.stderr, "Error adding %s: %s" % (pkg, e)
    ds.resolveDeps()
    processTransaction(ds)

def addGroups(ds, groupLst):
    ds.initActionTs()
    map(ds.selectGroup, filter(lambda x: ds.comps.has_group(x), groupLst))
    ds.resolveDeps()
    processTransaction(ds)

def createConfig(toppath):
    yumconfstr = """
[main]
distroverpkg=redhat-release
gpgcheck=0
reposdir=/dev/null
exclude=*debuginfo*

[anaconda]
name=Anaconda
baseurl=file://%s
enabled=1
""" % (toppath)
    
    try:
        (fd, path) = tempfile.mkstemp("", "yum-conf-", toppath)
    except (OSError, IOError), e:
        print >> sys.stderr, "Error writing to %s" % (toppath,)
        sys.exit(1)
    os.write(fd, yumconfstr)
    os.close(fd)
    return path

def usage():
    print >> sys.stderr, "pkgorder <toppath> <arch> <productpath>"
    print >> sys.stderr, "<arch>: use rpm architecture for tree, eg i686"

if __name__ == "__main__":
    import tempfile
    parser = OptionParser()
    parser.add_option("--debug", action="store_true", dest="debug", default=False)
    parser.add_option("--file", action="store", dest="file")
    parser.add_option("--product", action="store", dest="productPath", )
    parser.add_option("--exclude", action="append", dest="excludeList",
                      default=[])

    (options, args) = parser.parse_args()
     
    if len(args) != 3:
	usage()
        sys.exit(1)

    (toppath, arch, product) = args
    config = createConfig(toppath)

    # Boo.
    if arch == "i386":
        arch = "i686"
    if arch == "sparc":
        arch = "sparc64v"

    # print out kernel related packages first
    #printMatchingPkgs("kernel-*")        

    if os.environ.has_key('TMPDIR'):
        testpath = "%s/pkgorder-%d" %(os.environ['TMPDIR'],os.getpid(),)
    else:
        testpath = "/tmp/pkgorder-%d" %(os.getpid(),)

    os.system("mkdir -p %s/var/lib/rpm" %(testpath,))
    
    ds = PackageOrderer(arch=arch)
    ds.setup(fn=config, excludes=options.excludeList, root = testpath)
    
    # hack, hack, hack... make sure iscsi ends up on disc1 (#208832)
    addPackages(ds, ["kernel-*","dracut","mdadm"])

    # add the packages anaconda forces on us
    addPackages(ds, ["authconfig", "chkconfig", "dracut", "system-config-firewall-tui"])

    addGroups(ds, ["core", "base", "text-internet"])

    addGroups(ds, ["base-x", "dial-up",
                   "graphical-internet", "editors", 
                   "gnome-desktop", "sound-and-video", "printing",
                   "fonts", "hardware-support", "admin-tools", "online-docs",
                   "java", "legacy-fonts", "input-methods"])

    addGroups(ds, ["office", "games", "graphics", "authoring-and-publishing"])

    addGroups(ds, ["web-server", "ftp-server", "sql-server",
                   "mysql", "server-cfg", "dns-server",
                   "smb-server"])

    addGroups(ds, ["kde-desktop", "development-tools", "development-libs",
                   "gnome-software-development", "eclipse",
                   "x-software-development",
                   "java-development", "kde-software-development",
                   "mail-server", "network-server", "legacy-network-server"])

    addGroups(ds, ["news-server", "legacy-software-development", 
                   "engineering-and-scientific"])

    #Everthing else but kernels
    for po in ds.pkgSack.returnPackages():
        if po.name.find("kernel") == -1:
            member = ds.tsInfo.addInstall(po)

    ds.resolveDeps()
    processTransaction(ds)
    os.unlink(config)
    shutil.rmtree(testpath)
