Mercurial > mozilla > hg > MozillaTry
view mozillatry.py @ 50:582f3571ab33 default tip
better help string
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Fri, 31 May 2013 19:48:55 -0700 |
parents | ca72b5866da1 |
children |
line wrap: on
line source
#!/usr/bin/env python """ push patches to try server """ # TODO: # it'd be nice to be able to push something from a patch queue import configuration import datetime import optparse import os import shutil import subprocess import sys from subprocess import check_call as call ### methods for hg 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) try: call(['hg', 'update', '-r', 'tip', '--clean'], cwd=directory) try: # XXX stupid; see # https://wiki.mozilla.org/Build:TryServer#hg_phases call(['hg', 'phase', '-f', '--draft', 'qbase:tip'], cwd=directory, stdout=subprocess.PIPE) except subprocess.CalledProcessError: pass call(['hg', 'qpop', '--all'], cwd=directory) patches = os.path.join(hg_dir, 'patches') if os.path.exists(patches): # remove patches shutil.rmtree(patches) except: sys.stderr.write("Directory: %s\n" % directory) raise def update_repo(directory): """update an hg repository""" 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 apply_patches(directory, *patches): """apply patches to an hg repository""" update_repo(directory) for patch in patches: call(['hg', 'qimport', patch, '--push'], cwd=directory) ### methods for try def push_to_try(patches, repo, commit, _try='ssh://hg.mozilla.org/try/', update=True): """push a series of patches to try repository""" # ensure the repo is in a good state if update: update_repo(repo) try: # if no patches given and not updating, commit what you have if not patches and not update: hg_dir = os.path.join(repo, '.hg') assert os.path.exists(hg_dir) and os.path.isdir(hg_dir) patches_dir = os.path.join(hg_dir, 'patches') if os.path.exists(patches_dir): shutil.rmtree(patches_dir) call(['hg', 'qinit'], cwd=repo) # TODO: ensure there's something to commit call(['hg', 'qnew', datetime.datetime.now().strftime("%Y%m%d%H%M%S")], cwd=repo) # 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, platforms=('all',), 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, "At least one of `opt` or `debug` must be true" assert platforms, "No platforms specified" message = ['try:'] message += ['-b', '%s%s' % (('d' if debug else ''), ('o' if opt else ''))] message += ['-p', ','.join(platforms)] message += ['-u', (','.join(unittests) if unittests else 'none')] message += ['-t', (','.join(talos) if talos else 'none')] if bug: message += ['--post-to-bugzilla', 'Bug', str(bug)] return ' '.join(message) ### configuration parsing class ConfigurationError(Exception): """error when checking configuration""" class MozillaTryConfiguration(configuration.Configuration): # default configuration file # TODO: upstream the pattern to configuration but with default_config_file = None default_config_file = os.path.join('~', '.mozutils') usage = '%prog [options] patch <patch2> <...>' load_help = 'load from config file' if os.path.exists(os.path.expanduser(default_config_file)): load_help += ' [DEFAULT: %s]' % default_config_file # configuration options options = {'opt': {'default': True, 'help': "whether to try on opt builds"}, 'debug': {'default': True, 'help': "whether to try on debug builds"}, 'platforms': {'default': [], 'help': "platforms to run on, 'all' if not specified", "flags": ["-p", "--platform"]}, 'unittests': {'default': [], 'help': "unit tests to run", 'flags': ['-u', '--unittests']}, 'talostests': {'default': [], 'help': "talos tests to run", 'flags': ['-t', '--talostests']}, 'mozilla_central': {'help': "path to mozilla-central clone", 'required': True, 'flags': ["--m-c", "--mozilla-central"]}, 'bug': {'help': "bug number to post try results to", 'type': int, 'flags': ['-b', '--bug']} } # configuration items to interpolate as paths paths = ['mozilla_central'] @classmethod def main(cls, args=sys.argv[1:]): instance = cls() options, args = instance.parse_args() if not args: instance.print_usage() instance.exit() return instance, options, args def __init__(self): configuration.Configuration.__init__(self, usage=self.usage, load='--config') def validate(self): """check configuration""" configuration.Configuration.validate(self) if (not self.config.get('opt')) and (not self.config.get('debug')): raise ConfigurationError("Must have opt or debug builds") for path in self.paths: self.config[path] = os.path.expanduser(self.config[path]) try_directory = self.config.get('mozilla_central') if (try_directory is None) or (not os.path.exists(try_directory)): raise ConfigurationError("mozilla-central directory does not exist: %s" % try_directory) if not self.config.get('platforms'): self.config['platforms'] = ['all'] def configuration_files(self, options, args): configuration_files = configuration.Configuration.configuration_files(self, options, args) if not configuration_files: default_config = os.path.expanduser(self.default_config_file) if os.path.exists(default_config): configuration_files = [default_config] return configuration_files def load_configuration_file(self, filename): config = configuration.Configuration.load_configuration_file(self, filename) # ignore options that we don't care about config = dict([(key, value) for key, value in config.items() if key in self.option_dict]) return config ### methods for try on mozilla-central def try_syntax(self): return try_syntax(opt=self.config.get('opt'), debug=self.config.get('debug'), platforms=self.config.get('platforms'), unittests=self.config.get('unittests', []), talos=self.config.get('talostests', []), bug=self.config.get('bug')) def push_to_try(self, patches, commit=None, repo=None): assert patches if commit is None: commit = self.try_syntax() repo = repo or self.config['mozilla_central'] push_to_try(patches=patches, repo=repo, commit=commit) def main(args=sys.argv[1:]): # parse command line arguments mozillatry, options, patches = MozillaTryConfiguration.main(args) # get mozilla-central repository directory try_directory = options.mozilla_central # build try syntax commit = mozillatry.try_syntax() print commit # push to try mozillatry.push_to_try(patches, commit=commit) if __name__ == '__main__': main()