#!/usr/bin/env python

# imports
import datetime
import getpass
import glob
import optparse
import os
import shutil
import subprocess
import re
import sys
import tempfile
import urllib2

# globals
HOME = os.environ['HOME']
USERNAME = getpass.getuser()
TALOS = os.path.join(HOME, 'mozilla/src/talos-staging/src/talos')
TALOS_REPO = 'http://hg.mozilla.org/build/talos'
MOZILLA_TRY = os.path.join(HOME, 'mozilla/src/mozilla-try')

try:
    from subprocess import check_call as call
except ImportError:
    from subprocess import call

def cleanup():
    """cleanup the repository"""
    if os.path.exists(TALOS):
        shutil.rmtree(TALOS)
    directory = os.path.dirname(TALOS)
    if not os.path.exists(directory):
        os.makedirs(directory)
    call(['hg', 'clone', TALOS_REPO], cwd=directory)

def apply_diff(diff):
    """applies a diff to the talos clone"""

    process = subprocess.Popen(['hg', 'import', diff, '-m', 'importing %s' % diff], cwd=TALOS)
    stdout, stderr = process.communicate()
    assert not process.returncode, "Patch %s did not work!" % diff

def main(args=sys.argv[1:]):

    # parse command line options
    usage = '%prog [options] diff [diff2] [...]'
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('-b', '--bug', dest='bugs',
                      action='append', default=[],
                      help="bug #")
    parser.add_option('--no-try', dest='push_to_try',
                      action='store_false', default=True,
                      help="don't push to try server")
    parser.add_option('-z', '--zip', dest='zip',
                      action='store_true', default=False,
                      help='take the singular argument as a talos.zip file')
    parser.add_option('-p', '--platform', dest='platforms',
                      action='append',
                      help="platform for try chooser")
    parser.add_option('-t', dest='tests',
                      action='append',
                      help="tests for try chooser")
    options, args = parser.parse_args(args)
    if not args:
        parser.print_help()
        parser.exit()

    # ensure bug #s are ints
    try:
        options.bugs = [int(bug) for bug in options.bugs]
    except ValueError:
        parser.error("Bug number must be an integer: %s" % options.bugs)

    if options.zip:
        # a talos.zip file
        if len(args) != 1:
            parser.error("-z, --zip may only be used with a single talos.zip argument")
        dest = args[0]
        bugstring = 'bug-%s' % ('+'.join([('%d' % bug) for bug in options.bugs]))
    else:
        # get the bug #
        if not options.bugs:
            for arg in args:
                regex = 'bug[-]?(\d+)'
                match = re.search(regex, args[0])
                if match:
                    options.bugs.append(int(match.groups()[0]))
        bugstring = 'bug-%s' % ('+'.join([('%d' % bug) for bug in options.bugs]))

        # cleanup the repository
        cleanup()

        # apply the diffs
        for diff in args:
            apply_diff(diff)

        # modify run_tests.py so we can see what we're testing
        run_tests = os.path.join(TALOS, 'talos', 'run_tests.py')
        assert os.path.exists(run_tests)
        f = file(run_tests, 'a')
        print >> f, '  print %s' % (args)
        f.close()

        # zip up the talos
        zips = glob.glob(os.path.join(TALOS, 'talos*.zip'))
        if zips:
            for filename in zips:
                os.remove(filename)
        command = [sys.executable, 'create_talos_zip.py']
        process = subprocess.Popen(command, cwd=TALOS, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        if process.returncode:
            print >> sys.stderr, "create_talos_zip.py failed!"
            print >> sys.stderr, "stdout::"
            print >> sys.stderr, stdout
            print >> sys.stderr, "stderr::"
            print >> sys.stderr, stderr
            sys.exit(process.returncode)
        src = stdout.strip()
        assert os.path.exists(src)
        dest_filename = 'talos.%s.zip' % bugstring
        dest = '%s@people.mozilla.org:~/public_html/%s' % (USERNAME, dest_filename)
        call(['scp', src, dest])
        dest = 'http://people.mozilla.com/~%s/%s' % (USERNAME, dest_filename)

    # push to try if specified
    if options.push_to_try:
        assert os.path.exists(MOZILLA_TRY) and os.path.isdir(MOZILLA_TRY)
        hg_dir = os.path.join(MOZILLA_TRY, '.hg')
        assert os.path.exists(hg_dir) and os.path.isdir(hg_dir)
        call(['hg', 'qpop', '--all'], cwd=MOZILLA_TRY)
        try:
            shutil.rmtree(os.path.join(hg_dir, 'patches')) # remove patches
        except:
            pass
        call(['hg', 'pull'], cwd=MOZILLA_TRY)
        call(['hg', 'update'], cwd=MOZILLA_TRY)
        call(['hg', 'qinit'], cwd=MOZILLA_TRY)
        call(['hg', 'qnew', 'bug-%s' % bugstring], cwd=MOZILLA_TRY)

        # build try syntax
        if options.platforms:
            platforms = ','.join(options.platforms)
        else:
            platforms = 'all'
        if options.tests:
            tests = ','.join(options.tests)
        else:
            tests = 'all'
        commit = 'try: -b o -p %s -u none -t %s' % (platforms, tests) # http://trychooser.pub.build.mozilla.org/
        for bug in options.bugs:
            commit += ' --post-to-bugzilla Bug %d' % bug
        print commit

        # make talos.json file
        template = """{
    "talos.zip": {
        "url": "%s",
        "path": ""
    }
}
"""
        talos_json = os.path.join(MOZILLA_TRY, 'testing', 'talos', 'talos.json')
        assert os.path.exists(talos_json), "'%s' not found" % talos_json
        f = file(talos_json, 'w')
        f.write(template % dest)
        f.close()
        call(['hg', 'qref', '--message', commit], cwd=MOZILLA_TRY)
        call(['hg', 'push', '-f', 'ssh://hg.mozilla.org/try/'], cwd=MOZILLA_TRY)
        call(['hg', 'qpop', '--all'], cwd=MOZILLA_TRY)
        shutil.rmtree(os.path.join(hg_dir, 'patches')) # remove patches

if __name__ == '__main__':
    main()
