#!/usr/bin/env python
# vim: set ai et sw=4 ts=4 sts=4:
"""Script to remove retired devs from metadata.xml."""

import os
import sys
import difflib
import StringIO

try:
    import cElementTree as etree
except ImportError:
    try:
        from elementtree import ElementTree as etree
    except ImportError:
        print 'This script needs either celementtree (preferred, faster) or'
        print 'elementtree installed.'
        sys.exit(1)

def getretired(userinfo_path):
    """ Get a list of retired devs from userinfo.xml
    """
    retired = []
    userinfo = etree.parse(userinfo_path)

    for entry in userinfo.findall('user'):
        status = entry.find('status')
        if status is not None:
            if status.text == 'Retired' or status.text == 'retired':
                devname = entry.get('username')
                retired.append(devname)
    return retired

def herds(userinfo_path, herds_path):
    """ Show retired developers and which herds they are in
    """
    try:
        retired = getretired(userinfo_path)
    except:
        print >>sys.stderr, "Couldn't parse userinfo.xml"
        sys.exit(1)

    try:
        herds = etree.parse(herds_path)
    except:
        print >>sys.stderr, "Couldn't parse herds.xml"
        sys.exit(1)

    for herd in herds.findall('herd'):
        herdname = herd.find('name').text
        for entry in herd.findall('maintainer'):
            email = entry.find('email')
            username = email.text.replace('@gentoo.org','')
            if username in retired:
                print herdname + ':\t' + username
    return 0

def project(userinfo_path, files):
    """ Remove retired developers from project pages
    userinfo is path to proj/en/devrel/roll-call/userinfo.xml
    files is a list of project xmls
    """
    try:
        retired = getretired(userinfo_path)
    except:
        print >>sys.stderr, "Couldn't parse userinfo.xml"
        sys.exit(1)

    for file in files:
        try:
            project = etree.parse(file)
        except SyntaxError:
            print "Skipping %s, probably not a project xml" % file
            continue
        for entry in project.findall('dev'):
            if entry.text in retired:
                print file + ':\t' + entry.text


def metadata(devname, path):
    """ output a diff between current metadata.xml and
    metadata.xml with the retired dev removed.
    """
    email = '%s@gentoo.org' % devname
    if not os.path.isdir(path):
        print >>sys.stderr, '%r is not a directory' % path
        sys.exit(1)
    for root, dirs, files in os.walk(path):
        if 'metadata.xml' not in files:
            continue
        metadata_path = os.path.join(root, 'metadata.xml')
        try:
            metadata = etree.parse(metadata_path)
        except:
            print >>sys.stderr, "Couldn't parse %s .. skipping" % metadata_path
            continue

        changed = False
        noherd = False

        # Check if package has no-herd
        herd = metadata.find('herd')
        if herd is None or herd.text.strip() == 'no-herd':
            noherd = True

        for entry in metadata.findall('maintainer'):
            for mailentry in entry.findall('email'):
                if mailentry.text.strip() == email:
                    if noherd:
                        # remove name
                        for name in entry.findall('name'):
                            entry.remove(name)
                        mailentry.text = 'maintainer-needed@gentoo.org'
                    else:
                        metadata.getroot().remove(entry)
                    changed = True
        if changed:
            # we don't want the full path in the diff
            if not root.startswith(path + '/'):
                print 'wtf (not %r.startswith(%r/))' % (root, path)
                return 1
            shortpath = root[len(path) + 1:]
            newfile = StringIO.StringIO()
            # etree does not write the <?xml ...> header and DOCTYPE
            newfile.write('<?xml version="1.0" encoding="UTF-8"?>\n')
            newfile.write(
                '<!DOCTYPE pkgmetadata SYSTEM '
                '"http://www.gentoo.org/dtd/metadata.dtd">\n')
            metadata.write(newfile)
            # etree omits the final newline, add that to make the diff nicer
            newfile.write('\n')
            newfile.seek(0)
            # (skips the <?xml ...> and DOCTYPE lines, hopefully)
            for line in difflib.unified_diff(
                open(metadata_path).readlines(),
                list(newfile),
                '%s.orig' % shortpath,
                shortpath):
                print line,
            print
    return 0

def usage():
    print 'Usage: %s subcommand opts' % sys.argv[0]
    print 'Subcommands:'
    print '--herds /path/to/userinfo.xml /path/to/herds.xml : check herds.xml for retired developers'
    print '--metadata devname /path/to/tree :'
    print '\toutputs a diff between the current metadata.xml and'
    print '\tmetadata.xml with the retired dev removed.'
    print '--project /path/to/userinfo.xml project.xml ... :'
    print '\tcheck the given project pages for retired developers'
    sys.exit(1)

def main(args):
    subcommands = ( '--herds', '--metadata', '--project' )
    if len(args) == 1:
        usage()
    if args[1] not in subcommands:
        print args[1]
        usage()
    elif args[1] == '--herds':
        if not len(args) == 4:
            usage()
        herds(args[2],args[3])
    elif args[1] == '--metadata':
        if not len(args) == 4:
            usage()
        metadata(args[2], args[3])
    elif args[1] == '--project':
        project(args[2], args[2:])
    return 0
if __name__ == '__main__':
    sys.exit(main(sys.argv))
