def CMDtry(parser, args):
    'Triggers try jobs through BuildBucket.'
    group = optparse.OptionGroup(parser, 'Try job options')
    group.add_option('-b', '--bot', action='append', help="IMPORTANT: specify ONE builder per --bot flag. Use it multiple times to specify multiple builders. ex: '-b win_rel -b win_layout'. See the try server waterfall for the builders name and the tests available.")
    group.add_option('-m', '--master', default='', help='Specify a try master where to run the tries.')
    group.add_option('--luci', action='store_true')
    group.add_option('-r', '--revision', help='Revision to use for the try job; default: the revision will be determined by the try server; see its waterfall for more info')
    group.add_option('-c', '--clobber', action='store_true', default=False, help="Force a clobber before building; e.g. don't do an incremental build")
    group.add_option('--project', help='Override which project to use. Projects are defined server-side to define what default bot set to use')
    group.add_option('-p', '--property', dest='properties', action='append', default=[], help='Specify generic properties in the form -p key1=value1 -p key2=value2 etc (buildbucket only). The value will be treated as json if decodable, or as string otherwise.')
    group.add_option('-n', '--name', help='Try job name; default to current branch name')
    group.add_option('--use-rietveld', action='store_true', default=False, help='Use Rietveld to trigger try jobs.')
    group.add_option('--buildbucket-host', default='cr-buildbucket.appspot.com', help='Host of buildbucket. The default host is %default.')
    parser.add_option_group(group)
    auth.add_auth_options(parser)
    (options, args) = parser.parse_args(args)
    auth_config = auth.extract_auth_config_from_options(options)
    if (options.use_rietveld and options.properties):
        parser.error('Properties can only be specified with buildbucket')
    bad_params = [x for x in options.properties if ('=' not in x)]
    if bad_params:
        parser.error(('Got properties with missing "=": %s' % bad_params))
    if args:
        parser.error(('Unknown arguments: %s' % args))
    cl = Changelist(auth_config=auth_config)
    if (not cl.GetIssue()):
        parser.error('Need to upload first')
    if cl.IsGerrit():
        parser.error('Not yet supported for Gerrit (http://crbug.com/599931).\nIf your project has Commit Queue, dry run is a workaround:\n  git cl set-commit --dry-run')
    props = cl.GetIssueProperties()
    if props.get('closed'):
        parser.error('Cannot send tryjobs for a closed CL')
    if props.get('private'):
        parser.error('Cannot use trybots with private issue')
    if (not options.name):
        options.name = cl.GetBranch()
    if (options.bot and (not options.master)):
        (options.master, err_msg) = GetBuilderMaster(options.bot)
        if err_msg:
            parser.error(('Tryserver master cannot be found because: %s\nPlease manually specify the tryserver master, e.g. "-m tryserver.chromium.linux".' % err_msg))

    def GetMasterMap():
        if (not options.bot):
            change = cl.GetChange(cl.GetCommonAncestorWithUpstream(), None)
            masters = presubmit_support.DoGetTryMasters(change, change.LocalPaths(), settings.GetRoot(), None, None, options.verbose, sys.stdout)
            if masters:
                return masters
            options.bot = presubmit_support.DoGetTrySlaves(change, change.LocalPaths(), settings.GetRoot(), None, None, options.verbose, sys.stdout)
            if (not options.bot):
                cq_cfg = os.path.join(change.RepositoryRoot(), 'infra', 'config', 'cq.cfg')
                if os.path.exists(cq_cfg):
                    masters = {}
                    cq_masters = commit_queue.get_master_builder_map(cq_cfg, include_experimental=False, include_triggered=False)
                    for (master, builders) in cq_masters.iteritems():
                        for builder in builders:
                            masters.setdefault(master, {})[builder] = ['defaulttests']
                    if masters:
                        print(('Loaded default bots from CQ config (%s)' % cq_cfg))
                        return masters
                    else:
                        print(('CQ config exists (%s) but has no try bots listed' % cq_cfg))
        if (not options.bot):
            parser.error('No default try builder to try, use --bot')
        builders_and_tests = {}
        old_style = filter((lambda x: isinstance(x, basestring)), options.bot)
        new_style = filter((lambda x: isinstance(x, tuple)), options.bot)
        for bot in old_style:
            if (':' in bot):
                parser.error('Specifying testfilter is no longer supported')
            elif (',' in bot):
                parser.error('Specify one bot per --bot flag')
            else:
                builders_and_tests.setdefault(bot, [])
        for (bot, tests) in new_style:
            builders_and_tests.setdefault(bot, []).extend(tests)
        return {options.master: builders_and_tests}
    masters = GetMasterMap()
    for builders in masters.itervalues():
        if any((('triggered' in b) for b in builders)):
            print(('ERROR You are trying to send a job to a triggered bot. This type of bot requires an\ninitial job from a parent (usually a builder).  Instead send your job to the parent.\nBot list: %s' % builders), file=sys.stderr)
            return 1
    patchset = cl.GetMostRecentPatchset()
    if (patchset and (patchset != cl.GetPatchset())):
        print(('\nWARNING Mismatch between local config and server. Did a previous upload fail?\ngit-cl try always uses latest patchset from rietveld. Continuing using\npatchset %s.\n' % patchset))
    if options.luci:
        trigger_luci_job(cl, masters, options)
    elif (not options.use_rietveld):
        try:
            trigger_try_jobs(auth_config, cl, options, masters, 'git_cl_try')
        except BuildbucketResponseException as ex:
            print(('ERROR: %s' % ex))
            return 1
        except Exception as e:
            stacktrace = (''.join(traceback.format_stack()) + traceback.format_exc())
            print(('ERROR: Exception when trying to trigger tryjobs: %s\n%s' % (e, stacktrace)))
            return 1
    else:
        try:
            cl.RpcServer().trigger_distributed_try_jobs(cl.GetIssue(), patchset, options.name, options.clobber, options.revision, masters)
        except urllib2.HTTPError as e:
            if (e.code == 404):
                print('404 from rietveld; did you mean to use "git try" instead of "git cl try"?')
                return 1
        print('Tried jobs on:')
        for (master, builders) in sorted(masters.iteritems()):
            if master:
                print(('Master: %s' % master))
            length = max((len(builder) for builder in builders))
            for builder in sorted(builders):
                print(('  %*s: %s' % (length, builder, ','.join(builders[builder]))))
    return 0
Triggers try jobs through BuildBucket.
def CMDtry(parser, args):
    
    group = optparse.OptionGroup(parser, 'Try job options')
    group.add_option('-b', '--bot', action='append', help="IMPORTANT: specify ONE builder per --bot flag. Use it multiple times to specify multiple builders. ex: '-b win_rel -b win_layout'. See the try server waterfall for the builders name and the tests available.")
    group.add_option('-m', '--master', default=, help='Specify a try master where to run the tries.')
    group.add_option('--luci', action='store_true')
    group.add_option('-r', '--revision', help='Revision to use for the try job; default: the revision will be determined by the try server; see its waterfall for more info')
    group.add_option('-c', '--clobber', action='store_true', default=False, help="Force a clobber before building; e.g. don't do an incremental build")
    group.add_option('--project', help='Override which project to use. Projects are defined server-side to define what default bot set to use')
    group.add_option('-p', '--property', dest='properties', action='append', default=[], help='Specify generic properties in the form -p key1=value1 -p key2=value2 etc (buildbucket only). The value will be treated as json if decodable, or as string otherwise.')
    group.add_option('-n', '--name', help='Try job name; default to current branch name')
    group.add_option('--use-rietveld', action='store_true', default=False, help='Use Rietveld to trigger try jobs.')
    group.add_option('--buildbucket-host', default='cr-buildbucket.appspot.com', help='Host of buildbucket. The default host is %default.')
    parser.add_option_group(group)
    auth.add_auth_options(parser)
    (options, args) = parser.parse_args(args)
    auth_config = auth.extract_auth_config_from_options(options)
    if (options.use_rietveld and options.properties):
        parser.error('Properties can only be specified with buildbucket')
    bad_params = [x for x in options.properties if ('=' not in x)]
    if bad_params:
        parser.error(('Got properties with missing "=": %s' % bad_params))
    if args:
        parser.error(('Unknown arguments: %s' % args))
    cl = Changelist(auth_config=auth_config)
    if (not cl.GetIssue()):
        parser.error('Need to upload first')
    if cl.IsGerrit():
        parser.error('Not yet supported for Gerrit (http://crbug.com/599931).\nIf your project has Commit Queue, dry run is a workaround:\n  git cl set-commit --dry-run')
    props = cl.GetIssueProperties()
    if props.get('closed'):
        parser.error('Cannot send tryjobs for a closed CL')
    if props.get('private'):
        parser.error('Cannot use trybots with private issue')
    if (not options.name):
        options.name = cl.GetBranch()
    if (options.bot and (not options.master)):
        (options.master, err_msg) = GetBuilderMaster(options.bot)
        if err_msg:
            parser.error(('Tryserver master cannot be found because: %s\nPlease manually specify the tryserver master, e.g. "-m tryserver.chromium.linux".' % err_msg))

    def GetMasterMap():
        if (not options.bot):
            change = cl.GetChange(cl.GetCommonAncestorWithUpstream(), None)
            masters = presubmit_support.DoGetTryMasters(change, change.LocalPaths(), settings.GetRoot(), None, None, options.verbose, sys.stdout)
            if masters:
                return masters
            options.bot = presubmit_support.DoGetTrySlaves(change, change.LocalPaths(), settings.GetRoot(), None, None, options.verbose, sys.stdout)
            if (not options.bot):
                cq_cfg = os.path.join(change.RepositoryRoot(), 'infra', 'config', 'cq.cfg')
                if os.path.exists(cq_cfg):
                    masters = {}
                    cq_masters = commit_queue.get_master_builder_map(cq_cfg, include_experimental=False, include_triggered=False)
                    for (master, builders) in cq_masters.iteritems():
                        for builder in builders:
                            masters.setdefault(master, {})[builder] = ['defaulttests']
                    if masters:
                        print(('Loaded default bots from CQ config (%s)' % cq_cfg))
                        return masters
                    else:
                        print(('CQ config exists (%s) but has no try bots listed' % cq_cfg))
        if (not options.bot):
            parser.error('No default try builder to try, use --bot')
        builders_and_tests = {}
        old_style = filter((lambda x: isinstance(x, basestring)), options.bot)
        new_style = filter((lambda x: isinstance(x, tuple)), options.bot)
        for bot in old_style:
            if (':' in bot):
                parser.error('Specifying testfilter is no longer supported')
            elif (',' in bot):
                parser.error('Specify one bot per --bot flag')
            else:
                builders_and_tests.setdefault(bot, [])
        for (bot, tests) in new_style:
            builders_and_tests.setdefault(bot, []).extend(tests)
        return {options.master: builders_and_tests}
    masters = GetMasterMap()
    for builders in masters.itervalues():
        if any((('triggered' in b) for b in builders)):
            print(('ERROR You are trying to send a job to a triggered bot. This type of bot requires an\ninitial job from a parent (usually a builder).  Instead send your job to the parent.\nBot list: %s' % builders), file=sys.stderr)
            return 1
    patchset = cl.GetMostRecentPatchset()
    if (patchset and (patchset != cl.GetPatchset())):
        print(('\nWARNING Mismatch between local config and server. Did a previous upload fail?\ngit-cl try always uses latest patchset from rietveld. Continuing using\npatchset %s.\n' % patchset))
    if options.luci:
        trigger_luci_job(cl, masters, options)
    elif (not options.use_rietveld):
        try:
            trigger_try_jobs(auth_config, cl, options, masters, 'git_cl_try')
        except BuildbucketResponseException as ex:
            print(('ERROR: %s' % ex))
            return 1
        except Exception as e:
            stacktrace = (.join(traceback.format_stack()) + traceback.format_exc())
            print(('ERROR: Exception when trying to trigger tryjobs: %s\n%s' % (e, stacktrace)))
            return 1
    else:
        try:
            cl.RpcServer().trigger_distributed_try_jobs(cl.GetIssue(), patchset, options.name, options.clobber, options.revision, masters)
        except urllib2.HTTPError as e:
            if (e.code == 404):
                print('404 from rietveld; did you mean to use "git try" instead of "git cl try"?')
                return 1
        print('Tried jobs on:')
        for (master, builders) in sorted(masters.iteritems()):
            if master:
                print(('Master: %s' % master))
            length = max((len(builder) for builder in builders))
            for builder in sorted(builders):
                print(('  %*s: %s' % (length, builder, ','.join(builders[builder]))))
    return 0