view mozillatry.py @ 3:7495c25d8476

WIP
author Jeff Hammel <jhammel@mozilla.com>
date Mon, 03 Dec 2012 21:49:55 -0800
parents 3eaee0d10880
children 14275dcbff10
line wrap: on
line source

#!/usr/bin/env python

"""
push patches to try
"""

import optparse
import os
import sys

from subprocess import check_call as call

def reset(directory):
    """reset an hg directory to a good state"""
    assert os.path.exists(directory) and os.path.isdir(directory)
    hg_dir = os.path.join(directory, '.hg')
    assert os.path.exists(hg_dir) and os.path.isdir(hg_dir)
    call(['hg', 'revert', '--no-backup', '--all'], cwd=directory)
    call(['hg', 'qpop', '--all'], cwd=directory)
    try:
        shutil.rmtree(os.path.join(hg_dir, 'patches')) # remove patches
    except:
        pass

def update(directory):
    """update a mozilla-central checkout"""
    assert os.path.exists(directory) and os.path.isdir(directory)
    reset(directory)
    call(['hg', 'pull'], cwd=directory)
    call(['hg', 'update'], cwd=directory)
    call(['hg', 'qinit'], cwd=directory)

def push_to_try(patches, repo, commit, _try='ssh://hg.mozilla.org/try/'):
    """push a series of patches to try repository"""

    # ensure the repo is in a good state
    update(repo)

    try:
        # apply patches
        for patch in patches:
            call(['hg', 'qimport', patch], cwd=repo)
            call(['hg', 'qpush', '--all'], cwd=repo)
            call(['hg', 'qseries', '-v'], cwd=repo)

        # push to try
        call(['hg', 'qref', '--message', commit], cwd=repo)
        call(['hg', 'push', '-f', _try], cwd=repo)
    finally:
        reset(repo)

def try_syntax(opt=True, debug=True, unittests=('all'), talos=('all'), bug=None):
    """
    return try syntax; see also:
    - https://github.com/pbiggar/trychooser
    - http://trychooser.pub.build.mozilla.org/
    """

    assert opt or debug
    message = ['try:']
    message += ['-b', '%s%s' % (('d' if debug else ''), ('o' if opt else ''))]
    message += ['-u', (','.join(unittests) if unittests else 'none')]
    message += ['-t', (','.join(talos) if talos else 'none')]
    if bug:
        message += ['--post-to-bugzilla', str(bug)]
    return ' '.join(message)

def add_options(parser):
    """add options for mozilla try to an OptionParser instance"""

    parser.add_option('--no-opt', dest='opt',
                      action='store_false', default=True,
                      help='no opt builds')
    parser.add_option('--no-debug', dest='debug',
                      action='store_false', default=True,
                      help='no debug builds')
    parser.add_option('-u', dest='unittests', action='append',
                      help='unittests')
    parser.add_option('-t', dest='talostests',
                      action='append',
                      help='talos tests')
    parser.add_option('--bug', dest='bug', type='int',
                      help='post to bugzilla bug #')
    parser.add_option('-c', '--config', dest='config',
                      default=os.path.join(os.environ['HOME'], '.mozutils.ini'),
                      help='location of config file')
    parser.add_option('-m', '--m-c', '--mozilla-central',
                      help="path to mozilla-central repository")


def read_config(filename, options):
    """read .mozutils config file and substitute for options if None"""

    # XXX stub; this should really use
    # e.g. http://k0s.org/mozilla/hg/configuration/
    from ConfigParser import ConfigParser
    parser = ConfigParser()
    if not os.path.exists(filename):
        return parser
    parser.read(filename)
    if options.mozilla_central is None:
        try:
            path = parser.get('hg', 'mozilla-central')
            if path:
                options.mozilla_central = os.path.expanduser(path)
        except Exception: # XXX temporary hack
            pass
    return parser

def check(parser, options, args):
    """check configuration"""

    if not args:
        parser.print_help()
        parser.exit()
    if (not options.opt) and (not options.debug):
        parser.error("Must enable opt or debug builds")


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

    # parse command line arguments
    usage = '%prog [options] patch <patch2> <...>'
    class PlainDescriptionFormatter(optparse.IndentedHelpFormatter):
        """description formatter"""
        def format_description(self, description):
            description = description.strip()
            if description:
                return description + '\n'
            else:
                return ''
    parser = optparse.OptionParser(usage=usage, description=__doc__, formatter=PlainDescriptionFormatter())
    add_options(parser)
    options, args = parser.parse_args(args)
    config_file = options.config
    read_config(config_file)

    # get mozilla-central repository directory
    if os.path.exists(config_file):
    try_directory = options.mozilla_central
    if (try_directory is None) or (not os.path.exists(try_directory)):
        parser.error("mozilla-central directory does not exist: %s" % try_directory)

    # build try syntax
    commit = try_syntax(**options.__dict__)
    print commit

    # push to try
    push_to_try(patches=args, repo=try_directory, commit=commit)

if __name__ == '__main__':
    main()