#!/usr/bin/python
# vim:ts=4:sw=4:expandtab

# 
# Copyright (C) 2009 Red Hat, Inc.
#
# This file is part of IcedTea.
#
# IcedTea 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, version 2.
#
# IcedTea 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 IcedTea; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA.
#
# Linking this library statically or dynamically with other modules is
# making a combined work based on this library.  Thus, the terms and
# conditions of the GNU General Public License cover the whole
# combination.
#
# As a special exception, the copyright holders of this library give you
# permission to link this library with independent modules to produce an
# executable, regardless of the license terms of these independent
# modules, and to copy and distribute the resulting executable under
# terms of your choice, provided that you also meet, for each linked
# independent module, the terms and conditions of the license of that
# module.  An independent module is a module which is not derived from
# or based on this library.  If you modify this library, you may extend
# this exception to your version of the library, but you are not
# obligated to do so.  If you do not wish to do so, delete this
# exception statement from your version.
#

import os
import sys
import datetime
import subprocess
import smtplib

from email.mime.text import MIMEText


def generate_test_diff(old_file, new_file):
    """
    Return a diff-like output of changes between 2 files
    """
    
    diff = subprocess.Popen(['diff', '-bBdu', old_file, new_file], stdout=subprocess.PIPE)
    grep_additions = subprocess.Popen(['grep', '^+'], stdin=diff.stdout, stdout=subprocess.PIPE)
    grep_failed = subprocess.Popen(['grep', 'FAIL:'], stdin=grep_additions.stdout, stdout=subprocess.PIPE)
    raw_output = grep_failed.communicate()[0]
    raw_diff = raw_output.split('\n')
    pretty_diff = [ line[1:].split()[1] for line in raw_diff if len(line.strip()) > 0]
    
    output = pretty_diff
    output.sort()
    return output


def get_recent_committers(repo_dir, first_changeset, last_changeset):
    """
    Get list of recent commiters from repo
    """
    original_dir = os.getcwd()
    os.chdir(repo_dir)
    cmd =  ['hg', 'log', '-r', first_changeset + ':' + last_changeset,
        '--template', '{author}\n']
    log = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output = log.communicate()[0]
    committers = set([])
    for author in output.split('\n'):
        if len(author.strip()) > 0:
            committers.add(author)

    if log.returncode != 0:
        raise IOError('hg log failed: ' + log.communicate()[1])

    os.chdir(original_dir)
    return committers


def get_changelog(repo_dir, first_changeset, last_changeset):
    """
    Return the command used to get a changelog and the changelog itself
    """
    original_dir = os.getcwd()
    os.chdir(repo_dir)
    cmd =  ['hg', 'log', '-r', first_changeset + ':' + last_changeset,
        '--template', 'Author: {author}\n{desc}\n\n']
    log = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output = log.communicate()[0]

    if log.returncode != 0:
        raise IOError('hg log failed: ' + log.communicate()[1])

    os.chdir(original_dir)
    return (cmd, output)


def send_email(sender, receivers, subject, text):
    """
    Send text as email to receivers
    """

    message = MIMEText(text)

    message['From'] = sender
    message['To'] = ', '.join(receivers)
    message['Subject'] = subject

    s = smtplib.SMTP()
    s.connect('smtp.corp.redhat.com', 25)
    s.sendmail(sender, receivers , message.as_string())
    s.close()


def main(args):
    """
    Send email to recent committers on any test regresssions

    Usage:
        """ + args[0] + """ project old_mauve_file new_mauve_file 
        old_version_file new_version_file hg_dir old_changeset new_changeset

    args:
        project: the project name. used in email subject
        old_mauve_file: older mauve output 
        new_mauve_file: newer mauve output
        old_version_file: file containing output of 'java -version' for older mauve results
        new_version_file: file containing output of 'java -version' for newer mauve results
        hg_dir: path to hg dir containing changesets
        old_changeset: changeset of the older build
        new_changeset: changset of the newer build
    """

    if not (len(args) == 6 or len(args) == 9):
        sys.write(main.__doc__)
        exit(-1)

    # get the paramaters 
    project = args[1]
    older_file = args[2]
    latest_file = args[3]

    old_version_file = args[4]
    new_version_file = args[5]

    # if there is information about a repo, get that too
    if (len(args) == 9):
        have_changesets = True
        hg_dir = args[6]
        old_changeset = args[7]
        new_changeset = args[8]
    else:
        have_changesets = False

    diff_sender = project + ' Mauve <omajid@redhat.com>'
    email_subject = 'Regression in ' + project + '\'s Mauve Results'

    message = ''

    # add version information
    message = message + 'Regression from\n'

    for line in open(old_version_file, 'r'):
        if len(line.strip()) == 0:
            continue
        message = message + line.strip() + '\n'

    message = message + '\n'

    message = message + 'to\n'
    for line in open(new_version_file, 'r'):
        if len(line.strip()) == 0:
            continue
        message = message + line.strip() + '\n'

    message = message + '\n'

    test_list = generate_test_diff(older_file, latest_file)

    # no emails on a clean diff
    if (len(test_list) == 0):
        print 'No change in mauve tests'
        sys.exit(0)

    # list regresssions
    message = message + 'Regressions:\n'
    for test in test_list:
        message = message + test + '\n'
    
    message = message + '\n\n'

    # if we have changesets, include that information
    if (have_changesets):
        if old_changeset == new_changeset:
            message = message + 'No Recent Commits\n'
            message = message + 'This is probably an issue in the build system.\n'
        else:    
            cmd, changelog = get_changelog(hg_dir, old_changeset, new_changeset)
            message = message + 'Output of ' + ' '.join(cmd[:4]) + '\n'
            message = message + changelog
            #message = message + 'Commiters for changesets ' + old_changeset + ':' + \
            #    new_changeset + ':\n'
            #committers = get_recent_committers(hg_dir, old_changeset, new_changeset)
            #for committer in committers: 
            #    message = message + committer + '\n'

    #diff_receivers = [ 'Omair <omajid@redhat.com>', 'IcedTea6 Testresults <testresults@icedtea.classpath.org>' ]
    diff_receivers = [ 'Omair <omajid@redhat.com>']

    send_email(diff_sender, diff_receivers, email_subject , message)


if __name__ == '__main__':
    main(sys.argv)

