Example #1
0
def _GenTSBotSpec(checkouts, change, changed_files, options):
    bot_spec = []
    # Get try slaves from PRESUBMIT.py files if not specified.
    # Even if the diff comes from options.url, use the local checkout for bot
    # selection.
    try:
        import presubmit_support
        root_presubmit = checkouts[0].ReadRootFile('PRESUBMIT.py')
        if not change:
            if not changed_files:
                changed_files = checkouts[0].file_tuples
            change = presubmit_support.Change(options.name, '',
                                              checkouts[0].checkout_root,
                                              changed_files, options.issue,
                                              options.patchset, options.email)
        trybots = presubmit_support.DoGetTrySlaves(
            change, checkouts[0].GetFileNames(), checkouts[0].checkout_root,
            root_presubmit, options.project, options.verbose, sys.stdout)
        if trybots:
            old_style = filter(lambda x: isinstance(x, basestring), trybots)
            new_style = filter(lambda x: isinstance(x, tuple), trybots)

            # _ParseBotList's testfilter is set to None otherwise it will complain.
            bot_spec = _ApplyTestFilter(options.testfilter,
                                        _ParseBotList(old_style, None))

            bot_spec.extend(_ApplyTestFilter(options.testfilter, new_style))

    except ImportError:
        pass

    return bot_spec
Example #2
0
def _GenTSBotSpec(checkouts, change, changed_files, options):
  bot_spec = []
  # Get try slaves from PRESUBMIT.py files if not specified.
  # Even if the diff comes from options.url, use the local checkout for bot
  # selection.
  try:
    import presubmit_support
    root_presubmit = checkouts[0].ReadRootFile('PRESUBMIT.py')
    if not change:
      if not changed_files:
        changed_files = checkouts[0].file_tuples
      change = presubmit_support.Change(options.name,
                                        '',
                                        checkouts[0].checkout_root,
                                        changed_files,
                                        options.issue,
                                        options.patchset,
                                        options.email)
    masters = presubmit_support.DoGetTryMasters(
        change,
        checkouts[0].GetFileNames(),
        checkouts[0].checkout_root,
        root_presubmit,
        options.project,
        options.verbose,
        sys.stdout)

    # Compatibility for old checkouts and bots that were on tryserver.chromium.
    trybots = masters.get('tryserver.chromium', [])

    # Compatibility for checkouts that are not using tryserver.chromium
    # but are stuck with git-try or gcl-try.
    if not trybots and len(masters) == 1:
      trybots = masters.values()[0]

    if trybots:
      old_style = filter(lambda x: isinstance(x, basestring), trybots)
      new_style = filter(lambda x: isinstance(x, tuple), trybots)

      # _ParseBotList's testfilter is set to None otherwise it will complain.
      bot_spec = _ApplyTestFilter(options.testfilter,
                                  _ParseBotList(old_style, None))

      bot_spec.extend(_ApplyTestFilter(options.testfilter, new_style))

  except ImportError:
    pass

  return bot_spec
Example #3
0
def TryChange(argv, change, swallow_exception, prog=None, extra_epilog=None):
    """
  Args:
    argv: Arguments and options.
    change: Change instance corresponding to the CL.
    swallow_exception: Whether we raise or swallow exceptions.
  """
    parser = gen_parser(prog)
    epilog = EPILOG % {'prog': prog}
    if extra_epilog:
        epilog += extra_epilog
    parser.epilog = epilog
    # Remove epilog formatting
    parser.format_epilog = lambda x: parser.epilog

    options, args = parser.parse_args(argv)

    # If they've asked for help, give it to them
    if len(args) == 1 and args[0] == 'help':
        parser.print_help()
        return 0

    # If they've said something confusing, don't spawn a try job until you
    # understand what they want.
    if args:
        parser.error('Extra argument(s) "%s" not understood' % ' '.join(args))

    if options.dry_run:
        options.verbose += 1

    LOG_FORMAT = '%(levelname)s %(filename)s(%(lineno)d): %(message)s'
    if not swallow_exception:
        if options.verbose == 0:
            logging.basicConfig(level=logging.WARNING, format=LOG_FORMAT)
        elif options.verbose == 1:
            logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
        elif options.verbose > 1:
            logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT)

    logging.debug(argv)

    if (options.patchlevel is not None
            and (options.patchlevel < 0 or options.patchlevel > 10)):
        parser.error(
            'Have you tried --port instead? You probably confused -p and -P.')

    # Strip off any @ in the user, otherwise svn gets confused.
    options.user = options.user.split('@', 1)[0]

    if options.rietveld_url:
        # Try to extract the review number if possible and fix the protocol.
        if not '://' in options.rietveld_url:
            options.rietveld_url = 'http://' + options.rietveld_url
        match = re.match(r'^(.*)/(\d+)/?$', options.rietveld_url)
        if match:
            if options.issue or options.patchset:
                parser.error(
                    'Cannot use both --issue and use a review number url')
            options.issue = int(match.group(2))
            options.rietveld_url = match.group(1)

    try:
        changed_files = None
        # Always include os.getcwd() in the checkout settings.
        checkouts = []
        path = os.getcwd()

        file_list = []
        if options.files:
            file_list = options.files
        elif change:
            file_list = [f.LocalPath() for f in change.AffectedFiles()]

        if options.upstream_branch:
            path += '@' + options.upstream_branch
            # Clear file list so that the correct list will be retrieved from the
            # upstream branch.
            file_list = []
        checkouts.append(GuessVCS(options, path, file_list))
        checkouts[0].AutomagicalSettings()
        for item in options.sub_rep:
            # Pass file_list=None because we don't know the sub repo's file list.
            checkout = GuessVCS(options,
                                os.path.join(checkouts[0].checkout_root, item),
                                None)
            if checkout.checkout_root in [c.checkout_root for c in checkouts]:
                parser.error('Specified the root %s two times.' %
                             checkout.checkout_root)
            checkouts.append(checkout)

        can_http = options.port and options.host
        can_svn = options.svn_repo
        # If there was no transport selected yet, now we must have enough data to
        # select one.
        if not options.send_patch and not (can_http or can_svn):
            parser.error('Please specify an access method.')

        # Convert options.diff into the content of the diff.
        if options.url:
            if options.files:
                parser.error(
                    'You cannot specify files and --url at the same time.')
            options.diff = urllib.urlopen(options.url).read()
        elif options.diff:
            if options.files:
                parser.error(
                    'You cannot specify files and --diff at the same time.')
            options.diff = gclient_utils.FileRead(options.diff, 'rb')
        elif options.issue and options.patchset is None:
            # Retrieve the patch from rietveld when the diff is not specified.
            # When patchset is specified, it's because it's done by gcl/git-try.
            api_url = '%s/api/%d' % (options.rietveld_url, options.issue)
            logging.debug(api_url)
            contents = json.loads(urllib.urlopen(api_url).read())
            options.patchset = contents['patchsets'][-1]
            diff_url = (
                '%s/download/issue%d_%d.diff' %
                (options.rietveld_url, options.issue, options.patchset))
            diff = GetMungedDiff('', urllib.urlopen(diff_url).readlines())
            options.diff = ''.join(diff[0])
            changed_files = diff[1]
        else:
            # Use this as the base.
            root = checkouts[0].checkout_root
            diffs = []
            for checkout in checkouts:
                raw_diff = checkout.GenerateDiff()
                if not raw_diff:
                    logging.error('Empty or non-existant diff, exiting.')
                    return 1
                diff = raw_diff.splitlines(True)
                path_diff = gclient_utils.PathDifference(
                    root, checkout.checkout_root)
                # Munge it.
                diffs.extend(GetMungedDiff(path_diff, diff)[0])
            options.diff = ''.join(diffs)

        if not options.name:
            if options.issue:
                options.name = 'Issue %s' % options.issue
            else:
                options.name = 'Unnamed'
                print('Note: use --name NAME to change the try job name.')

        if not options.email:
            parser.error(
                'Using an anonymous checkout. Please use --email or set '
                'the TRYBOT_RESULTS_EMAIL_ADDRESS environment variable.')
        print('Results will be emailed to: ' + options.email)

        if not options.bot:
            # Get try slaves from PRESUBMIT.py files if not specified.
            # Even if the diff comes from options.url, use the local checkout for bot
            # selection.
            try:
                import presubmit_support
                root_presubmit = checkouts[0].ReadRootFile('PRESUBMIT.py')
                if not change:
                    if not changed_files:
                        changed_files = checkouts[0].file_tuples
                    change = presubmit_support.Change(
                        options.name, '', checkouts[0].checkout_root,
                        changed_files, options.issue, options.patchset,
                        options.email)
                options.bot = presubmit_support.DoGetTrySlaves(
                    change, checkouts[0].GetFileNames(),
                    checkouts[0].checkout_root, root_presubmit,
                    options.project, options.verbose, sys.stdout)
            except ImportError:
                pass
            if options.testfilter:
                bots = set()
                for bot in options.bot:
                    assert ',' not in bot
                    if bot.endswith(':compile'):
                        # Skip over compile-only builders for now.
                        continue
                    bots.add(bot.split(':', 1)[0])
                options.bot = list(bots)

            # If no bot is specified, either the default pool will be selected or the
            # try server will refuse the job. Either case we don't need to interfere.

        if any('triggered' in b.split(':', 1)[0] for b in options.bot):
            print >> sys.stderr, (
                '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' %
                options.bot)
            return 1

        if options.print_bots:
            print 'Bots which would be used:'
            for bot in options.bot:
                print '  %s' % bot
            return 0

        # Send the patch.
        if options.send_patch:
            # If forced.
            options.send_patch(options)
            PrintSuccess(options)
            return 0
        try:
            if can_http:
                _SendChangeHTTP(options)
                PrintSuccess(options)
                return 0
        except NoTryServerAccess:
            if not can_svn:
                raise
        _SendChangeSVN(options)
        PrintSuccess(options)
        return 0
    except (InvalidScript, NoTryServerAccess), e:
        if swallow_exception:
            return 1
        print >> sys.stderr, e
        return 1
Example #4
0
def TryChange(argv, change, swallow_exception, prog=None, extra_epilog=None):
    """
  Args:
    argv: Arguments and options.
    change: Change instance corresponding to the CL.
    swallow_exception: Whether we raise or swallow exceptions.
  """
    # Parse argv
    parser = optparse.OptionParser(usage=USAGE, version=__version__, prog=prog)
    epilog = EPILOG % {'prog': prog}
    if extra_epilog:
        epilog += extra_epilog
    parser.epilog = epilog
    # Remove epilog formatting
    parser.format_epilog = lambda x: parser.epilog
    parser.add_option("-v",
                      "--verbose",
                      action="count",
                      default=0,
                      help="Prints debugging infos")
    group = optparse.OptionGroup(parser, "Result and status")
    group.add_option("-u",
                     "--user",
                     default=getpass.getuser(),
                     help="Owner user name [default: %default]")
    group.add_option(
        "-e",
        "--email",
        default=os.environ.get('TRYBOT_RESULTS_EMAIL_ADDRESS',
                               os.environ.get('EMAIL_ADDRESS')),
        help="Email address where to send the results. Use either "
        "the TRYBOT_RESULTS_EMAIL_ADDRESS environment "
        "variable or EMAIL_ADDRESS to set the email address "
        "the try bots report results to [default: %default]")
    group.add_option("-n", "--name", help="Descriptive name of the try job")
    group.add_option("--issue",
                     type='int',
                     help="Update rietveld issue try job status")
    group.add_option("--patchset",
                     type='int',
                     help="Update rietveld issue try job status. This is "
                     "optional if --issue is used, In that case, the "
                     "latest patchset will be used.")
    group.add_option("--dry_run",
                     action='store_true',
                     help="Don't send the try job. This implies --verbose, so "
                     "it will print the diff.")
    parser.add_option_group(group)

    group = optparse.OptionGroup(parser, "Try job options")
    group.add_option("-b",
                     "--bot",
                     action="append",
                     help="Only use specifics build slaves, ex: "
                     "'--bot win,layout_mac'; see the try "
                     "server waterfall for the slave's name")
    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",
                     help="Force a clobber before building; e.g. don't do an "
                     "incremental build")
    # TODO(maruel): help="Select a specific configuration, usually 'debug' or "
    #                    "'release'"
    group.add_option("--target", help=optparse.SUPPRESS_HELP)

    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(
        "-t",
        "--testfilter",
        action="append",
        help="Add a gtest_filter to a test. Use multiple times to "
        "specify filters for different tests. (i.e. "
        "--testfilter base_unittests:ThreadTest.* "
        "--testfilter ui_tests) If you specify any testfilters "
        "the test results will not be reported in rietveld and "
        "only tests with filters will run.")

    parser.add_option_group(group)

    group = optparse.OptionGroup(parser, "Patch to run")
    group.add_option("-f",
                     "--file",
                     default=[],
                     dest="files",
                     metavar="FILE",
                     action="append",
                     help="Use many times to list the files to include in the "
                     "try, relative to the repository root")
    group.add_option("--diff", help="File containing the diff to try")
    group.add_option("--url",
                     help="Url where to grab a patch, e.g. "
                     "http://example.com/x.diff")
    group.add_option("-R",
                     "--rietveld_url",
                     default="codereview.appspot.com",
                     metavar="URL",
                     help="Has 2 usages, both refer to the rietveld instance: "
                     "Specify which code review patch to use as the try job "
                     "or rietveld instance to update the try job results "
                     "Default:%default")
    group.add_option("--root",
                     help="Root to use for the patch; base subdirectory for "
                     "patch created in a subdirectory")
    group.add_option("-p",
                     "--patchlevel",
                     type='int',
                     metavar="LEVEL",
                     help="Used as -pN parameter to patch")
    group.add_option("-s",
                     "--sub_rep",
                     action="append",
                     default=[],
                     help="Subcheckout to use in addition. This is mainly "
                     "useful for gclient-style checkouts. In git, checkout "
                     "the branch with changes first. Use @rev or "
                     "@branch to specify the "
                     "revision/branch to diff against. If no @branch is "
                     "given the diff will be against the upstream branch. "
                     "If @branch then the diff is branch..HEAD. "
                     "All edits must be checked in.")
    group.add_option("--no_search",
                     action="store_true",
                     help=("Disable automatic search for gclient or repo "
                           "checkout root."))
    group.add_option(
        "-E",
        "--exclude",
        action="append",
        default=['ChangeLog'],
        metavar='REGEXP',
        help="Regexp patterns to exclude files. Default: %default")
    group.add_option("--upstream_branch",
                     action="store",
                     help="Specify the upstream branch to diff against in the "
                     "main checkout")
    parser.add_option_group(group)

    group = optparse.OptionGroup(parser, "Access the try server by HTTP")
    group.add_option("--use_http",
                     action="store_const",
                     const=_SendChangeHTTP,
                     dest="send_patch",
                     help="Use HTTP to talk to the try server [default]")
    group.add_option("-H", "--host", help="Host address")
    group.add_option("-P", "--port", type="int", help="HTTP port")
    group.add_option("--proxy", help="HTTP proxy")
    parser.add_option_group(group)

    group = optparse.OptionGroup(parser, "Access the try server with SVN")
    group.add_option("--use_svn",
                     action="store_const",
                     const=_SendChangeSVN,
                     dest="send_patch",
                     help="Use SVN to talk to the try server")
    group.add_option(
        "-S",
        "--svn_repo",
        metavar="SVN_URL",
        help="SVN url to use to write the changes in; --use_svn is "
        "implied when using --svn_repo")
    parser.add_option_group(group)

    options, args = parser.parse_args(argv)

    # If they've asked for help, give it to them
    if len(args) == 1 and args[0] == 'help':
        parser.print_help()
        return 0

    # If they've said something confusing, don't spawn a try job until you
    # understand what they want.
    if args:
        parser.error('Extra argument(s) "%s" not understood' % ' '.join(args))

    if options.dry_run:
        options.verbose += 1

    LOG_FORMAT = '%(levelname)s %(filename)s(%(lineno)d): %(message)s'
    if not swallow_exception:
        if options.verbose == 0:
            logging.basicConfig(level=logging.WARNING, format=LOG_FORMAT)
        elif options.verbose == 1:
            logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
        elif options.verbose > 1:
            logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT)

    logging.debug(argv)

    if (options.patchlevel is not None
            and (options.patchlevel < 0 or options.patchlevel > 10)):
        parser.error(
            'Have you tried --port instead? You probably confused -p and -P.')

    # Strip off any @ in the user, otherwise svn gets confused.
    options.user = options.user.split('@', 1)[0]

    if options.rietveld_url:
        # Try to extract the review number if possible and fix the protocol.
        if not '://' in options.rietveld_url:
            options.rietveld_url = 'http://' + options.rietveld_url
        match = re.match(r'^(.*)/(\d+)/?$', options.rietveld_url)
        if match:
            if options.issue or options.patchset:
                parser.error(
                    'Cannot use both --issue and use a review number url')
            options.issue = int(match.group(2))
            options.rietveld_url = match.group(1)

    try:
        changed_files = None
        # Always include os.getcwd() in the checkout settings.
        checkouts = []
        path = os.getcwd()

        file_list = []
        if options.files:
            file_list = options.files
        elif change:
            file_list = [f.LocalPath() for f in change.AffectedFiles()]

        if options.upstream_branch:
            path += '@' + options.upstream_branch
            # Clear file list so that the correct list will be retrieved from the
            # upstream branch.
            file_list = []
        checkouts.append(GuessVCS(options, path, file_list))
        checkouts[0].AutomagicalSettings()
        for item in options.sub_rep:
            # Pass file_list=None because we don't know the sub repo's file list.
            checkout = GuessVCS(options,
                                os.path.join(checkouts[0].checkout_root, item),
                                None)
            if checkout.checkout_root in [c.checkout_root for c in checkouts]:
                parser.error('Specified the root %s two times.' %
                             checkout.checkout_root)
            checkouts.append(checkout)

        can_http = options.port and options.host
        can_svn = options.svn_repo
        # If there was no transport selected yet, now we must have enough data to
        # select one.
        if not options.send_patch and not (can_http or can_svn):
            parser.error('Please specify an access method.')

        # Convert options.diff into the content of the diff.
        if options.url:
            if options.files:
                parser.error(
                    'You cannot specify files and --url at the same time.')
            options.diff = urllib.urlopen(options.url).read()
        elif options.diff:
            if options.files:
                parser.error(
                    'You cannot specify files and --diff at the same time.')
            options.diff = gclient_utils.FileRead(options.diff, 'rb')
        elif options.issue and options.patchset is None:
            # Retrieve the patch from rietveld when the diff is not specified.
            # When patchset is specified, it's because it's done by gcl/git-try.
            if json is None:
                parser.error(
                    'json or simplejson library is missing, please install.')
            api_url = '%s/api/%d' % (options.rietveld_url, options.issue)
            logging.debug(api_url)
            contents = json.loads(urllib.urlopen(api_url).read())
            options.patchset = contents['patchsets'][-1]
            diff_url = (
                '%s/download/issue%d_%d.diff' %
                (options.rietveld_url, options.issue, options.patchset))
            diff = GetMungedDiff('', urllib.urlopen(diff_url).readlines())
            options.diff = ''.join(diff[0])
            changed_files = diff[1]
        else:
            # Use this as the base.
            root = checkouts[0].checkout_root
            diffs = []
            for checkout in checkouts:
                diff = checkout.GenerateDiff().splitlines(True)
                path_diff = gclient_utils.PathDifference(
                    root, checkout.checkout_root)
                # Munge it.
                diffs.extend(GetMungedDiff(path_diff, diff)[0])
            options.diff = ''.join(diffs)

        if not options.name:
            if options.issue:
                options.name = 'Issue %s' % options.issue
            else:
                options.name = 'Unnamed'
                print('Note: use --name NAME to change the try job name.')

        if not options.email:
            parser.error(
                'Using an anonymous checkout. Please use --email or set '
                'the TRYBOT_RESULTS_EMAIL_ADDRESS environment variable.')
        print('Results will be emailed to: ' + options.email)

        if not options.bot:
            # Get try slaves from PRESUBMIT.py files if not specified.
            # Even if the diff comes from options.url, use the local checkout for bot
            # selection.
            try:
                import presubmit_support
                root_presubmit = checkouts[0].ReadRootFile('PRESUBMIT.py')
                if not change:
                    if not changed_files:
                        changed_files = checkouts[0].file_tuples
                    change = presubmit_support.Change(
                        options.name, '', checkouts[0].checkout_root,
                        changed_files, options.issue, options.patchset,
                        options.email)
                options.bot = presubmit_support.DoGetTrySlaves(
                    change, checkouts[0].GetFileNames(),
                    checkouts[0].checkout_root, root_presubmit,
                    options.project, False, sys.stdout)
            except ImportError:
                pass
            # If no bot is specified, either the default pool will be selected or the
            # try server will refuse the job. Either case we don't need to interfere.

        # Send the patch.
        if options.send_patch:
            # If forced.
            options.send_patch(options)
            PrintSuccess(options)
            return 0
        try:
            if can_http:
                _SendChangeHTTP(options)
                PrintSuccess(options)
                return 0
        except NoTryServerAccess:
            if not can_svn:
                raise
        _SendChangeSVN(options)
        PrintSuccess(options)
        return 0
    except (InvalidScript, NoTryServerAccess), e:
        if swallow_exception:
            return 1
        print >> sys.stderr, e
        return 1