<commit_before># coding=utf-8
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

"""autobisectjs, for bisecting changeset regression windows. Supports Mercurial repositories and SpiderMonkey only.
"""

from optparse import OptionParser  # pylint: disable=deprecated-module
import os
from pathlib import Path
import re
import shutil
import subprocess
import sys
import tempfile
import time

from lithium.interestingness.utils import rel_or_abs_import

from . import known_broken_earliest_working as kbew
from ..js import build_options
from ..js import compile_shell
from ..js import inspect_shell
from ..util import hg_helpers
from ..util import s3cache
from ..util import sm_compile_helpers
from ..util import subprocesses as sps
from ..util.lock_dir import LockDir


def parseOpts():  # pylint: disable=invalid-name,missing-docstring,missing-return-doc,missing-return-type-doc
    # pylint: disable=too-many-branches,too-complex,too-many-statements
    usage = "Usage: %prog [options]"
    parser = OptionParser(usage)
    # http://docs.python.org/library/optparse.html#optparse.OptionParser.disable_interspersed_args
    parser.disable_interspersed_args()

    parser.set_defaults(
        resetRepoFirst=False,
        startRepo=None,
        endRepo="default",
        testInitialRevs=True,
        output="",
        watchExitCode=None,
        useInterestingnessTests=False,
        parameters="-e 42",  # http://en.wikipedia.org/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy
        compilationFailedLabel="skip",
        build_options="",
        useTreeherderBinaries=False,
        nameOfTreeherderBranch="mozilla-inbound",
    )

    # Specify how the shell will be built.
    parser.add_option("-b", "--build",
                      dest="build_options",
                      help=('Specify js shell build options, e.g. -b "--enable-debug --32"'
                            "(python3 -m funfuzz.js.build_options --help)"))

    parser.add_option("--resetToTipFirst", dest="resetRepoFirst",
                      action="store_true",
                      help="First reset to default tip overwriting all local changes. "
                           'Equivalent to first executing `hg update -C default`. Defaults to "%default".')

    # Specify the revisions between which to bisect.
    parser.add_option("-s", "--startRev", dest="startRepo",
                      help='Earliest changeset/build numeric ID to consider (usually a "good" cset). '
                           "Defaults to the earliest revision known to work at all/available.")
    parser.add_option("-e", "--endRev", dest="endRepo",
                      help='Latest changeset/build numeric ID to consider (usually a "bad" cset). '
                           'Defaults to the head of the main branch, "default", or latest available build.')
    parser.add_option("-k", "--skipInitialRevs", dest="testInitialRevs",
                      action="store_false",
                      help="Skip testing the -s and -e revisions and automatically trust them as -g and -b.")

    # Specify the type of failure to look for.
    # (Optional -- by default, internalTestAndLabel will look for exit codes that indicate a crash or assert.)
    parser.add_option("-o", "--output", dest="output",
                      help='Stdout or stderr output to be observed. Defaults to "%default". '
                           'For assertions, set to "ssertion fail"')
    parser.add_option("-w", "--watchExitCode", dest="watchExitCode",
                      type="int",
                      help='Look out for a specific exit code. Only this exit code will be considered "bad".')
    parser.add_option("-i", "--useInterestingnessTests",
                      dest="useInterestingnessTests",
                      action="store_true",
                      help="Interpret the final arguments as an interestingness test.")

    # Specify parameters for the js shell.
    parser.add_option("-p", "--parameters", dest="parameters",
                      help='Specify parameters for the js shell, e.g. -p "-a --ion-eager testcase.js".')

    # Specify how to treat revisions that fail to compile.
    # (You might want to add these to kbew.knownBrokenRanges in known_broken_earliest_working.)
    parser.add_option("-l", "--compilationFailedLabel", dest="compilationFailedLabel",
                      help="Specify how to treat revisions that fail to compile. "
                           '(bad, good, or skip) Defaults to "%default"')

    parser.add_option("-T", "--useTreeherderBinaries",
                      dest="useTreeherderBinaries",
                      action="store_true",
                      help="Use treeherder binaries for quick bisection, assuming a fast "
                           'internet connection. Defaults to "%default"')
    parser.add_option("-N", "--nameOfTreeherderBranch",
                      dest="nameOfTreeherderBranch",
                      help='Name of the branch to download. Defaults to "%default"')

    (options, args) = parser.parse_args()
    if options.useTreeherderBinaries:
        print("TBD: Bisection using downloaded shells is temporarily not supported.", flush=True)
        sys.exit(0)

    options.build_options = build_options.parse_shell_opts(options.build_options)
    options.skipRevs = " + ".join(kbew.known_broken_ranges(options.build_options))

    options.runtime_params = [x for x in options.parameters.split(" ") if x]

    # First check that the testcase is present.
    if "-e 42" not in options.parameters and not Path(options.runtime_params[-1]).expanduser().is_file():
        print(flush=True)
        print(f'List of parameters to be passed to the shell is: {" ".join(options.runtime_params)}', flush=True)
        print(flush=True)
        raise OSError(f"Testcase at {options.runtime_params[-1]} is not present.")

    assert options.compilationFailedLabel in ("bad", "good", "skip")

    extraFlags = []  # pylint: disable=invalid-name

    if options.useInterestingnessTests:
        if len(args) < 1:
            print(f"args are: {args}", flush=True)
            parser.error("Not enough arguments.")
        for a in args:  # pylint: disable=invalid-name
            if a.startswith("--flags="):
                extraFlags = a[8:].split(" ")  # pylint: disable=invalid-name
        options.testAndLabel = externalTestAndLabel(options, args)
    elif len(args) >= 1:
        parser.error("Too many arguments.")
    else:
        options.testAndLabel = internalTestAndLabel(options)

    earliestKnownQuery = kbew.earliest_known_working_rev(  # pylint: disable=invalid-name
        options.build_options, options.runtime_params + extraFlags, options.skipRevs)

    earliestKnown = ""  # pylint: disable=invalid-name

    if not options.useTreeherderBinaries:<commit_msg>Fix pylint 2.x.x len-as-condition error.<commit_after># coding=utf-8
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

"""autobisectjs, for bisecting changeset regression windows. Supports Mercurial repositories and SpiderMonkey only.
"""

from optparse import OptionParser  # pylint: disable=deprecated-module
import os
from pathlib import Path
import re
import shutil
import subprocess
import sys
import tempfile
import time

from lithium.interestingness.utils import rel_or_abs_import

from . import known_broken_earliest_working as kbew
from ..js import build_options
from ..js import compile_shell
from ..js import inspect_shell
from ..util import hg_helpers
from ..util import s3cache
from ..util import sm_compile_helpers
from ..util import subprocesses as sps
from ..util.lock_dir import LockDir


def parseOpts():  # pylint: disable=invalid-name,missing-docstring,missing-return-doc,missing-return-type-doc
    # pylint: disable=too-many-branches,too-complex,too-many-statements
    usage = "Usage: %prog [options]"
    parser = OptionParser(usage)
    # http://docs.python.org/library/optparse.html#optparse.OptionParser.disable_interspersed_args
    parser.disable_interspersed_args()

    parser.set_defaults(
        resetRepoFirst=False,
        startRepo=None,
        endRepo="default",
        testInitialRevs=True,
        output="",
        watchExitCode=None,
        useInterestingnessTests=False,
        parameters="-e 42",  # http://en.wikipedia.org/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy
        compilationFailedLabel="skip",
        build_options="",
        useTreeherderBinaries=False,
        nameOfTreeherderBranch="mozilla-inbound",
    )

    # Specify how the shell will be built.
    parser.add_option("-b", "--build",
                      dest="build_options",
                      help=('Specify js shell build options, e.g. -b "--enable-debug --32"'
                            "(python3 -m funfuzz.js.build_options --help)"))

    parser.add_option("--resetToTipFirst", dest="resetRepoFirst",
                      action="store_true",
                      help="First reset to default tip overwriting all local changes. "
                           'Equivalent to first executing `hg update -C default`. Defaults to "%default".')

    # Specify the revisions between which to bisect.
    parser.add_option("-s", "--startRev", dest="startRepo",
                      help='Earliest changeset/build numeric ID to consider (usually a "good" cset). '
                           "Defaults to the earliest revision known to work at all/available.")
    parser.add_option("-e", "--endRev", dest="endRepo",
                      help='Latest changeset/build numeric ID to consider (usually a "bad" cset). '
                           'Defaults to the head of the main branch, "default", or latest available build.')
    parser.add_option("-k", "--skipInitialRevs", dest="testInitialRevs",
                      action="store_false",
                      help="Skip testing the -s and -e revisions and automatically trust them as -g and -b.")

    # Specify the type of failure to look for.
    # (Optional -- by default, internalTestAndLabel will look for exit codes that indicate a crash or assert.)
    parser.add_option("-o", "--output", dest="output",
                      help='Stdout or stderr output to be observed. Defaults to "%default". '
                           'For assertions, set to "ssertion fail"')
    parser.add_option("-w", "--watchExitCode", dest="watchExitCode",
                      type="int",
                      help='Look out for a specific exit code. Only this exit code will be considered "bad".')
    parser.add_option("-i", "--useInterestingnessTests",
                      dest="useInterestingnessTests",
                      action="store_true",
                      help="Interpret the final arguments as an interestingness test.")

    # Specify parameters for the js shell.
    parser.add_option("-p", "--parameters", dest="parameters",
                      help='Specify parameters for the js shell, e.g. -p "-a --ion-eager testcase.js".')

    # Specify how to treat revisions that fail to compile.
    # (You might want to add these to kbew.knownBrokenRanges in known_broken_earliest_working.)
    parser.add_option("-l", "--compilationFailedLabel", dest="compilationFailedLabel",
                      help="Specify how to treat revisions that fail to compile. "
                           '(bad, good, or skip) Defaults to "%default"')

    parser.add_option("-T", "--useTreeherderBinaries",
                      dest="useTreeherderBinaries",
                      action="store_true",
                      help="Use treeherder binaries for quick bisection, assuming a fast "
                           'internet connection. Defaults to "%default"')
    parser.add_option("-N", "--nameOfTreeherderBranch",
                      dest="nameOfTreeherderBranch",
                      help='Name of the branch to download. Defaults to "%default"')

    (options, args) = parser.parse_args()
    if options.useTreeherderBinaries:
        print("TBD: Bisection using downloaded shells is temporarily not supported.", flush=True)
        sys.exit(0)

    options.build_options = build_options.parse_shell_opts(options.build_options)
    options.skipRevs = " + ".join(kbew.known_broken_ranges(options.build_options))

    options.runtime_params = [x for x in options.parameters.split(" ") if x]

    # First check that the testcase is present.
    if "-e 42" not in options.parameters and not Path(options.runtime_params[-1]).expanduser().is_file():
        print(flush=True)
        print(f'List of parameters to be passed to the shell is: {" ".join(options.runtime_params)}', flush=True)
        print(flush=True)
        raise OSError(f"Testcase at {options.runtime_params[-1]} is not present.")

    assert options.compilationFailedLabel in ("bad", "good", "skip")

    extraFlags = []  # pylint: disable=invalid-name

    if options.useInterestingnessTests:
        if not args:
            print(f"args are: {args}", flush=True)
            parser.error("Not enough arguments.")
        for a in args:  # pylint: disable=invalid-name
            if a.startswith("--flags="):
                extraFlags = a[8:].split(" ")  # pylint: disable=invalid-name
        options.testAndLabel = externalTestAndLabel(options, args)
    elif args:
        parser.error("Too many arguments.")
    else:
        options.testAndLabel = internalTestAndLabel(options)

    earliestKnownQuery = kbew.earliest_known_working_rev(  # pylint: disable=invalid-name
        options.build_options, options.runtime_params + extraFlags, options.skipRevs)

    earliestKnown = ""  # pylint: disable=invalid-name

    if not options.useTreeherderBinaries:
{'fraction_non_alphanumeric': 0.10640436530729466, 'fraction_numerical': 0.0029437105112004596, 'mean_word_length': 2.635865309318716, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6706850', 'n_tokens_mistral': 3927, 'n_tokens_neox': 3774, 'n_words': 1102}