Ejemplo n.º 1
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('input',
                        type=str,
                        nargs='*',
                        metavar='file/folder',
                        default=os.path.join(util.get_default_workspace(),
                                             'reports'),
                        help="The analysis result files and/or folders "
                             "containing analysis results which should be "
                             "parsed and printed.")

    parser.add_argument('-t', '--type', '--input-format',
                        dest="input_format",
                        required=False,
                        choices=['plist'],
                        default='plist',
                        help="Specify the format the analysis results were "
                             "created as.")

    parser.add_argument('--suppress',
                        type=str,
                        dest="suppress",
                        default=argparse.SUPPRESS,
                        required=False,
                        help="Path of the suppress file to use. Records in "
                             "the suppress file are used to suppress the "
                             "display of certain results when parsing the "
                             "analyses' report. (Reports to an analysis "
                             "result can also be suppressed in the source "
                             "code -- please consult the manual on how to "
                             "do so.) NOTE: The suppress file relies on the "
                             "\"bug identifier\" generated by the analyzers "
                             "which is experimental, take care when relying "
                             "on it.")

    parser.add_argument('--export-source-suppress',
                        dest="create_suppress",
                        action="store_true",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Write suppress data from the suppression "
                             "annotations found in the source files that were "
                             "analyzed earlier that created the results. "
                             "The suppression information will be written "
                             "to the parameter of '--suppress'.")

    parser.add_argument('--print-steps',
                        dest="print_steps",
                        action="store_true",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Print the steps the analyzers took in finding "
                             "the reported defect.")

    add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 2
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('--all',
                        dest="all",
                        action='store_true',
                        default=argparse.SUPPRESS,
                        required=False,
                        help="Show all supported analyzers, not just the "
                        "available ones.")

    parser.add_argument('--details',
                        dest="details",
                        action='store_true',
                        default=argparse.SUPPRESS,
                        required=False,
                        help="Show details about the analyzers, not just "
                        "their names.")

    parser.add_argument('-o',
                        '--output',
                        dest='output_format',
                        required=False,
                        default='rows',
                        choices=output_formatters.USER_FORMATS,
                        help="Specify the format of the output list.")

    logger.add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 3
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('--analyzers',
                        nargs='+',
                        dest='analyzers',
                        metavar='ANALYZER',
                        required=False,
                        choices=analyzer_types.supported_analyzers,
                        default=argparse.SUPPRESS,
                        help="Show checkers only from the analyzers "
                        "specified.")

    parser.add_argument('--details',
                        dest='details',
                        default=argparse.SUPPRESS,
                        action='store_true',
                        required=False,
                        help="Show details about the checker, such as "
                        "description, if available.")

    parser.add_argument('--profile',
                        dest='profile',
                        metavar='PROFILE/list',
                        required=False,
                        default=argparse.SUPPRESS,
                        help="List checkers enabled by the selected profile. "
                        "'list' is a special option showing details "
                        "about profiles collectively.")

    filters = parser.add_mutually_exclusive_group(required=False)

    filters.add_argument('--only-enabled',
                         dest='only_enabled',
                         default=argparse.SUPPRESS,
                         action='store_true',
                         help="Show only the enabled checkers.")

    filters.add_argument('--only-disabled',
                         dest='only_disabled',
                         default=argparse.SUPPRESS,
                         action='store_true',
                         help="Show only the disabled checkers.")

    parser.add_argument('-o',
                        '--output',
                        dest='output_format',
                        required=False,
                        default='rows',
                        choices=output_formatters.USER_FORMATS,
                        help="The format to list the applicable checkers as.")

    logger.add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 4
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    context = generic_package_context.get_context()
    working, _ = analyzer_types.check_supported_analyzers(
        analyzer_types.supported_analyzers, context)

    parser.add_argument('--all',
                        dest="all",
                        action='store_true',
                        default=argparse.SUPPRESS,
                        required=False,
                        help="Show all supported analyzers, not just the "
                        "available ones.")

    parser.add_argument('--details',
                        dest="details",
                        action='store_true',
                        default=argparse.SUPPRESS,
                        required=False,
                        help="Show details about the analyzers, not just "
                        "their names.")

    parser.add_argument('--dump-config',
                        dest='dump_config',
                        required=False,
                        choices=list(working),
                        help="Dump the available checker options for the "
                        "given analyzer to the standard output. "
                        "Currently only clang-tidy supports this option. "
                        "The output can be redirected to a file named "
                        ".clang-tidy. If this file is placed to the "
                        "project directory then the options are applied "
                        "to the files under that directory. This config "
                        "file can also be provided via "
                        "'CodeChecker analyze' and 'CodeChecker check' "
                        "commands.")

    parser.add_argument('-o',
                        '--output',
                        dest='output_format',
                        required=False,
                        default='rows',
                        choices=output_formatters.USER_FORMATS,
                        help="Specify the format of the output list.")

    logger.add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 5
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('-o', '--output',
                        dest='output_format',
                        required=False,
                        default='table',
                        choices=output_formatters.USER_FORMATS,
                        help="The format to use when printing the version.")

    logger.add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 6
0
def __add_common_arguments(parser,
                           needs_product_url=True,
                           has_matrix_output=False):
    """
    Add some common arguments, like server address and verbosity, to parser.
    """

    common_group = parser.add_argument_group('common arguments')

    if needs_product_url is None:
        # Explicitly not add anything, the command does not connect to a
        # server.
        pass
    elif needs_product_url:
        # Command connects to a product on a server.
        common_group.add_argument('--url',
                                  type=str,
                                  metavar='PRODUCT_URL',
                                  dest="product_url",
                                  default="localhost:8001/Default",
                                  required=False,
                                  help="The URL of the product which will be "
                                  "accessed by the client, in the "
                                  "format of"
                                  " '[http[s]://]host:port/Endpoint'.")
    else:
        # Command connects to a server directly.
        common_group.add_argument('--url',
                                  type=str,
                                  metavar='SERVER_URL',
                                  dest="server_url",
                                  default="localhost:8001",
                                  required=False,
                                  help="The URL of the server to access, "
                                  "in the format of"
                                  " '[http[s]://]host:port'.")

    if has_matrix_output:
        common_group.add_argument(
            '-o',
            '--output',
            dest="output_format",
            required=False,
            # TODO: 'plaintext' only kept for legacy.
            default="plaintext",
            choices=["plaintext"] + output_formatters.USER_FORMATS,
            help="The output format to use in showing "
            "the data.")

    add_verbose_arguments(common_group)
Ejemplo n.º 7
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('-o',
                        '--output',
                        type=str,
                        dest="logfile",
                        default=argparse.SUPPRESS,
                        required=True,
                        help="Path of the file to write the collected "
                        "compilation commands to. If the file already "
                        "exists, it will be overwritten.")

    parser.add_argument('-b',
                        '--build',
                        type=str,
                        dest="command",
                        default=argparse.SUPPRESS,
                        required=True,
                        help="The build command to execute. Build commands "
                        "can be simple calls to 'g++' or 'clang++' or "
                        "'make', but a more complex command, or the call "
                        "of a custom script file is also supported.")

    parser.add_argument('-k',
                        '--keep-link',
                        dest="keep_link",
                        default=argparse.SUPPRESS,
                        action="store_true",
                        help="If this flag is given then the output log file "
                        "will contain the linking build actions too.")

    parser.add_argument('-q',
                        '--quiet',
                        dest="quiet",
                        action='store_true',
                        default=argparse.SUPPRESS,
                        required=False,
                        help="Do not print the output of the build tool into "
                        "the output of this command.")

    logger.add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 8
0
def __add_common_arguments(parser, has_matrix_output=False):
    """
    Add some common arguments, like server address and verbosity, to parser.
    """

    common_group = parser.add_argument_group('common arguments')

    common_group.add_argument('--host',
                              type=str,
                              dest="host",
                              default="localhost",
                              required=False,
                              help="The address of the CodeChecker viewer "
                              "server to connect to.")

    common_group.add_argument('-p',
                              '--port',
                              type=int,
                              dest="port",
                              default=8001,
                              required=False,
                              help="The port the server is running on.")

    if has_matrix_output:
        common_group.add_argument(
            '-o',
            '--output',
            dest="output_format",
            required=False,
            # TODO: 'plaintext' only kept for legacy.
            default="plaintext",
            choices=["plaintext"] + output_formatters.USER_FORMATS,
            help="The output format to use in showing "
            "the data.")

    add_verbose_arguments(common_group)
Ejemplo n.º 9
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('input',
                        type=str,
                        nargs='*',
                        metavar='file/folder',
                        default=os.path.join(util.get_default_workspace(),
                                             'reports'),
                        help="The analysis result files and/or folders "
                        "containing analysis results which should be "
                        "parsed and printed.")

    parser.add_argument('-t',
                        '--type',
                        '--input-format',
                        dest="input_format",
                        required=False,
                        choices=['plist'],
                        default='plist',
                        help="Specify the format the analysis results were "
                        "created as.")

    parser.add_argument('-n',
                        '--name',
                        type=str,
                        dest="name",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="The name of the analysis run to use in storing "
                        "the reports to the database. If not specified, "
                        "the '--name' parameter given to 'codechecker-"
                        "analyze' will be used, if exists.")

    parser.add_argument('--tag',
                        type=str,
                        dest="tag",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="A uniques identifier for this individual store "
                        "of results in the run's history.")

    parser.add_argument('--trim-path-prefix',
                        type=str,
                        nargs='*',
                        dest="trim_path_prefix",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Removes leading path from files which will be "
                        "stored. So if you have /a/b/c/x.cpp and "
                        "/a/b/c/y.cpp then by removing \"/a/b/\" prefix "
                        "will store files like c/x.cpp and c/y.cpp. "
                        "If multiple prefix is given, the longest match "
                        "will be removed.")

    parser.add_argument('-f',
                        '--force',
                        dest="force",
                        default=argparse.SUPPRESS,
                        action='store_true',
                        required=False,
                        help="Delete analysis results stored in the database "
                        "for the current analysis run's name and store "
                        "only the results reported in the 'input' files. "
                        "(By default, CodeChecker would keep reports "
                        "that were coming from files not affected by the "
                        "analysis, and only incrementally update defect "
                        "reports for source files that were analysed.)")

    server_args = parser.add_argument_group(
        "server arguments",
        "Specifies a 'CodeChecker server' instance which will be used to "
        "store the results. This server must be running and listening, and "
        "the given product must exist prior to the 'store' command being ran.")

    server_args.add_argument('--url',
                             type=str,
                             metavar='PRODUCT_URL',
                             dest="product_url",
                             default="localhost:8001/Default",
                             required=False,
                             help="The URL of the product to store the "
                             "results for, in the format of "
                             "'[http[s]://]host:port/Endpoint'.")

    logger.add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 10
0
def main(subcommands=None):
    """
    CodeChecker main command line.
    """

    def signal_handler(sig, frame):
        """
        Without this handler the PostgreSQL
        server does not terminate at signal.
        """
        sys.exit(1)

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    try:
        parser = argparse.ArgumentParser(
            prog='CodeChecker',
            formatter_class=argparse.RawDescriptionHelpFormatter,
            description='''
Run the CodeChecker source analyzer framework.
See the subcommands for specific features.''',
            epilog='''
Example usage:
--------------
Analyzing a project with default settings:
CodeChecker check -b "cd ~/myproject && make" -n myproject

Start the viewer to see the results:
CodeChecker server

See the results in a web browser: localhost:8001
See results in  the command line: CodeChecker cmd results -p 8001 -n myproject

To analyze a small project quickcheck feature can be used.
The results will be printed only to the standard output.
(No database will be used)

CodeChecker quickcheck -b "cd ~/myproject && make"
''')

        subparsers = parser.add_subparsers(help='commands')

        # TODO: Delete these once a later version rolls.
        old_subcommands = []

        def _warn_deprecated_command(cmd_name):
            # Write to stderr so the output is not captured by pipes, e.g.
            # with the "checkers" command, the "-" in the new command's name
            # would mess up pipe usage.
            err_msg = "[WARNING] The called command 'CodeChecker {0}' is " \
                      "DEPRECATED since version A.B. A new version is "    \
                      "available as 'codechecker-{0}'.\nThe DEPRECATED "   \
                      "command will be REPLACED when version X.Y is "      \
                      "released.\nPlease see 'codechecker-{0} --help' on " \
                      "details how to run the new version.\n".format(cmd_name)

            # This warning is implemented for showing later on, once old
            # behaviour commands are deprecated. We don't warn between 5.8 and
            # 6.0 for now.
            # sys.stderr.write(err_msg)

        workspace_help_msg = 'Directory where the CodeChecker can' \
            ' store analysis related data.'

        # --------------------------------------
        # Checkers parser.
        checker_p = subparsers.add_parser('checkers',
                                          formatter_class=ADHF,
                                          help='List the available checkers '
                                               'for the supported analyzers '
                                               'and show their default status '
                                               '(+ for being enabled, '
                                               '- for being disabled by '
                                               'default).')
        old_subcommands.append('checkers')

        checker_p.add_argument('--analyzers', nargs='+',
                               dest="analyzers", required=False,
                               help='Select which analyzer checkers '
                               'should be listed.\nCurrently supported '
                               'analyzers:\n' + analyzers)

        logger.add_verbose_arguments(checker_p)
        checker_p.set_defaults(func=arg_handler.handle_list_checkers)

        # --------------------------------------
        # Server.
        server_parser = subparsers.add_parser('server',
                                              formatter_class=ADHF,
                                              help='Start and manage the '
                                                   'CodeChecker web server.')
        old_subcommands.append('server')

        server_parser.add_argument('-w', '--workspace', type=str,
                                   dest="workspace",
                                   default=util.get_default_workspace(),
                                   help=workspace_help_msg)

        server_parser.add_argument('-l', '--list',
                                   action='store_true',
                                   dest="list",
                                   required=False,
                                   help='List servers started by your user.')

        server_parser.add_argument('-s', '--stop',
                                   action='store_true',
                                   dest="stop",
                                   required=False,
                                   help='Stops the server associated with '
                                        'the given view-port and workspace.')

        server_parser.add_argument('--stop-all',
                                   action='store_true',
                                   dest="stop_all",
                                   required=False,
                                   help='Stops all of your running '
                                        'CodeChecker instances.')

        server_parser.add_argument('-v', '--view-port', type=int,
                                   dest="view_port",
                                   default=8001, required=False,
                                   help='Port used for viewing.')

        server_parser.add_argument('-u', '--suppress', type=str,
                                   dest="suppress",
                                   required=False,
                                   help='Path to suppress file.')

        server_parser.add_argument('--not-host-only', action="store_true",
                                   dest="not_host_only",
                                   help='Viewing the results is possible not '
                                        'only by browsers or clients '
                                        'started locally.')

        server_parser.add_argument('--check-port', type=int, dest="check_port",
                                   default=None, required=False,
                                   help='Port used for checking.')

        server_parser.add_argument('--check-address', type=str,
                                   dest="check_address", default="localhost",
                                   required=False, help='Server address.')

        add_database_arguments(server_parser)
        logger.add_verbose_arguments(server_parser)
        server_parser.set_defaults(func=arg_handler.handle_server)

        # --------------------------------------
        # Cmd_line.
        cmd_line_parser = subparsers.add_parser('cmd',
                                                help='Command line client')
        old_subcommands.append('cmd')
        cmd_line_client.register_client_command_line(cmd_line_parser)

        # --------------------------------------
        # Debug parser.
        debug_parser = subparsers.add_parser('debug',
                                             formatter_class=ADHF,
                                             help='Generate gdb debug dump '
                                                  'files for all the failed '
                                                  'compilation commands in '
                                                  'the last analyzer run.\n'
                                                  'Requires a database with '
                                                  'the failed compilation '
                                                  'commands.')
        old_subcommands.append('debug')

        debug_parser.add_argument('-w', '--workspace', type=str,
                                  dest="workspace",
                                  default=util.get_default_workspace(),
                                  help=workspace_help_msg)

        debug_parser.add_argument('-f', '--force', action="store_true",
                                  dest="force", required=False, default=False,
                                  help='Overwrite already generated files.')

        add_database_arguments(debug_parser)
        logger.add_verbose_arguments(debug_parser)
        debug_parser.set_defaults(func=arg_handler.handle_debug)

        if subcommands:
            # Load the 'libcodechecker' module and acquire its path.
            file, path, descr = imp.find_module("libcodechecker")
            libcc_path = imp.load_module("libcodechecker",
                                         file, path, descr).__path__[0]

            # Try to check if the user has already given us a subcommand to
            # execute. If so, don't load every available parts of CodeChecker
            # to ensure a more optimised run.
            if len(sys.argv) > 1:
                first_command = sys.argv[1]
                if first_command in subcommands:
                    LOG.debug("Supplied an existing, valid subcommand: " +
                              first_command)

                    if 'CC_FROM_LEGACY_INVOKE' not in os.environ:
                        # Consider only the given command as an available one.
                        subcommands = [first_command]
                    else:
                        if first_command in old_subcommands:
                            # Certain commands as of now have a 'new' and an
                            # 'old' invocation and execution. In case of an
                            # 'old' invocation is passed ('CodeChecker
                            # command'), do NOT load the 'new' argument parser
                            # and executed method.
                            #
                            # TODO: Delete this once the new commands are
                            # fleshed out and old are deprecated later on.
                            _warn_deprecated_command(first_command)
                            subcommands = []

            for subcommand in subcommands:
                if 'CC_FROM_LEGACY_INVOKE' in os.environ and \
                        subcommand in old_subcommands:
                    # Make sure 'old' commands have a priority in the listing
                    # when '--help' is queried.
                    continue

                LOG.debug("Creating arg parser for subcommand " + subcommand)

                try:
                    # Even though command verbs and nouns are joined by a
                    # hyphen, the Python files contain underscores.
                    command_file = os.path.join(libcc_path,
                                                subcommand.replace('-', '_') +
                                                ".py")

                    # Load the module's source code, located under
                    # libcodechecker/sub_command.py.
                    # We can't use find_module() and load_module() here as both
                    # a file AND a package exists with the same name, and
                    # find_module() would find
                    # libcodechecker/sub_command/__init__.py first.
                    # Thus, manual source-code reading is required.
                    # NOTE: load_source() loads the compiled .pyc, if such
                    # exists.
                    command_module = imp.load_source(subcommand, command_file)

                    # Now that the module is loaded, construct an
                    # ArgumentParser for it.
                    sc_parser = subparsers.add_parser(
                        subcommand, **command_module.get_argparser_ctor_args())

                    command_module.add_arguments_to_parser(sc_parser)

                except (IOError, ImportError):
                    LOG.warning("Couldn't import module for subcommand '" +
                                subcommand + "'... ignoring.")
                    import traceback
                    traceback.print_exc(file=sys.stdout)

        args = parser.parse_args()
        if 'verbose' in args:
            LoggerFactory.set_log_level(args.verbose)
        args.func(args)

        if 'CC_FROM_LEGACY_INVOKE' in os.environ and \
                first_command and first_command in old_subcommands:
            _warn_deprecated_command(first_command)

    except KeyboardInterrupt as kb_err:
        LOG.info(str(kb_err))
        LOG.info("Interrupted by user...")
        sys.exit(1)

    except shared.ttypes.RequestFailed as thrift_ex:
        LOG.info("Server error.")
        LOG.info("Error code: " + str(thrift_ex.error_code))
        LOG.info("Error message: " + str(thrift_ex.message))
        sys.exit(1)

    # Handle all exception, but print stacktrace. It is needed for atexit.
    # atexit does not work correctly when an unhandled exception occurred.
    # So in this case, the servers left running when the script exited.
    except Exception:
        import traceback
        traceback.print_exc(file=sys.stdout)
        sys.exit(1)
Ejemplo n.º 11
0
def register_client_command_line(argument_parser):
    """ Should be used to extend the already existing arguments
    extend the argument parser with extra commands."""

    subparsers = argument_parser.add_subparsers()

    # List runs.
    listruns_parser = subparsers.add_parser('runs',
                                            formatter_class=ADHFormatter,
                                            help='Get the run data.')
    listruns_parser.add_argument('--host',
                                 type=str,
                                 dest="host",
                                 default='localhost',
                                 help='Server host.')
    listruns_parser.add_argument('-p',
                                 '--port',
                                 type=str,
                                 dest="port",
                                 default="8001",
                                 help='HTTP Server port.')
    listruns_parser.add_argument('-o',
                                 choices=['plaintext', 'json', 'csv'],
                                 default='plaintext',
                                 type=str,
                                 dest="output_format",
                                 help='Output format.')
    logger.add_verbose_arguments(listruns_parser)
    listruns_parser.set_defaults(func=handle_list_runs)

    # List results.
    listresults_parser = subparsers.add_parser('results',
                                               formatter_class=ADHFormatter,
                                               help='List results.')
    listresults_parser.add_argument('--host',
                                    type=str,
                                    dest="host",
                                    default='localhost',
                                    help='Server host.')
    listresults_parser.add_argument('-p',
                                    '--port',
                                    type=str,
                                    dest="port",
                                    default="8001",
                                    help='HTTP Server port.')
    listresults_parser.add_argument('-n',
                                    '--name',
                                    type=str,
                                    dest="name",
                                    required=True,
                                    help='Check name.')
    listresults_parser.add_argument('-s',
                                    '--suppressed',
                                    action="store_true",
                                    dest="suppressed",
                                    help='Suppressed results.')
    listresults_parser.add_argument('--filter',
                                    dest='filter',
                                    type=str,
                                    default='::',
                                    help='Filter string in the '
                                    'following format: '
                                    '<severity>:<checker_name>:<file_path>')
    listresults_parser.add_argument('-o',
                                    choices=['plaintext', 'json', 'csv'],
                                    default='plaintext',
                                    type=str,
                                    dest="output_format",
                                    help='Output format.')
    logger.add_verbose_arguments(listresults_parser)
    listresults_parser.set_defaults(func=handle_list_results)

    # List diffs.
    diff_parser = subparsers.add_parser('diff',
                                        formatter_class=ADHFormatter,
                                        help='Diff two run.')
    diff_parser.add_argument('--host',
                             type=str,
                             dest="host",
                             default='localhost',
                             help='Server host.')
    diff_parser.add_argument('-p',
                             '--port',
                             type=str,
                             dest="port",
                             default="8001",
                             help='HTTP Server port.')
    diff_parser.add_argument('-b',
                             '--basename',
                             type=str,
                             dest="basename",
                             required=True,
                             help='Base name.')
    diff_parser.add_argument('-n',
                             '--newname',
                             type=str,
                             dest="newname",
                             required=True,
                             help='New name.')
    diff_parser.add_argument('-s',
                             '--suppressed',
                             action="store_true",
                             dest="suppressed",
                             default=False,
                             required=False,
                             help='Show suppressed bugs.')
    diff_parser.add_argument('-o',
                             choices=['plaintext', 'json', 'csv'],
                             default='plaintext',
                             type=str,
                             dest="output_format",
                             help='Output format.')
    diff_parser.add_argument('--filter',
                             dest='filter',
                             type=str,
                             default='::',
                             help='Filter string in the '
                             'following format: '
                             '<severity>:<checker_name>:<file_path>')
    group = diff_parser.add_mutually_exclusive_group(required=True)
    group.add_argument('--new',
                       action="store_true",
                       dest="new",
                       help="Show new results.")
    group.add_argument('--unresolved',
                       action="store_true",
                       dest="unresolved",
                       help="Show unresolved results.")
    group.add_argument('--resolved',
                       action="store_true",
                       dest="resolved",
                       help="Show resolved results.")
    logger.add_verbose_arguments(diff_parser)
    diff_parser.set_defaults(func=handle_diff_results)

    # List resulttypes.
    sum_parser = subparsers.add_parser('sum',
                                       formatter_class=ADHFormatter,
                                       help='Sum results.')
    sum_parser.add_argument('--host',
                            type=str,
                            dest="host",
                            default='localhost',
                            help='Server host.')
    sum_parser.add_argument('-p',
                            '--port',
                            type=str,
                            dest="port",
                            default="8001",
                            help='HTTP Server port.')
    name_group = sum_parser.add_mutually_exclusive_group(required=True)
    name_group.add_argument('-n',
                            '--name',
                            nargs='+',
                            type=str,
                            dest="names",
                            help='Check name.')
    name_group.add_argument('-a',
                            '--all',
                            action='store_true',
                            dest="all_results",
                            help='All results.')

    sum_parser.add_argument('-s',
                            '--suppressed',
                            action="store_true",
                            dest="suppressed",
                            help='Suppressed results.')
    sum_parser.add_argument('--filter',
                            dest='filter',
                            type=str,
                            default='::',
                            help='Filter string in the '
                            'following format: '
                            '<severity>:<checker_name>:<source_file_path>')
    sum_parser.add_argument('-o',
                            choices=['plaintext', 'json', 'csv'],
                            default='plaintext',
                            type=str,
                            dest="output_format",
                            help='Output format.')
    logger.add_verbose_arguments(sum_parser)
    sum_parser.set_defaults(func=handle_list_result_types)

    # Delete run results.
    del_parser = subparsers.add_parser('del',
                                       formatter_class=ADHFormatter,
                                       help='Remove run results.')
    del_parser.add_argument('--host',
                            type=str,
                            dest="host",
                            default='localhost',
                            help='Server host.')
    del_parser.add_argument('-p',
                            '--port',
                            type=str,
                            dest="port",
                            default=8001,
                            required=True,
                            help='HTTP Server port.')
    group = del_parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-n',
                       '--name',
                       nargs='+',
                       type=str,
                       dest="name",
                       help='Server port.')
    group.add_argument('--all-after-run',
                       type=str,
                       dest='all_after_run',
                       help='Delete all runs checked after this run.')
    group.add_argument('--all-before-run',
                       type=str,
                       dest='all_before_run',
                       help='Delete all runs checked before this run.')
    group.add_argument('--all-after-time',
                       type=valid_time,
                       dest='all_after_time',
                       help='Delete all runs checked after this timestamp. '
                       'The format should be min:hour:day:month:year.')
    group.add_argument('--all-before-time',
                       type=valid_time,
                       dest='all_before_time',
                       help='Delete all runs checked before this timestamp. '
                       'The format should be min:hour:day:month:year.')
    logger.add_verbose_arguments(del_parser)
    del_parser.set_defaults(func=handle_remove_run_results)

    # Handle authentication.
    auth_parser = subparsers.add_parser('login',
                                        formatter_class=ADHFormatter,
                                        help='Log in onto a '
                                        'CodeChecker server.')
    auth_parser.add_argument('--host',
                             type=str,
                             dest="host",
                             default='localhost',
                             help='Server host.')
    auth_parser.add_argument('-p',
                             '--port',
                             type=str,
                             dest="port",
                             default="8001",
                             help='HTTP Server port.')
    auth_parser.add_argument('-u',
                             '--username',
                             type=str,
                             dest="username",
                             required=False,
                             help='Username to use on authentication.',
                             default=getpass.getuser())
    auth_parser.add_argument('-d',
                             '--deactivate',
                             '--logout',
                             action='store_true',
                             dest='logout',
                             help='Send a logout request for the server.')
    logger.add_verbose_arguments(auth_parser)
    auth_parser.set_defaults(func=handle_auth_requests)
Ejemplo n.º 12
0
def __add_common_arguments(parser,
                           needs_product_url=True,
                           has_matrix_output=False):
    """
    Add some common arguments, like server address and verbosity, to parser.
    """

    common_group = parser.add_argument_group('common arguments')

    if needs_product_url is None:
        # Explicitly not add anything, the command does not connect to a
        # server.
        pass
    elif needs_product_url:
        # Command connects to a product on a server.
        common_group.add_argument('--url',
                                  type=str,
                                  metavar='PRODUCT_URL',
                                  dest="product_url",
                                  default="localhost:8001/Default",
                                  required=False,
                                  help="The URL of the product which will be "
                                  "accessed by the client, in the "
                                  "format of"
                                  " '[http[s]://]host:port/Endpoint'.")
    else:
        # Command connects to a server directly.
        common_group.add_argument('--url',
                                  type=str,
                                  metavar='SERVER_URL',
                                  dest="server_url",
                                  default="localhost:8001",
                                  required=False,
                                  help="The URL of the server to access, "
                                  "in the format of"
                                  " '[http[s]://]host:port'.")

    if has_matrix_output:
        common_group.add_argument(
            '-o',
            '--output',
            dest="output_format",
            required=False,
            # TODO: 'plaintext' only kept for legacy.
            default="plaintext",
            choices=["plaintext", "html"] + output_formatters.USER_FORMATS,
            help="The output format to use in showing "
            "the data.")

        common_group.add_argument('-e',
                                  '--export-dir',
                                  dest="export_dir",
                                  default=argparse.SUPPRESS,
                                  help="Store the output in the given folder.")

        common_group.add_argument('-c',
                                  '--clean',
                                  dest="clean",
                                  required=False,
                                  action='store_true',
                                  default=argparse.SUPPRESS,
                                  help="Delete output results stored in the "
                                  "output directory. (By default, it "
                                  "would keep output files and "
                                  "overwrites only those that contain "
                                  "any reports).")

    logger.add_verbose_arguments(common_group)
Ejemplo n.º 13
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    # TODO: --workspace is an outdated concept in 'store'. Later on,
    # it shall be deprecated, as changes to db_handler commence.
    parser.add_argument('-w', '--workspace',
                        type=str,
                        dest="workspace",
                        default=util.get_default_workspace(),
                        required=False,
                        help="Directory where CodeChecker can store analysis "
                             "result related data, such as the database. "
                             "(Cannot be specified at the same time with "
                             "'--sqlite' or '--config-directory'.)")

    parser.add_argument('-f', '--config-directory',
                        type=str,
                        dest="config_directory",
                        default=util.get_default_workspace(),
                        required=False,
                        help="Directory where CodeChecker server should read "
                             "server-specific configuration (such as "
                             "authentication settings, SSL certificate"
                             " (cert.pem) and key (key.pem)) from.")

    parser.add_argument('--host',
                        type=str,
                        dest="listen_address",
                        default="localhost",
                        required=False,
                        help="The IP address or hostname of the server on "
                             "which it should listen for connections.")

    # TODO: -v/--view-port is too verbose. The server's -p/--port is used
    # symmetrically in 'CodeChecker cmd' anyways.
    parser.add_argument('-v', '--view-port',  # TODO: <- Deprecate and remove.
                        '-p', '--port',
                        type=int,
                        dest="view_port",
                        metavar='PORT',
                        default=8001,
                        required=False,
                        help="The port which will be used as listen port for "
                             "the server.")

    # TODO: This should be removed later on, in favour of --host.
    parser.add_argument('--not-host-only',
                        dest="not_host_only",
                        action="store_true",
                        required=False,
                        help="If specified, storing and viewing the results "
                             "will be possible not only by browsers and "
                             "clients running locally, but to everyone, who "
                             "can access the server over the Internet. "
                             "(Equivalent to specifying '--host \"\"'.)")

    parser.add_argument('--skip-db-cleanup',
                        dest="skip_db_cleanup",
                        action='store_true',
                        default=False,
                        required=False,
                        help="Skip performing cleanup jobs on the database "
                             "like removing unused files.")

    dbmodes = parser.add_argument_group("configuration database arguments")

    dbmodes = dbmodes.add_mutually_exclusive_group(required=False)

    dbmodes.add_argument('--sqlite',
                         type=str,
                         dest="sqlite",
                         metavar='SQLITE_FILE',
                         default=os.path.join(
                             '<CONFIG_DIRECTORY>',
                             "config.sqlite"),
                         required=False,
                         help="Path of the SQLite database file to use.")

    dbmodes.add_argument('--postgresql',
                         dest="postgresql",
                         action='store_true',
                         required=False,
                         default=argparse.SUPPRESS,
                         help="Specifies that a PostgreSQL database is to be "
                              "used instead of SQLite. See the \"PostgreSQL "
                              "arguments\" section on how to configure the "
                              "database connection.")

    pgsql = parser.add_argument_group("PostgreSQL arguments",
                                      "Values of these arguments are ignored, "
                                      "unless '--postgresql' is specified!")

    # TODO: --dbSOMETHING arguments are kept to not break interface from
    # old command. Database using commands such as "CodeChecker store" no
    # longer supports these --- it would be ideal to break and remove args
    # with this style and only keep --db-SOMETHING.
    pgsql.add_argument('--dbaddress', '--db-host',
                       type=str,
                       dest="dbaddress",
                       default="localhost",
                       required=False,
                       help="Database server address.")

    pgsql.add_argument('--dbport', '--db-port',
                       type=int,
                       dest="dbport",
                       default=5432,
                       required=False,
                       help="Database server port.")

    pgsql.add_argument('--dbusername', '--db-username',
                       type=str,
                       dest="dbusername",
                       default='codechecker',
                       required=False,
                       help="Username to use for connection.")

    pgsql.add_argument('--dbname', '--db-name',
                       type=str,
                       dest="dbname",
                       default="config",
                       required=False,
                       help="Name of the database to use.")

    root_account = parser.add_argument_group(
        "root account arguments",
        "Servers automatically create a root user to access the server's "
        "configuration via the clients. This user is created at first start "
        "and saved in the CONFIG_DIRECTORY, and the credentials are printed "
        "to the server's standard output. The plaintext credentials are "
        "NEVER accessible again.")

    root_account.add_argument('--reset-root',
                              dest="reset_root",
                              action='store_true',
                              default=argparse.SUPPRESS,
                              required=False,
                              help="Force the server to recreate the master "
                                   "superuser (root) account name and "
                                   "password. The previous credentials will "
                                   "be invalidated, and the new ones will be "
                                   "printed to the standard output.")

    root_account.add_argument('--force-authentication',
                              dest="force_auth",
                              action='store_true',
                              default=argparse.SUPPRESS,
                              required=False,
                              help="Force the server to run in "
                                   "authentication requiring mode, despite "
                                   "the configuration value in "
                                   "'server_config.json'. This is needed "
                                   "if you need to edit the product "
                                   "configuration of a server that would not "
                                   "require authentication otherwise.")

    instance_mgmnt = parser.add_argument_group("running server management")

    instance_mgmnt = instance_mgmnt. \
        add_mutually_exclusive_group(required=False)

    instance_mgmnt.add_argument('-l', '--list',
                                dest="list",
                                action='store_true',
                                default=argparse.SUPPRESS,
                                required=False,
                                help="List the servers that has been started "
                                     "by you.")

    instance_mgmnt.add_argument('-r', '--reload',
                                dest="reload",
                                action='store_true',
                                default=argparse.SUPPRESS,
                                required=False,
                                help="Sends the CodeChecker server process a "
                                     "SIGHUP signal, causing it to reread "
                                     "it's configuration files.")

    # TODO: '-s' was removed from 'quickcheck', it shouldn't be here either?
    instance_mgmnt.add_argument('-s', '--stop',
                                dest="stop",
                                action='store_true',
                                default=argparse.SUPPRESS,
                                required=False,
                                help="Stops the server associated with "
                                     "the given view-port and workspace.")

    instance_mgmnt.add_argument('--stop-all',
                                dest="stop_all",
                                action='store_true',
                                default=argparse.SUPPRESS,
                                required=False,
                                help="Stops all of your running CodeChecker "
                                     "server instances.")

    database_mgmnt = parser.add_argument_group(
            "Database management arguments.",
            """WARNING these commands needs to be called with the same
            workspace and configuration arguments as the server so the
            configuration database will be found which is required for the
            schema migration. Migration can be done without a running server
            but pay attention to use the same arguments which will be used to
            start the server.
            NOTE:
            Before migration it is advised to create a full a backup of
            the product databases.
            """)

    database_mgmnt = database_mgmnt. \
        add_mutually_exclusive_group(required=False)

    database_mgmnt.add_argument('--db-status',
                                type=str,
                                dest="status",
                                action='store',
                                default=argparse.SUPPRESS,
                                required=False,
                                help="Name of the product to get "
                                     "the database status for. "
                                     "Use 'all' to list the database "
                                     "statuses for all of the products.")

    database_mgmnt.add_argument('--db-upgrade-schema',
                                type=str,
                                dest='product_to_upgrade',
                                action='store',
                                default=argparse.SUPPRESS,
                                required=False,
                                help="Name of the product to upgrade to the "
                                     "latest database schema available in "
                                     "the package. Use 'all' to upgrade all "
                                     "of the products. "
                                     "NOTE: Before migration it is advised"
                                     " to create a full backup of "
                                     "the product databases.")

    database_mgmnt.add_argument('--db-force-upgrade',
                                dest='force_upgrade',
                                action='store_true',
                                default=argparse.SUPPRESS,
                                required=False,
                                help="Force the server to do database "
                                     "migration without user interaction. "
                                     "NOTE: Please use with caution and "
                                     "before automatic migration it is "
                                     "advised to create a full backup of the "
                                     "product databases.")

    logger.add_verbose_arguments(parser)

    def __handle(args):
        """Custom handler for 'server' so custom error messages can be
        printed without having to capture 'parser' in main."""

        def arg_match(options):
            return util.arg_match(options, sys.argv[1:])

        # See if there is a "PostgreSQL argument" specified in the invocation
        # without '--postgresql' being there. There is no way to distinguish
        # a default argument and a deliberately specified argument without
        # inspecting sys.argv.
        options = ['--dbaddress', '--dbport', '--dbusername', '--dbname',
                   '--db-host', '--db-port', '--db-username', '--db-name']
        psql_args_matching = arg_match(options)
        if any(psql_args_matching) and\
                'postgresql' not in args:
            first_matching_arg = next(iter([match for match
                                            in psql_args_matching]))
            parser.error("argument {0}: not allowed without "
                         "argument --postgresql".format(first_matching_arg))
            # parser.error() terminates with return code 2.

        # --not-host-only is a "shortcut", actually a to-be-deprecated
        # call which means '--host ""'.
        # TODO: Actually deprecate --not-host-only later on.
        options = ['--not-host-only', '--host']
        if set(arg_match(options)) == set(options):
            parser.error("argument --not-host-only: not allowed with "
                         "argument --host, as it is a shortcut to --host "
                         "\"\"")
        else:
            # Apply the shortcut.
            if len(arg_match(['--not-host-only'])) > 0:
                args.listen_address = ""  # Listen on every interface.

            # --not-host-only is just a shortcut optstring, no actual use
            # is intended later on.
            delattr(args, 'not_host_only')

        # --workspace and --sqlite cannot be specified either, as
        # both point to a database location.
        options = ['--sqlite', '--workspace']
        options_short = ['--sqlite', '-w']
        if set(arg_match(options)) == set(options) or \
                set(arg_match(options_short)) == set(options_short):
            parser.error("argument --sqlite: not allowed with "
                         "argument --workspace")

        # --workspace and --config-directory also aren't allowed together now,
        # the latter one is expected to replace the earlier.
        options = ['--config-directory', '--workspace']
        options_short = ['--config-directory', '-w']
        if set(arg_match(options)) == set(options) or \
                set(arg_match(options_short)) == set(options_short):
            parser.error("argument --config-directory: not allowed with "
                         "argument --workspace")

        # If workspace is specified, sqlite is workspace/config.sqlite
        # and config_directory is the workspace directory.
        if len(arg_match(['--workspace', '-w'])) > 0:
            args.config_directory = args.workspace
            args.sqlite = os.path.join(args.workspace,
                                       'config.sqlite')
            setattr(args, 'dbdatadir', os.path.join(args.workspace,
                                                    'pgsql_data'))

        # Workspace should not exist as a Namespace key.
        delattr(args, 'workspace')

        if '<CONFIG_DIRECTORY>' in args.sqlite:
            # Replace the placeholder variable with the actual value.
            args.sqlite = args.sqlite.replace('<CONFIG_DIRECTORY>',
                                              args.config_directory)

        if 'postgresql' not in args:
            # Later called database modules need the argument to be actually
            # present, even though the default is suppressed in the optstring.
            setattr(args, 'postgresql', False)

            # This is not needed by the database starter as we are
            # running SQLite.
            if 'dbdatadir' in args:
                delattr(args, 'dbdatadir')
        else:
            # If --postgresql is given, --sqlite is useless.
            delattr(args, 'sqlite')

        # If everything is fine, do call the handler for the subcommand.
        main(args)

    parser.set_defaults(func=__handle)
Ejemplo n.º 14
0
def main():
    """
    CodeChecker main command line.
    """

    def signal_handler(sig, frame):
        """
        Without this handler the PostgreSQL
        server does not terminate at signal.
        """
        sys.exit(1)

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    try:
        parser = argparse.ArgumentParser(
            prog='CodeChecker',
            formatter_class=argparse.RawDescriptionHelpFormatter,
            description='''
Run the CodeChecker source analyzer framework.
See the subcommands for specific features.''',
            epilog='''
Example usage:
--------------
Analyzing a project with default settings:
CodeChecker check -b "cd ~/myproject && make" -n myproject

Start the viewer to see the results:
CodeChecker server

See the results in a web browser: localhost:8001
See results in  the command line: CodeChecker cmd results -p 8001 -n myproject

To analyze a small project quickcheck feature can be used.
The results will be printed only to the standard output.
(No database will be used)

CodeChecker quickcheck -b "cd ~/myproject && make"
''')

        subparsers = parser.add_subparsers(help='commands')

        workspace_help_msg = 'Directory where the CodeChecker can' \
            ' store analysis related data.'

        name_help_msg = 'Name of the analysis.'

        jobs_help_msg = 'Number of jobs. ' \
            'Start multiple processes for faster analysis.'

        log_argument_help_msg = """Path to the log file which is created
         during the build. \nIf there is an already generated log file
         with the compilation commands\ngenerated by \'CodeChecker log\' or
         \'cmake -DCMAKE_EXPORT_COMPILE_COMMANDS\' \n CodeChecker check can
         use it for the analysis in that case running the original build
         will \nbe left out from the analysis process (no log is needed)."""

        suppress_help_msg = """Path to suppress file.\nSuppress file can be used
         to suppress analysis results during the analysis.\nIt is based on the
         bug identifier generated by the compiler which is experimental.\nDo
         not depend too much on this file because identifier or file format
         can be changed.\nFor other in source suppress features see the user
         guide."""

        # --------------------------------------
        # check commands
        check_parser = subparsers.add_parser('check',
                                             formatter_class=ADHF,
                                             help=''' \
Run the supported source code analyzers on a project.''')

        check_parser.add_argument('-w', '--workspace', type=str,
                                  default=util.get_default_workspace(),
                                  dest="workspace",
                                  help=workspace_help_msg)

        check_parser.add_argument('-n', '--name', type=str,
                                  dest="name", required=True,
                                  default=argparse.SUPPRESS,
                                  help=name_help_msg)

        checkgroup = check_parser.add_mutually_exclusive_group(required=True)

        checkgroup.add_argument('-b', '--build', type=str, dest="command",
                                default=argparse.SUPPRESS,
                                required=False, help='''\
Build command which is used to build the project.''')

        checkgroup.add_argument('-l', '--log', type=str, dest="logfile",
                                default=argparse.SUPPRESS,
                                required=False,
                                help=log_argument_help_msg)

        check_parser.add_argument('-j', '--jobs', type=int, dest="jobs",
                                  default=1, required=False,
                                  help=jobs_help_msg)

        check_parser.add_argument('-u', '--suppress', type=str,
                                  dest="suppress",
                                  default=argparse.SUPPRESS,
                                  required=False,
                                  help=suppress_help_msg)
        check_parser.add_argument('-c', '--clean',
                                  default=argparse.SUPPRESS,
                                  action=DeprecatedOptionAction)

        check_parser.add_argument('--update', action=DeprecatedOptionAction,
                                  dest="update", default=False, required=False,
                                  help="Incremental parsing, update the "
                                       "results of a previous run. "
                                       "Only the files changed since the last "
                                       "build will be reanalyzed. Depends on"
                                       " the build system.")

        check_parser.add_argument('--force', action="store_true",
                                  dest="force", default=False, required=False,
                                  help="Delete analysis results form the "
                                       "database if a run with the "
                                       "given name already exists.")

        check_parser.add_argument('-s', '--skip', type=str, dest="skipfile",
                                  default=argparse.SUPPRESS,
                                  required=False, help='Path to skip file.')

        check_parser.add_argument('--quiet-build',
                                  action='store_true',
                                  default=False,
                                  required=False,
                                  help='Do not print out the output of the '
                                       'original build.')

        check_parser.add_argument('--add-compiler-defaults',
                                  action='store_true',
                                  default=False,
                                  required=False,
                                  help='Fetch built in compiler include '
                                       'paths and defines '
                                       'and pass them to Clang. This is '
                                       'useful when you do cross-compilation.')

        add_analyzer_arguments(check_parser)
        add_database_arguments(check_parser)
        logger.add_verbose_arguments(check_parser)
        check_parser.set_defaults(func=arg_handler.handle_check)

        # --------------------------------------
        # QuickCheck commands.
        qcheck_parser = subparsers.add_parser('quickcheck',
                                              formatter_class=ADHF,
                                              help='Run CodeChecker for a '
                                                   'project without database.')

        qcheckgroup = qcheck_parser.add_mutually_exclusive_group(required=True)

        qcheckgroup.add_argument('-b', '--build', type=str, dest="command",
                                 default=argparse.SUPPRESS,
                                 required=False, help='Build command.')

        qcheckgroup.add_argument('-l', '--log', type=str, dest="logfile",
                                 required=False,
                                 default=argparse.SUPPRESS,
                                 help=log_argument_help_msg)

        qcheck_parser.add_argument('-s', '--steps', action="store_true",
                                   dest="print_steps", help='Print steps.')

        qcheck_parser.add_argument('--quiet-build',
                                   action='store_true',
                                   default=False,
                                   required=False,
                                   help='Do not print out the output of the '
                                        'original build.')
        qcheck_parser.add_argument('-i', '--skip', type=str, dest="skipfile",
                                   default=argparse.SUPPRESS,
                                   required=False, help='Path to skip file.')
        qcheck_parser.add_argument('-j', '--jobs', type=int, dest="jobs",
                                   default=1, required=False,
                                   help=jobs_help_msg)
        qcheck_parser.add_argument('-u', '--suppress', type=str,
                                   dest="suppress",
                                   default=argparse.SUPPRESS,
                                   required=False,
                                   help=suppress_help_msg)
        qcheck_parser.add_argument('--add-compiler-defaults',
                                   action='store_true',
                                   default=False,
                                   required=False,
                                   help='Fetch built in compiler include paths'
                                        ' and defines and pass them to Clang. '
                                        'This is useful when you'
                                        'do cross-compilation.')
        add_analyzer_arguments(qcheck_parser)
        logger.add_verbose_arguments(qcheck_parser)
        qcheck_parser.set_defaults(func=arg_handler.handle_quickcheck)

        # --------------------------------------
        # Log commands.
        logging_p = subparsers.add_parser('log',
                                          formatter_class=ADHF,
                                          help='Runs the given build '
                                               'command. During the '
                                               'build the compilation '
                                               'commands are collected '
                                               'and stored into a '
                                               'compilation command '
                                               'json file '
                                               '(no analysis is done '
                                               'during the build).')

        logging_p.add_argument('-o', '--output', type=str, dest="logfile",
                               default=argparse.SUPPRESS,
                               required=True,
                               help='Path to the log file.')

        logging_p.add_argument('-b', '--build', type=str, dest="command",
                               default=argparse.SUPPRESS,
                               required=True, help='Build command.')

        logger.add_verbose_arguments(logging_p)
        logging_p.set_defaults(func=arg_handler.handle_log)

        # --------------------------------------
        # Checkers parser.
        checker_p = subparsers.add_parser('checkers',
                                          formatter_class=ADHF,
                                          help='List the available checkers '
                                               'for the supported analyzers '
                                               'and show their default status '
                                               '(+ for being enabled, '
                                               '- for being disabled by '
                                               'default).')

        checker_p.add_argument('--analyzers', nargs='+',
                               dest="analyzers", required=False,
                               help='Select which analyzer checkers '
                               'should be listed.\nCurrently supported '
                               'analyzers:\n' + analyzers)

        logger.add_verbose_arguments(checker_p)
        checker_p.set_defaults(func=arg_handler.handle_list_checkers)

        # --------------------------------------
        # Server.
        server_parser = subparsers.add_parser('server',
                                              formatter_class=ADHF,
                                              help='Start and manage the '
                                                   'CodeChecker web server.')
        server_parser.add_argument('-w', '--workspace', type=str,
                                   dest="workspace",
                                   default=util.get_default_workspace(),
                                   help=workspace_help_msg)

        server_parser.add_argument('-l', '--list',
                                   action='store_true',
                                   dest="list",
                                   required=False,
                                   help='List servers started by your user.')

        server_parser.add_argument('-s', '--stop',
                                   action='store_true',
                                   dest="stop",
                                   required=False,
                                   help='Stops the server associated with '
                                        'the given view-port and workspace.')

        server_parser.add_argument('--stop-all',
                                   action='store_true',
                                   dest="stop_all",
                                   required=False,
                                   help='Stops all of your running '
                                        'CodeChecker instances.')

        server_parser.add_argument('-v', '--view-port', type=int,
                                   dest="view_port",
                                   default=8001, required=False,
                                   help='Port used for viewing.')

        server_parser.add_argument('-u', '--suppress', type=str,
                                   dest="suppress",
                                   required=False,
                                   help='Path to suppress file.')

        server_parser.add_argument('--not-host-only', action="store_true",
                                   dest="not_host_only",
                                   help='Viewing the results is possible not '
                                        'only by browsers or clients '
                                        'started locally.')

        server_parser.add_argument('--check-port', type=int, dest="check_port",
                                   default=None, required=False,
                                   help='Port used for checking.')

        server_parser.add_argument('--check-address', type=str,
                                   dest="check_address", default="localhost",
                                   required=False, help='Server address.')

        add_database_arguments(server_parser)
        logger.add_verbose_arguments(server_parser)
        server_parser.set_defaults(func=arg_handler.handle_server)

        # --------------------------------------
        # Cmd_line.
        cmd_line_parser = subparsers.add_parser('cmd',
                                                help='Command line client')
        cmd_line_client.register_client_command_line(cmd_line_parser)

        # --------------------------------------
        # Debug parser.
        debug_parser = subparsers.add_parser('debug',
                                             formatter_class=ADHF,
                                             help='Generate gdb debug dump '
                                                  'files for all the failed '
                                                  'compilation commands in '
                                                  'the last analyzer run.\n'
                                                  'Requires a database with '
                                                  'the failed compilation '
                                                  'commands.')

        debug_parser.add_argument('-w', '--workspace', type=str,
                                  dest="workspace",
                                  default=util.get_default_workspace(),
                                  help=workspace_help_msg)

        debug_parser.add_argument('-f', '--force', action="store_true",
                                  dest="force", required=False, default=False,
                                  help='Overwrite already generated files.')

        add_database_arguments(debug_parser)
        logger.add_verbose_arguments(debug_parser)
        debug_parser.set_defaults(func=arg_handler.handle_debug)

        # --------------------------------------
        # Plist parser.
        plist_parser = subparsers.add_parser('plist',
                                             formatter_class=ADHF,
                                             help='Parse plist files in '
                                                  'the given directory and '
                                                  'store them to the database '
                                                  'or print to the standard '
                                                  'output.')

        plist_parser.add_argument('-w', '--workspace', type=str,
                                  dest="workspace",
                                  default=util.get_default_workspace(),
                                  help=workspace_help_msg)

        plist_parser.add_argument('-n', '--name', type=str,
                                  dest="name", required=True,
                                  default=argparse.SUPPRESS,
                                  help=name_help_msg)

        plist_parser.add_argument('-d', '--directory', type=str,
                                  dest="directory", required=True,
                                  help='Path of a directory containing plist '
                                  'files to parse.')

        plist_parser.add_argument('-j', '--jobs', type=int, dest="jobs",
                                  default=1, required=False,
                                  help=jobs_help_msg)

        plist_parser.add_argument('-s', '--steps', action="store_true",
                                  dest="print_steps", help='Print steps.')

        plist_parser.add_argument('--stdout', action="store_true",
                                  dest="stdout",
                                  required=False, default=False,
                                  help='Print results to stdout instead of '
                                       'storing to the database.')

        plist_parser.add_argument('--force', action="store_true",
                                  dest="force", default=False, required=False,
                                  help='Delete analysis results form the '
                                       'database if a run with the given '
                                       'name already exists.')

        add_database_arguments(plist_parser)
        logger.add_verbose_arguments(plist_parser)
        plist_parser.set_defaults(func=arg_handler.handle_plist)

        # --------------------------------------
        # Package version info.
        version_parser = subparsers.add_parser('version',
                                               help='Print package version '
                                                    'information.')
        version_parser.set_defaults(func=arg_handler.handle_version_info)
        logger.add_verbose_arguments(version_parser)

        args = parser.parse_args()
        LoggerFactory.set_log_level(args.verbose)
        args.func(args)

    except KeyboardInterrupt as kb_err:
        LOG.info(str(kb_err))
        LOG.info("Interrupted by user...")
        sys.exit(1)

    except shared.ttypes.RequestFailed as thrift_ex:
        LOG.info("Server error.")
        LOG.info("Error code: " + str(thrift_ex.error_code))
        LOG.info("Error message: " + str(thrift_ex.message))
        sys.exit(1)

    # Handle all exception, but print stacktrace. It is needed for atexit.
    # atexit does not work correctly when an unhandled exception occurred.
    # So in this case, the servers left running when the script exited.
    except Exception:
        import traceback
        traceback.print_exc(file=sys.stdout)
        sys.exit(2)
Ejemplo n.º 15
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    # TODO: --name does not exist in 'parse'.
    # In 'store', --name is not a required argument by argparse, as 'analyze'
    # can prepare a name, which is read after 'store' is started.
    # If the name is missing, the user is explicitly warned.
    # TODO: This should be an optional argument here too. Also it doesn't make
    # sense to require --name if --stdout ('parse'-mode) is set.
    parser.add_argument('-n',
                        '--name',
                        type=str,
                        dest="name",
                        required=True,
                        default=argparse.SUPPRESS,
                        help="The name of the analysis run to use in storing "
                        "the reports to the database. If not specified, "
                        "the '--name' parameter given to 'codechecker-"
                        "analyze' will be used, if exists.")

    # TODO: This argument is without an opt-string in 'store' and 'parse'.
    parser.add_argument('-d',
                        '--directory',
                        type=str,
                        dest="directory",
                        required=True,
                        help="Path of the directory where the plist files "
                        "to be used are found.")

    # TODO: Workspace is no longer a concept in the new subcommands.
    parser.add_argument('-w',
                        '--workspace',
                        type=str,
                        default=util.get_default_workspace(),
                        dest="workspace",
                        help="Directory where CodeChecker can store analysis "
                        "related data, such as the database.")

    parser.add_argument('-f',
                        '--force',
                        dest="force",
                        default=False,
                        action='store_true',
                        required=False,
                        help="Delete analysis results stored in the database "
                        "for the current analysis run's name and store "
                        "only the results reported in the 'input' files. "
                        "(By default, CodeChecker would keep reports "
                        "that were coming from files not affected by the "
                        "analysis, and only incrementally update defect "
                        "reports for source files that were analysed.)")

    parser.add_argument('-j',
                        '--jobs',
                        type=int,
                        dest="jobs",
                        required=False,
                        default=1,
                        help="Number of threads to use in parsing and storing "
                        "of results. More threads mean faster analysis "
                        "at the cost of using more memory.")

    # TODO: Parse does not know '-s' or '--steps' for this.
    parser.add_argument('-s',
                        '--steps',
                        '--print-steps',
                        dest="print_steps",
                        action="store_true",
                        required=False,
                        help="Print the steps the analyzers took in finding "
                        "the reported defect.")

    parser.add_argument('--stdout',
                        dest="stdout",
                        action='store_true',
                        required=False,
                        default=False,
                        help="Print the analysis results to the standard "
                        "output instead of storing to the database.")

    server_args = parser.add_argument_group(
        "server arguments",
        "Specifies a 'CodeChecker server' instance which will be used to "
        "store the results. This server must be running and listening prior "
        "to the 'store' command being ran.")

    server_args.add_argument('--host',
                             type=str,
                             dest="host",
                             required=False,
                             default="localhost",
                             help="The IP address or hostname of the "
                             "CodeChecker server.")

    server_args.add_argument('-p',
                             '--port',
                             type=int,
                             dest="port",
                             required=False,
                             default=8001,
                             help="The port of the server to use for storing.")

    # TODO: These arguments have been retroactively removed from 'store'
    # and are deprecated here. They should be completely removed.
    dbmodes = parser.add_argument_group("database arguments")
    dbmodes = dbmodes.add_mutually_exclusive_group(required=False)
    db_deprec = "Database connectivity has been removed from 'check'. " \
                "Please specify a CodeChecker server address via --host " \
                "and --port instead!"

    # SQLite is the default, and for 'check', it was deprecated.
    # TODO: In 'store', --sqlite has been replaced as an option to specify the
    # .sqlite file, essentially replacing the concept of 'workspace'.
    dbmodes.add_argument('--sqlite',
                         kill_if_used=True,
                         error_string=db_deprec,
                         action=DeprecatedOptionAction)

    dbmodes.add_argument('--postgresql',
                         kill_if_used=True,
                         error_string=db_deprec,
                         action=DeprecatedOptionAction)

    pgsql = parser.add_argument_group(
        "PostgreSQL arguments", "Values of these arguments are ignored, "
        "unless '--postgresql' is specified!")

    # WARNING: '--dbaddress' default value influences workspace creation
    # in SQLite.
    # TODO: These are '--db-something' in 'store', not '--dbsomething'.
    pgsql.add_argument('--dbaddress',
                       nargs=1,
                       kill_if_used=True,
                       error_string=db_deprec,
                       action=DeprecatedOptionAction)

    pgsql.add_argument('--dbport',
                       nargs=1,
                       kill_if_used=True,
                       error_string=db_deprec,
                       action=DeprecatedOptionAction)

    pgsql.add_argument('--dbusername',
                       nargs=1,
                       kill_if_used=True,
                       error_string=db_deprec,
                       action=DeprecatedOptionAction)

    pgsql.add_argument('--dbname',
                       nargs=1,
                       kill_if_used=True,
                       error_string=db_deprec,
                       action=DeprecatedOptionAction)

    add_verbose_arguments(parser)

    def __kill_deprec(args):
        if '_deprecated' in args:
            LOG.warning("A deprecated argument was passed to the "
                        "commandline. This argument has no effect anymore, "
                        "and the behaviour has changed.")
            LOG.error("Execution halted: CodeChecker would work in an "
                      "unexpected way with this argument passed.")
            sys.exit(2)  # argparse kills with error code 2.

        # Call the main process if everything matches.
        main(args)

    parser.set_defaults(func=__kill_deprec)
Ejemplo n.º 16
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """
    def is_ctu_capable():
        """ Detects if the current clang is CTU compatible. """

        context = generic_package_context.get_context()
        ctu_func_map_cmd = context.ctu_func_map_cmd
        try:
            version = subprocess.check_output([ctu_func_map_cmd, '-version'])
        except (subprocess.CalledProcessError, OSError):
            version = 'ERROR'
        return version != 'ERROR'

    parser.add_argument('logfile',
                        type=str,
                        nargs='+',
                        help="Path to the JSON compilation command database "
                        "files which were created during the build. "
                        "The analyzers will check only the files "
                        "registered in these build databases.")

    parser.add_argument('-j',
                        '--jobs',
                        type=int,
                        dest="jobs",
                        required=False,
                        default=1,
                        help="Number of threads to use in analysis. More "
                        "threads mean faster analysis at the cost of "
                        "using more memory.")

    parser.add_argument('-i',
                        '--ignore',
                        '--skip',
                        dest="skipfile",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Path to the Skipfile dictating which project "
                        "files should be omitted from analysis. Please "
                        "consult the User guide on how a Skipfile "
                        "should be laid out.")

    parser.add_argument('-o',
                        '--output',
                        dest="output_path",
                        required=False,
                        default=os.path.join(util.get_default_workspace(),
                                             'reports'),
                        help="Store the analysis output in the given folder.")

    parser.add_argument('-t',
                        '--type',
                        '--output-format',
                        dest="output_format",
                        required=False,
                        choices=['plist'],
                        default='plist',
                        help="Specify the format the analysis results should "
                        "use.")

    parser.add_argument('-n',
                        '--name',
                        dest="name",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Annotate the ran analysis with a custom name in "
                        "the created metadata file.")

    analyzer_opts = parser.add_argument_group("analyzer arguments")

    analyzer_opts.add_argument(
        '--analyzers',
        nargs='+',
        dest='analyzers',
        metavar='ANALYZER',
        required=False,
        choices=analyzer_types.supported_analyzers,
        default=argparse.SUPPRESS,
        help="Run analysis only with the analyzers "
        "specified. Currently supported analyzers "
        "are: " + ', '.join(analyzer_types.supported_analyzers) + ".")

    analyzer_opts.add_argument('--add-compiler-defaults',
                               action='store_true',
                               default=False,
                               required=False,
                               help="Retrieve compiler-specific configuration "
                               "from the compilers themselves, and use "
                               "them with Clang. This is used when the "
                               "compiler on the system is special, e.g. "
                               "when doing cross-compilation.")

    analyzer_opts.add_argument('--capture-analysis-output',
                               dest='capture_analysis_output',
                               action='store_true',
                               default=argparse.SUPPRESS,
                               required=False,
                               help="Store standard output and standard error "
                               "of successful analyzer invocations "
                               "into the '<OUTPUT_DIR>/success' "
                               "directory.")

    analyzer_opts.add_argument('--saargs',
                               dest="clangsa_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for the Clang Static "
                               "Analyzer.")

    analyzer_opts.add_argument('--tidyargs',
                               dest="tidy_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for Clang-Tidy.")

    if is_ctu_capable():
        ctu_opts = parser.add_argument_group(
            "cross translation unit analysis arguments",
            "These arguments are only available if the Clang Static Analyzer "
            "supports Cross-TU analysis. By default, no CTU analysis is ran "
            "when 'CodeChecker analyze' is called.")

        ctu_modes = ctu_opts.add_mutually_exclusive_group()

        ctu_modes.add_argument('--ctu',
                               '--ctu-all',
                               action='store_const',
                               const=[True, True],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform Cross Translation Unit (CTU) "
                               "analysis, both 'collect' and 'analyze' "
                               "phases. In this mode, the extra files "
                               "created by 'collect' are cleaned up "
                               "after the analysis.")

        ctu_modes.add_argument('--ctu-collect',
                               action='store_const',
                               const=[True, False],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform the first, 'collect' phase of "
                               "Cross-TU analysis. This phase generates "
                               "extra files needed by CTU analysis, and "
                               "puts them into '<OUTPUT_DIR>/ctu-dir'. "
                               "NOTE: If this argument is present, "
                               "CodeChecker will NOT execute the "
                               "analyzers!")

        ctu_modes.add_argument('--ctu-analyze',
                               action='store_const',
                               const=[False, True],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform the second, 'analyze' phase of "
                               "Cross-TU analysis, using already "
                               "available extra files in "
                               "'<OUTPUT_DIR>/ctu-dir'. (These files "
                               "will not be cleaned up in this mode.)")

        ctu_opts.add_argument('--ctu-on-the-fly',
                              action='store_true',
                              dest='ctu_in_memory',
                              default=False,
                              help="If specified, the 'collect' phase will "
                              "not create the extra AST dumps, but "
                              "rather analysis will be ran with an "
                              "in-memory recompilation of the source "
                              "files.")

    checkers_opts = parser.add_argument_group(
        "checker configuration",
        "See 'codechecker-checkers' for the list of available checkers. "
        "You can fine-tune which checkers to use in the analysis by setting "
        "the enabled and disabled flags starting from the bigger groups "
        "and going inwards, e.g. '-e core -d core.uninitialized -e "
        "core.uninitialized.Assign' will enable every 'core' checker, but "
        "only 'core.uninitialized.Assign' from the 'core.uninitialized' "
        "group. Please consult the manual for details. Disabling certain "
        "checkers - such as the 'core' group - is unsupported by the LLVM/"
        "Clang community, and thus discouraged.")

    checkers_opts.add_argument('-e',
                               '--enable',
                               dest="enable",
                               metavar='checker/checker-group',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE USED in the analysis.")

    checkers_opts.add_argument('-d',
                               '--disable',
                               dest="disable",
                               metavar='checker/checker-group',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE PROHIBITED from use in the "
                               "analysis.")

    checkers_opts.add_argument('--enable-all',
                               dest="enable_all",
                               action='store_true',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="Force the running analyzers to use "
                               "almost every checker available. The "
                               "checker groups 'alpha.', 'debug.' and "
                               "'osx.' (on Linux) are NOT enabled "
                               "automatically and must be EXPLICITLY "
                               "specified. WARNING! Enabling all "
                               "checkers might result in the analysis "
                               "losing precision and stability, and "
                               "could even result in a total failure of "
                               "the analysis. USE WISELY AND AT YOUR "
                               "OWN RISK!")

    add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 17
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('--keep-tmp', action=DeprecatedOptionAction)

    log_args = parser.add_argument_group(
        "log arguments",
        "Specify how the build information database should be obtained. You "
        "need to specify either an already existing log file, or a build "
        "command which will be used to generate a log file on the fly.")

    log_args.add_argument('-q',
                          '--quiet-build',
                          dest="quiet_build",
                          action='store_true',
                          default=False,
                          required=False,
                          help="Do not print the output of the build tool "
                          "into the output of this command.")

    log_args = log_args.add_mutually_exclusive_group(required=True)

    log_args.add_argument('-b',
                          '--build',
                          type=str,
                          dest="command",
                          default=argparse.SUPPRESS,
                          required=False,
                          help="Execute and record a build command. Build "
                          "commands can be simple calls to 'g++' or "
                          "'clang++' or 'make', but a more complex "
                          "command, or the call of a custom script file "
                          "is also supported.")

    log_args.add_argument('-l',
                          '--logfile',
                          type=str,
                          dest="logfile",
                          help="Use an already existing JSON compilation "
                          "command database file specified at this path.")

    analyzer_opts = parser.add_argument_group("analyzer arguments")
    analyzer_opts.add_argument('-j',
                               '--jobs',
                               type=int,
                               dest="jobs",
                               required=False,
                               default=1,
                               help="Number of threads to use in analysis. "
                               "More threads mean faster analysis at "
                               "the cost of using more memory.")

    # TODO: Analyze knows '--ignore' also for this.
    analyzer_opts.add_argument('-i',
                               '--skip',
                               dest="skipfile",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="Path to the Skipfile dictating which "
                               "project files should be omitted from "
                               "analysis. Please consult the User guide "
                               "on how a Skipfile should be laid out.")

    analyzer_opts.add_argument(
        '--analyzers',
        nargs='+',
        dest='analyzers',
        metavar='ANALYZER',
        required=False,
        choices=analyzer_types.supported_analyzers,
        default=argparse.SUPPRESS,
        help="Run analysis only with the analyzers "
        "specified. Currently supported analyzers "
        "are: " + ', '.join(analyzer_types.supported_analyzers) + ".")

    analyzer_opts.add_argument('--add-compiler-defaults',
                               action='store_true',
                               default=False,
                               required=False,
                               help="Retrieve compiler-specific configuration "
                               "from the analyzers themselves, and use "
                               "them with Clang. This is used when the "
                               "compiler on the system is special, e.g. "
                               "when doing cross-compilation.")

    # TODO: One day, get rid of these. See Issue #36, #427.
    analyzer_opts.add_argument('--saargs',
                               dest="clangsa_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for the Clang Static "
                               "analyzer.")

    analyzer_opts.add_argument('--tidyargs',
                               dest="tidy_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for the Clang-Tidy "
                               "analyzer.")

    checkers_opts = parser.add_argument_group(
        "checker configuration",
        "See 'codechecker-checkers' for the list of available checkers. "
        "You can fine-tune which checkers to use in the analysis by setting "
        "the enabled and disabled flags starting from the bigger groups "
        "and going inwards, e.g. '-e core -d core.uninitialized -e "
        "core.uninitialized.Assign' will enable every 'core' checker, but "
        "only 'core.uninitialized.Assign' from the 'core.uninitialized' "
        "group. Please consult the manual for details. Disabling certain "
        "checkers - such as the 'core' group - is unsupported by the LLVM/"
        "Clang community, and thus discouraged.")

    checkers_opts.add_argument('-e',
                               '--enable',
                               dest="enable",
                               metavar='checker/checker-group',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE USED in the analysis.")

    checkers_opts.add_argument('-d',
                               '--disable',
                               dest="disable",
                               metavar='checker/checker-group',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE PROHIBITED from use in the "
                               "analysis.")

    output_opts = parser.add_argument_group("output arguments")
    # TODO: Analyze does not know '-u', only '--suppress'
    output_opts.add_argument('-u',
                             '--suppress',
                             type=str,
                             dest="suppress",
                             default=argparse.SUPPRESS,
                             required=False,
                             help="Path of the suppress file to use. Records "
                             "in the suppress file are used to suppress "
                             "the display of certain results when "
                             "parsing the analyses' report. (Reports to "
                             "an analysis result can also be suppressed "
                             "in the source code -- please consult the "
                             "manual on how to do so.) NOTE: The "
                             "suppress file relies on the \"bug "
                             "identifier\" generated by the analyzers "
                             "which is experimental, take care when "
                             "relying on it.")

    # TODO: Parse does not know '-s' or '--steps' for this.
    output_opts.add_argument('-s',
                             '--steps',
                             '--print-steps',
                             dest="print_steps",
                             action="store_true",
                             required=False,
                             help="Print the steps the analyzers took in "
                             "finding the reported defect.")

    add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 18
0
def main(subcommands=None):
    """
    CodeChecker main command line.
    """
    def signal_handler(sig, frame):
        """
        Without this handler the PostgreSQL
        server does not terminate at signal.
        """
        sys.exit(1)

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    try:
        parser = argparse.ArgumentParser(
            prog="CodeChecker",
            formatter_class=argparse.RawDescriptionHelpFormatter,
            description="""Run the CodeChecker sourcecode analyzer framework.
Please specify a subcommand to access individual features.""",
            epilog="""Example scenario: Analyzing, and storing results
------------------------------------------------
Start the server where the results will be stored and can be viewed
after the analysis is done:
    CodeChecker server

Analyze a project with default settings:
    CodeChecker check -b "cd ~/myproject && make" -n myproject

The results can be viewed:
 * In a web browser: http://localhost:8001
 * In the command line:
    CodeChecker cmd results -p 8001 -n myproject

Example scenario: Analyzing, and printing results to Terminal (no storage)
--------------------------------------------------------------------------
In this case, no database is used, and the results are printed on the standard
output.

    CodeChecker quickcheck -b "cd ~/myproject && make\"""")

        subparsers = parser.add_subparsers(help='commands')

        # TODO: Delete these once a later version rolls.
        old_subcommands = []

        def _warn_deprecated_command(cmd_name):
            # Write to stderr so the output is not captured by pipes, e.g.
            # with the "checkers" command, the "-" in the new command's name
            # would mess up pipe usage.
            err_msg = "[WARNING] The called command 'CodeChecker {0}' is " \
                      "DEPRECATED since version A.B. A new version is "    \
                      "available as 'codechecker-{0}'.\nThe DEPRECATED "   \
                      "command will be REPLACED when version X.Y is "      \
                      "released.\nPlease see 'codechecker-{0} --help' on " \
                      "details how to run the new version.\n".format(cmd_name)

            # This warning is implemented for showing later on, once old
            # behaviour commands are deprecated. We don't warn between 5.8 and
            # 6.0 for now.
            # sys.stderr.write(err_msg)

        # --------------------------------------
        # Checkers parser.
        checker_p = subparsers.add_parser('checkers',
                                          formatter_class=ADHF,
                                          help='List the available checkers '
                                          'for the supported analyzers '
                                          'and show their default status '
                                          '(+ for being enabled, '
                                          '- for being disabled by '
                                          'default).')
        old_subcommands.append('checkers')

        checker_p.add_argument('--analyzers',
                               nargs='+',
                               dest="analyzers",
                               required=False,
                               help='Select which analyzer checkers '
                               'should be listed.\nCurrently supported '
                               'analyzers:\n' + analyzers)

        logger.add_verbose_arguments(checker_p)
        checker_p.set_defaults(func=arg_handler.handle_list_checkers)

        if subcommands:
            # Try to check if the user has already given us a subcommand to
            # execute. If so, don't load every available parts of CodeChecker
            # to ensure a more optimised run.
            if len(sys.argv) > 1:
                first_command = sys.argv[1]
                if first_command in subcommands:
                    LOG.debug("Supplied an existing, valid subcommand: " +
                              first_command)

                    if 'CC_FROM_LEGACY_INVOKE' not in os.environ:
                        # Consider only the given command as an available one.
                        subcommands = [first_command]
                    else:
                        if first_command in old_subcommands:
                            # Certain commands as of now have a 'new' and an
                            # 'old' invocation and execution. In case of an
                            # 'old' invocation is passed ('CodeChecker
                            # command'), do NOT load the 'new' argument parser
                            # and executed method.
                            #
                            # TODO: Delete this once the new commands are
                            # fleshed out and old are deprecated later on.
                            _warn_deprecated_command(first_command)
                            subcommands = []

            for subcommand in subcommands:
                if 'CC_FROM_LEGACY_INVOKE' in os.environ and \
                        subcommand in old_subcommands:
                    # Make sure 'old' commands have a priority in the listing
                    # when '--help' is queried.
                    continue

                LOG.debug("Creating arg parser for subcommand " + subcommand)

                try:
                    libhandlers.add_subcommand(subparsers, str(subcommand))
                except (IOError, ImportError):
                    LOG.warning("Couldn't import module for subcommand '" +
                                subcommand + "'... ignoring.")
                    import traceback
                    traceback.print_exc(file=sys.stdout)

        args = parser.parse_args()
        if 'verbose' in args:
            LoggerFactory.set_log_level(args.verbose)
        args.func(args)

        if 'CC_FROM_LEGACY_INVOKE' in os.environ and \
                first_command and first_command in old_subcommands:
            _warn_deprecated_command(first_command)

    except KeyboardInterrupt as kb_err:
        LOG.info(str(kb_err))
        LOG.info("Interrupted by user...")
        sys.exit(1)

    except shared.ttypes.RequestFailed as thrift_ex:
        LOG.info("Server error.")
        LOG.info("Error code: " + str(thrift_ex.error_code))
        LOG.info("Error message: " + str(thrift_ex.message))
        sys.exit(1)

    # Handle all exception, but print stacktrace. It is needed for atexit.
    # atexit does not work correctly when an unhandled exception occurred.
    # So in this case, the servers left running when the script exited.
    except Exception:
        import traceback
        traceback.print_exc(file=sys.stdout)
        sys.exit(1)
Ejemplo n.º 19
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('input',
                        type=str,
                        nargs='+',
                        metavar='file/folder',
                        help="The analysis result files and/or folders "
                        "containing analysis results which should be "
                        "parsed and printed.")

    parser.add_argument('-t',
                        '--type',
                        '--input-format',
                        dest="input_format",
                        required=False,
                        choices=['plist'],
                        default='plist',
                        help="Specify the format the analysis results were "
                        "created as.")

    output_opts = parser.add_argument_group("export arguments")
    output_opts.add_argument('-e',
                             '--export',
                             dest="export",
                             required=False,
                             choices=['html'],
                             help="Specify extra output format type.")

    output_opts.add_argument('-o',
                             '--output',
                             dest="output_path",
                             help="Store the output in the given folder.")

    output_opts.add_argument('-c',
                             '--clean',
                             dest="clean",
                             required=False,
                             action='store_true',
                             default=True,
                             help="DEPRECATED. Delete output results stored "
                             "in the output directory. (By default, it "
                             "would keep output files and overwrites "
                             "only those that belongs to a plist file "
                             "given by the input argument.")

    parser.add_argument('--suppress',
                        type=str,
                        dest="suppress",
                        default=argparse.SUPPRESS,
                        required=False,
                        help="Path of the suppress file to use. Records in "
                        "the suppress file are used to suppress the "
                        "display of certain results when parsing the "
                        "analyses' report. (Reports to an analysis "
                        "result can also be suppressed in the source "
                        "code -- please consult the manual on how to "
                        "do so.) NOTE: The suppress file relies on the "
                        "\"bug identifier\" generated by the analyzers "
                        "which is experimental, take care when relying "
                        "on it.")

    parser.add_argument('--export-source-suppress',
                        dest="create_suppress",
                        action="store_true",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Write suppress data from the suppression "
                        "annotations found in the source files that were "
                        "analyzed earlier that created the results. "
                        "The suppression information will be written "
                        "to the parameter of '--suppress'.")

    parser.add_argument('--print-steps',
                        dest="print_steps",
                        action="store_true",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Print the steps the analyzers took in finding "
                        "the reported defect.")

    parser.add_argument('-i',
                        '--ignore',
                        '--skip',
                        dest="skipfile",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Path to the Skipfile dictating which project "
                        "files should be omitted from analysis. Please "
                        "consult the User guide on how a Skipfile "
                        "should be laid out.")

    logger.add_verbose_arguments(parser)

    def __handle(args):
        """Custom handler for 'parser' so custom error messages can be
        printed without having to capture 'parser' in main."""
        def arg_match(options):
            return util.arg_match(options, sys.argv[1:])

        # --export cannot be specified without --output.
        export = ['-e', '--export']
        output = ['-o', '--output']
        if any(arg_match(export)) and not any(arg_match(output)):
            parser.error("argument --export: not allowed without "
                         "argument --output")

        # If everything is fine, do call the handler for the subcommand.
        main(args)

    parser.set_defaults(func=__handle)
Ejemplo n.º 20
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('logfile',
                        type=str,
                        nargs='+',
                        help="Path to the JSON compilation command database "
                        "files which were created during the build. "
                        "The analyzers will check only the files "
                        "registered in these build databases.")

    parser.add_argument('-j',
                        '--jobs',
                        type=int,
                        dest="jobs",
                        required=False,
                        default=1,
                        help="Number of threads to use in analysis. More "
                        "threads mean faster analysis at the cost of "
                        "using more memory.")

    parser.add_argument('-i',
                        '--ignore',
                        '--skip',
                        dest="skipfile",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Path to the Skipfile dictating which project "
                        "files should be omitted from analysis. Please "
                        "consult the User guide on how a Skipfile "
                        "should be laid out.")

    parser.add_argument('-o',
                        '--output',
                        dest="output_path",
                        required=True,
                        default=argparse.SUPPRESS,
                        help="Store the analysis output in the given folder.")

    parser.add_argument('--compiler-includes-file',
                        dest="compiler_includes_file",
                        required=False,
                        default=None,
                        help="Read the compiler includes from the specified "
                        "file rather than invoke the compiler "
                        "executable.")

    parser.add_argument('--compiler-target-file',
                        dest="compiler_target_file",
                        required=False,
                        default=None,
                        help="Read the compiler target from the specified "
                        "file rather than invoke the compiler "
                        "executable.")

    parser.add_argument('-t',
                        '--type',
                        '--output-format',
                        dest="output_format",
                        required=False,
                        choices=['plist'],
                        default='plist',
                        help="Specify the format the analysis results should "
                        "use.")

    parser.add_argument('-q',
                        '--quiet',
                        dest="quiet",
                        action='store_true',
                        default=argparse.SUPPRESS,
                        required=False,
                        help="Do not print the output or error of the "
                        "analyzers to the standard output of "
                        "CodeChecker.")

    parser.add_argument('-c',
                        '--clean',
                        dest="clean",
                        required=False,
                        action='store_true',
                        default=argparse.SUPPRESS,
                        help="Delete analysis reports stored in the output "
                        "directory. (By default, CodeChecker would keep "
                        "reports and overwrites only those files that "
                        "were update by the current build command).")

    parser.add_argument('-n',
                        '--name',
                        dest="name",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Annotate the run analysis with a custom name in "
                        "the created metadata file.")

    analyzer_opts = parser.add_argument_group("analyzer arguments")

    analyzer_opts.add_argument(
        '--analyzers',
        nargs='+',
        dest='analyzers',
        metavar='ANALYZER',
        required=False,
        choices=analyzer_types.supported_analyzers,
        default=argparse.SUPPRESS,
        help="Run analysis only with the analyzers "
        "specified. Currently supported analyzers "
        "are: " + ', '.join(analyzer_types.supported_analyzers) + ".")

    analyzer_opts.add_argument('--add-compiler-defaults',
                               action='store_true',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="DEPRECATED. Always True. Retrieve "
                               "compiler-specific configuration "
                               "from the compilers themselves, and use "
                               "them with Clang. This is used when the "
                               "compiler on the system is special, e.g. "
                               "when doing cross-compilation.")

    analyzer_opts.add_argument('--capture-analysis-output',
                               dest='capture_analysis_output',
                               action='store_true',
                               default=argparse.SUPPRESS,
                               required=False,
                               help="Store standard output and standard error "
                               "of successful analyzer invocations "
                               "into the '<OUTPUT_DIR>/success' "
                               "directory.")

    analyzer_opts.add_argument('--saargs',
                               dest="clangsa_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for the Clang Static "
                               "Analyzer.")

    analyzer_opts.add_argument('--tidyargs',
                               dest="tidy_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for Clang-Tidy.")

    analyzer_opts.add_argument('--timeout',
                               type=int,
                               dest='timeout',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="The amount of time (in seconds) that "
                               "each analyzer can spend, individually, "
                               "to analyze the project. If the analysis "
                               "of a particular file takes longer than "
                               "this time, the analyzer is killed and "
                               "the analysis is considered as a failed "
                               "one.")

    if host_check.is_ctu_capable():
        ctu_opts = parser.add_argument_group(
            "cross translation unit analysis arguments",
            "These arguments are only available if the Clang Static Analyzer "
            "supports Cross-TU analysis. By default, no CTU analysis is run "
            "when 'CodeChecker analyze' is called.")

        ctu_modes = ctu_opts.add_mutually_exclusive_group()
        ctu_modes.add_argument('--ctu',
                               '--ctu-all',
                               action='store_const',
                               const=[True, True],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform Cross Translation Unit (CTU) "
                               "analysis, both 'collect' and 'analyze' "
                               "phases. In this mode, the extra files "
                               "created by 'collect' are cleaned up "
                               "after the analysis.")

        ctu_modes.add_argument('--ctu-collect',
                               action='store_const',
                               const=[True, False],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform the first, 'collect' phase of "
                               "Cross-TU analysis. This phase generates "
                               "extra files needed by CTU analysis, and "
                               "puts them into '<OUTPUT_DIR>/ctu-dir'. "
                               "NOTE: If this argument is present, "
                               "CodeChecker will NOT execute the "
                               "analyzers!")

        ctu_modes.add_argument('--ctu-analyze',
                               action='store_const',
                               const=[False, True],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform the second, 'analyze' phase of "
                               "Cross-TU analysis, using already "
                               "available extra files in "
                               "'<OUTPUT_DIR>/ctu-dir'. (These files "
                               "will not be cleaned up in this mode.)")

        ctu_opts.add_argument('--ctu-reanalyze-on-failure',
                              action='store_true',
                              dest='ctu_reanalyze_on_failure',
                              default=argparse.SUPPRESS,
                              help="If Cross-TU analysis is enabled and fails "
                              "for some reason, try to re analyze the "
                              "same translation unit without "
                              "Cross-TU enabled.")

    if host_check.is_statistics_capable():
        stat_opts = parser.add_argument_group(
            "EXPERIMENTAL statistics analysis feature arguments",
            "These arguments are only available if the Clang Static Analyzer "
            "supports Statistics-based analysis "
            "(e.g. statisticsCollector.ReturnValueCheck, "
            "statisticsCollector.SpecialReturnValue checkers are available).")
        stat_opts.add_argument('--stats-collect',
                               '--stats-collect',
                               action='store',
                               default=argparse.SUPPRESS,
                               dest='stats_output',
                               help="EXPERIMENTAL feature. "
                               "Perform the first, 'collect' phase of "
                               "Statistical analysis. This phase "
                               "generates extra files needed by "
                               "statistics analysis, and "
                               "puts them into "
                               "'<STATS_OUTPUT>'."
                               " NOTE: If this argument is present, "
                               "CodeChecker will NOT execute the "
                               "analyzers!")

        stat_opts.add_argument('--stats-use',
                               '--stats-use',
                               action='store',
                               default=argparse.SUPPRESS,
                               dest='stats_dir',
                               help="EXPERIMENTAL feature. "
                               "Use the previously generated statistics "
                               "results for the analysis from the given "
                               "'<STATS_DIR>'.")

        stat_opts.add_argument('--stats',
                               action='store_true',
                               default=argparse.SUPPRESS,
                               dest='stats_enabled',
                               help="EXPERIMENTAL feature. "
                               "Perform both phases of "
                               "Statistical analysis. This phase "
                               "generates extra files needed by "
                               "statistics analysis and enables "
                               "the statistical checkers. "
                               "No need to enable them explicitly.")

    checkers_opts = parser.add_argument_group(
        "checker configuration",
        "See 'codechecker-checkers' for the list of available checkers. "
        "You can fine-tune which checkers to use in the analysis by setting "
        "the enabled and disabled flags starting from the bigger groups "
        "and going inwards, e.g. '-e core -d core.uninitialized -e "
        "core.uninitialized.Assign' will enable every 'core' checker, but "
        "only 'core.uninitialized.Assign' from the 'core.uninitialized' "
        "group. Please consult the manual for details. Disabling certain "
        "checkers - such as the 'core' group - is unsupported by the LLVM/"
        "Clang community, and thus discouraged.")

    checkers_opts.add_argument('-e',
                               '--enable',
                               dest="enable",
                               metavar='checker/group/profile',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE USED in the analysis.")

    checkers_opts.add_argument('-d',
                               '--disable',
                               dest="disable",
                               metavar='checker/group/profile',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE PROHIBITED from use in the "
                               "analysis.")

    checkers_opts.add_argument('--enable-all',
                               dest="enable_all",
                               action='store_true',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="Force the running analyzers to use "
                               "almost every checker available. The "
                               "checker groups 'alpha.', 'debug.' and "
                               "'osx.' (on Linux) are NOT enabled "
                               "automatically and must be EXPLICITLY "
                               "specified. WARNING! Enabling all "
                               "checkers might result in the analysis "
                               "losing precision and stability, and "
                               "could even result in a total failure of "
                               "the analysis. USE WISELY AND AT YOUR "
                               "OWN RISK!")

    logger.add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 21
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('-o',
                        '--output',
                        type=str,
                        dest="output_dir",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Store the analysis output in the given folder. "
                        "If it is not given then the results go into a "
                        "temporary directory which will be removed after "
                        "the analysis.")

    parser.add_argument('-t',
                        '--type',
                        '--output-format',
                        dest="output_format",
                        required=False,
                        choices=['plist'],
                        default='plist',
                        help="Specify the format the analysis results "
                        "should use.")

    parser.add_argument('-q',
                        '--quiet',
                        dest="quiet",
                        action='store_true',
                        required=False,
                        default=argparse.SUPPRESS,
                        help="If specified, the build tool's and the "
                        "analyzers' output will not be printed to the "
                        "standard output.")

    parser.add_argument('-f',
                        '--force',
                        dest="force",
                        default=argparse.SUPPRESS,
                        action='store_true',
                        required=False,
                        help="Delete analysis results stored in the database "
                        "for the current analysis run's name and store "
                        "only the results reported in the 'input' files. "
                        "(By default, CodeChecker would keep reports "
                        "that were coming from files not affected by the "
                        "analysis, and only incrementally update defect "
                        "reports for source files that were analysed.)")

    log_args = parser.add_argument_group(
        "log arguments",
        "Specify how the build information database should be obtained. You "
        "need to specify either an already existing log file, or a build "
        "command which will be used to generate a log file on the fly.")

    log_args = log_args.add_mutually_exclusive_group(required=True)

    log_args.add_argument('-b',
                          '--build',
                          type=str,
                          dest="command",
                          default=argparse.SUPPRESS,
                          help="Execute and record a build command. Build "
                          "commands can be simple calls to 'g++' or "
                          "'clang++' or 'make', but a more complex "
                          "command, or the call of a custom script file "
                          "is also supported.")

    log_args.add_argument('-l',
                          '--logfile',
                          type=str,
                          dest="logfile",
                          default=argparse.SUPPRESS,
                          help="Use an already existing JSON compilation "
                          "command database file specified at this path.")

    analyzer_opts = parser.add_argument_group("analyzer arguments")
    analyzer_opts.add_argument('-j',
                               '--jobs',
                               type=int,
                               dest="jobs",
                               required=False,
                               default=1,
                               help="Number of threads to use in analysis. "
                               "More threads mean faster analysis at "
                               "the cost of using more memory.")

    analyzer_opts.add_argument('-c',
                               '--clean',
                               dest="clean",
                               required=False,
                               action='store_true',
                               default=argparse.SUPPRESS,
                               help="Delete analysis reports stored in the "
                               "output directory. (By default, "
                               "CodeChecker would keep reports and "
                               "overwrites only those files that were "
                               "update by the current build command).")

    analyzer_opts.add_argument('-i',
                               '--ignore',
                               '--skip',
                               dest="skipfile",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="Path to the Skipfile dictating which "
                               "project files should be omitted from "
                               "analysis. Please consult the User guide "
                               "on how a Skipfile should be laid out.")

    analyzer_opts.add_argument(
        '--analyzers',
        nargs='+',
        dest='analyzers',
        metavar='ANALYZER',
        required=False,
        choices=analyzer_types.supported_analyzers,
        default=argparse.SUPPRESS,
        help="Run analysis only with the analyzers "
        "specified. Currently supported analyzers "
        "are: " + ', '.join(analyzer_types.supported_analyzers) + ".")

    analyzer_opts.add_argument('--add-compiler-defaults',
                               action='store_true',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="DEPRECATED. Always True. Retrieve "
                               " compiler-specific configuration "
                               "from the analyzers themselves, and use "
                               "them with Clang. This is used when the "
                               "compiler on the system is special, e.g. "
                               "when doing cross-compilation.")

    analyzer_opts.add_argument('--capture-analysis-output',
                               dest='capture_analysis_output',
                               action='store_true',
                               default=argparse.SUPPRESS,
                               required=False,
                               help="Store standard output and standard error "
                               "of successful analyzer invocations "
                               "into the '<OUTPUT_DIR>/success' "
                               "directory.")

    # TODO: One day, get rid of these. See Issue #36, #427.
    analyzer_opts.add_argument('--saargs',
                               dest="clangsa_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for the Clang Static "
                               "analyzer.")

    analyzer_opts.add_argument('--tidyargs',
                               dest="tidy_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for the Clang-Tidy "
                               "analyzer.")

    analyzer_opts.add_argument('--timeout',
                               type=int,
                               dest='timeout',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="The amount of time (in seconds) that "
                               "each analyzer can spend, individually, "
                               "to analyze the project. If the analysis "
                               "of a particular file takes longer than "
                               "this time, the analyzer is killed and "
                               "the analysis is considered as a failed "
                               "one.")

    if host_check.is_ctu_capable():
        ctu_opts = parser.add_argument_group(
            "cross translation unit analysis arguments",
            "These arguments are only available if the Clang Static Analyzer "
            "supports Cross-TU analysis. By default, no CTU analysis is run "
            "when 'CodeChecker analyze' is called.")

        ctu_modes = ctu_opts.add_mutually_exclusive_group()

        ctu_modes.add_argument('--ctu',
                               '--ctu-all',
                               action='store_const',
                               const=[True, True],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform Cross Translation Unit (CTU) "
                               "analysis, both 'collect' and 'analyze' "
                               "phases. In this mode, the extra files "
                               "created by 'collect' are cleaned up "
                               "after the analysis.")

        ctu_modes.add_argument('--ctu-collect',
                               action='store_const',
                               const=[True, False],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform the first, 'collect' phase of "
                               "Cross-TU analysis. This phase generates "
                               "extra files needed by CTU analysis, and "
                               "puts them into '<OUTPUT_DIR>/ctu-dir'. "
                               "NOTE: If this argument is present, "
                               "CodeChecker will NOT execute the "
                               "analyzers!")

        ctu_modes.add_argument('--ctu-analyze',
                               action='store_const',
                               const=[False, True],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform the second, 'analyze' phase of "
                               "Cross-TU analysis, using already "
                               "available extra files in "
                               "'<OUTPUT_DIR>/ctu-dir'. (These files "
                               "will not be cleaned up in this mode.)")

    checkers_opts = parser.add_argument_group(
        "checker configuration",
        "See 'codechecker-checkers' for the list of available checkers. "
        "You can fine-tune which checkers to use in the analysis by setting "
        "the enabled and disabled flags starting from the bigger groups "
        "and going inwards, e.g. '-e core -d core.uninitialized -e "
        "core.uninitialized.Assign' will enable every 'core' checker, but "
        "only 'core.uninitialized.Assign' from the 'core.uninitialized' "
        "group. Please consult the manual for details. Disabling certain "
        "checkers - such as the 'core' group - is unsupported by the LLVM/"
        "Clang community, and thus discouraged.")

    checkers_opts.add_argument('-e',
                               '--enable',
                               dest="enable",
                               metavar='checker/group/profile',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE USED in the analysis.")

    checkers_opts.add_argument('-d',
                               '--disable',
                               dest="disable",
                               metavar='checker/group/profile',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE PROHIBITED from use in the "
                               "analysis.")

    checkers_opts.add_argument('--enable-all',
                               dest="enable_all",
                               action='store_true',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="Force the running analyzers to use "
                               "almost every checker available. The "
                               "checker groups 'alpha.', 'debug.' and "
                               "'osx.' (on Linux) are NOT enabled "
                               "automatically and must be EXPLICITLY "
                               "specified. WARNING! Enabling all "
                               "checkers might result in the analysis "
                               "losing precision and stability, and "
                               "could even result in a total failure of "
                               "the analysis. USE WISELY AND AT YOUR "
                               "OWN RISK!")

    output_opts = parser.add_argument_group("output arguments")

    output_opts.add_argument('--print-steps',
                             dest="print_steps",
                             action="store_true",
                             required=False,
                             default=argparse.SUPPRESS,
                             help="Print the steps the analyzers took in "
                             "finding the reported defect.")

    logger.add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 22
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('logfile',
                        type=str,
                        nargs='+',
                        help="Path to the JSON compilation command database "
                             "files which were created during the build. "
                             "The analyzers will check only the files "
                             "registered in these build databases.")

    parser.add_argument('-j', '--jobs',
                        type=int,
                        dest="jobs",
                        required=False,
                        default=1,
                        help="Number of threads to use in analysis. More "
                             "threads mean faster analysis at the cost of "
                             "using more memory.")

    parser.add_argument('-i', '--ignore', '--skip',
                        dest="skipfile",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Path to the Skipfile dictating which project "
                             "files should be omitted from analysis. Please "
                             "consult the User guide on how a Skipfile "
                             "should be laid out.")

    parser.add_argument('-o', '--output',
                        dest="output_path",
                        required=False,
                        default=os.path.join(util.get_default_workspace(),
                                             'reports'),
                        help="Store the analysis output in the given folder.")

    parser.add_argument('-t', '--type', '--output-format',
                        dest="output_format",
                        required=False,
                        choices=['plist'],
                        default='plist',
                        help="Specify the format the analysis results should "
                             "use.")

    parser.add_argument('-n', '--name',
                        dest="name",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Annotate the ran analysis with a custom name in "
                             "the created metadata file.")

    analyzer_opts = parser.add_argument_group("analyzer arguments")

    analyzer_opts.add_argument('--analyzers',
                               nargs='+',
                               dest='analyzers',
                               metavar='ANALYZER',
                               required=False,
                               choices=analyzer_types.supported_analyzers,
                               default=argparse.SUPPRESS,
                               help="Run analysis only with the analyzers "
                                    "specified. Currently supported analyzers "
                                    "are: " +
                                    ', '.join(analyzer_types.
                                              supported_analyzers) + ".")

    analyzer_opts.add_argument('--add-compiler-defaults',
                               action='store_true',
                               default=False,
                               required=False,
                               help="Retrieve compiler-specific configuration "
                                    "from the compilers themselves, and use "
                                    "them with Clang. This is used when the "
                                    "compiler on the system is special, e.g. "
                                    "when doing cross-compilation.")

    analyzer_opts.add_argument('--saargs',
                               dest="clangsa_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                                    "forwarded verbatim for the Clang Static "
                                    "Analyzer.")

    analyzer_opts.add_argument('--tidyargs',
                               dest="tidy_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                                    "forwarded verbatim for Clang-Tidy.")

    checkers_opts = parser.add_argument_group(
        "checker configuration",
        "See 'codechecker-checkers' for the list of available checkers. "
        "You can fine-tune which checkers to use in the analysis by setting "
        "the enabled and disabled flags starting from the bigger groups "
        "and going inwards, e.g. '-e core -d core.uninitialized -e "
        "core.uninitialized.Assign' will enable every 'core' checker, but "
        "only 'core.uninitialized.Assign' from the 'core.uninitialized' "
        "group. Please consult the manual for details. Disabling certain "
        "checkers - such as the 'core' group - is unsupported by the LLVM/"
        "Clang community, and thus discouraged.")

    checkers_opts.add_argument('-e', '--enable',
                               dest="enable",
                               metavar='checker/checker-group',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                                    "to BE USED in the analysis.")

    checkers_opts.add_argument('-d', '--disable',
                               dest="disable",
                               metavar='checker/checker-group',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                                    "to BE PROHIBITED from use in the "
                                    "analysis.")

    checkers_opts.add_argument('--enable-all',
                               dest="enable_all",
                               action='store_true',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="Force the running analyzers to use "
                                    "almost every checker available. The "
                                    "checker groups 'alpha.', 'debug.' and "
                                    "'osx.' (on Linux) are NOT enabled "
                                    "automatically and must be EXPLICITLY "
                                    "specified. WARNING! Enabling all "
                                    "checkers might result in the analysis "
                                    "losing precision and stability, and "
                                    "could even result in a total failure of "
                                    "the analysis. USE WISELY AND AT YOUR "
                                    "OWN RISK!")

    add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 23
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    # Some arguments were deprecated already in 'CodeChecker check'.
    parser.add_argument('--keep-tmp', action=DeprecatedOptionAction)

    parser.add_argument('-c', '--clean', action=DeprecatedOptionAction)

    parser.add_argument('--update', action=DeprecatedOptionAction)

    # In 'store', --name is not a required argument by argparse, as 'analyze'
    # can prepare a name, which is read after 'store' is started.
    # If the name is missing, the user is explicitly warned.
    # TODO: This should be an optional argument here too.
    parser.add_argument('-n',
                        '--name',
                        type=str,
                        dest="name",
                        required=True,
                        default=argparse.SUPPRESS,
                        help="The name of the analysis run to use in storing "
                        "the reports to the database. If not specified, "
                        "the '--name' parameter given to 'codechecker-"
                        "analyze' will be used, if exists.")

    # TODO: Workspace is no longer a concept in the new subcommands.
    parser.add_argument('-w',
                        '--workspace',
                        type=str,
                        default=util.get_default_workspace(),
                        dest="workspace",
                        help="Directory where CodeChecker can store analysis "
                        "related data, such as intermediate result files "
                        "and the database.")

    parser.add_argument('-f',
                        '--force',
                        dest="force",
                        default=False,
                        action='store_true',
                        required=False,
                        help="Delete analysis results stored in the database "
                        "for the current analysis run's name and store "
                        "only the results reported in the 'input' files. "
                        "(By default, CodeChecker would keep reports "
                        "that were coming from files not affected by the "
                        "analysis, and only incrementally update defect "
                        "reports for source files that were analysed.)")

    log_args = parser.add_argument_group(
        "log arguments",
        "Specify how the build information database should be obtained. You "
        "need to specify either an already existing log file, or a build "
        "command which will be used to generate a log file on the fly.")

    log_args.add_argument('-q',
                          '--quiet-build',
                          dest="quiet_build",
                          action='store_true',
                          default=False,
                          required=False,
                          help="Do not print the output of the build tool "
                          "into the output of this command.")

    log_args = log_args.add_mutually_exclusive_group(required=True)

    log_args.add_argument('-b',
                          '--build',
                          type=str,
                          dest="command",
                          default=argparse.SUPPRESS,
                          required=False,
                          help="Execute and record a build command. Build "
                          "commands can be simple calls to 'g++' or "
                          "'clang++' or 'make', but a more complex "
                          "command, or the call of a custom script file "
                          "is also supported.")

    log_args.add_argument('-l',
                          '--logfile',
                          type=str,
                          dest="logfile",
                          help="Use an already existing JSON compilation "
                          "command database file specified at this path.")

    analyzer_opts = parser.add_argument_group("analyzer arguments")
    analyzer_opts.add_argument('-j',
                               '--jobs',
                               type=int,
                               dest="jobs",
                               required=False,
                               default=1,
                               help="Number of threads to use in analysis. "
                               "More threads mean faster analysis at "
                               "the cost of using more memory.")

    # TODO: Analyze knows '--ignore' also for this.
    analyzer_opts.add_argument('-i',
                               '--skip',
                               dest="skipfile",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="Path to the Skipfile dictating which "
                               "project files should be omitted from "
                               "analysis. Please consult the User guide "
                               "on how a Skipfile should be laid out.")

    analyzer_opts.add_argument(
        '--analyzers',
        nargs='+',
        dest='analyzers',
        metavar='ANALYZER',
        required=False,
        choices=analyzer_types.supported_analyzers,
        default=argparse.SUPPRESS,
        help="Run analysis only with the analyzers "
        "specified. Currently supported analyzers "
        "are: " + ', '.join(analyzer_types.supported_analyzers) + ".")

    analyzer_opts.add_argument('--add-compiler-defaults',
                               action='store_true',
                               default=False,
                               required=False,
                               help="Retrieve compiler-specific configuration "
                               "from the compilers themselves, and use "
                               "them with Clang. This is used when the "
                               "compiler on the system is special, e.g. "
                               "when doing cross-compilation.")

    analyzer_opts.add_argument('--saargs',
                               dest="clangsa_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for the Clang Static "
                               "analyzer.")

    analyzer_opts.add_argument('--tidyargs',
                               dest="tidy_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for the Clang-Tidy "
                               "analyzer.")

    checkers_opts = parser.add_argument_group(
        "checker configuration",
        "See 'codechecker-checkers' for the list of available checkers. "
        "You can fine-tune which checkers to use in the analysis by setting "
        "the enabled and disabled flags starting from the bigger groups "
        "and going inwards, e.g. '-e core -d core.uninitialized -e "
        "core.uninitialized.Assign' will enable every 'core' checker, but "
        "only 'core.uninitialized.Assign' from the 'core.uninitialized' "
        "group. Please consult the manual for details. Disabling certain "
        "checkers - such as the 'core' group - is unsupported by the LLVM/"
        "Clang community, and thus discouraged.")

    checkers_opts.add_argument('-e',
                               '--enable',
                               dest="enable",
                               metavar='checker/checker-group',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE USED in the analysis.")

    checkers_opts.add_argument('-d',
                               '--disable',
                               dest="disable",
                               metavar='checker/checker-group',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE PROHIBITED from use in the "
                               "analysis.")

    # TODO: Analyze does not know '-u', only '--suppress'
    parser.add_argument('-u',
                        '--suppress',
                        type=str,
                        dest="suppress",
                        default=argparse.SUPPRESS,
                        required=False,
                        help="Path of the suppress file to use. Records in "
                        "the suppress file are used to suppress the "
                        "storage of certain results when parsing the "
                        "analyses' report. (Reports to an analysis "
                        "result can also be suppressed in the source "
                        "code -- please consult the manual on how to do "
                        "so.) NOTE: The suppress file relies on the "
                        "\"bug identifier\" generated by the analyzers "
                        "which is experimental, take care when relying "
                        "on it.")

    dbmodes = parser.add_argument_group("database arguments")

    dbmodes = dbmodes.add_mutually_exclusive_group(required=False)

    # SQLite is the default, and for 'check', it was deprecated.
    # TODO: In 'store', --sqlite has been replaced as an option to specify the
    # .sqlite file, essentially replacing the concept of 'workspace'.
    dbmodes.add_argument('--sqlite', action=DeprecatedOptionAction)

    dbmodes.add_argument('--postgresql',
                         dest="postgresql",
                         action='store_true',
                         required=False,
                         default=argparse.SUPPRESS,
                         help="Specifies that a PostgreSQL database is to be "
                         "used instead of SQLite. See the \"PostgreSQL "
                         "arguments\" section on how to configure the "
                         "database connection.")

    pgsql = parser.add_argument_group(
        "PostgreSQL arguments", "Values of these arguments are ignored, "
        "unless '--postgresql' is specified!")

    # WARNING: '--dbaddress' default value influences workspace creation
    # in SQLite.
    # TODO: These are '--db-something' in 'store', not '--dbsomething'.
    pgsql.add_argument('--dbaddress',
                       type=str,
                       dest="dbaddress",
                       default="localhost",
                       required=False,
                       help="Database server address.")

    pgsql.add_argument('--dbport',
                       type=int,
                       dest="dbport",
                       default=5432,
                       required=False,
                       help="Database server port.")

    pgsql.add_argument('--dbusername',
                       type=str,
                       dest="dbusername",
                       default='codechecker',
                       required=False,
                       help="Username to use for connection.")

    pgsql.add_argument('--dbname',
                       type=str,
                       dest="dbname",
                       default="codechecker",
                       required=False,
                       help="Name of the database to use.")

    add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 24
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    # TODO: --name does not exist in 'parse'.
    # In 'store', --name is not a required argument by argparse, as 'analyze'
    # can prepare a name, which is read after 'store' is started.
    # If the name is missing, the user is explicitly warned.
    # TODO: This should be an optional argument here too. Also it doesn't make
    # sense to require --name if --stdout ('parse'-mode) is set.
    parser.add_argument('-n',
                        '--name',
                        type=str,
                        dest="name",
                        required=True,
                        default=argparse.SUPPRESS,
                        help="The name of the analysis run to use in storing "
                        "the reports to the database. If not specified, "
                        "the '--name' parameter given to 'codechecker-"
                        "analyze' will be used, if exists.")

    # TODO: This argument is without an opt-string in 'store' and 'parse'.
    parser.add_argument('-d',
                        '--directory',
                        type=str,
                        dest="directory",
                        required=True,
                        help="Path of the directory where the plist files "
                        "to be used are found.")

    # TODO: Workspace is no longer a concept in the new subcommands.
    parser.add_argument('-w',
                        '--workspace',
                        type=str,
                        default=util.get_default_workspace(),
                        dest="workspace",
                        help="Directory where CodeChecker can store analysis "
                        "related data, such as the database.")

    parser.add_argument('-f',
                        '--force',
                        dest="force",
                        default=False,
                        action='store_true',
                        required=False,
                        help="Delete analysis results stored in the database "
                        "for the current analysis run's name and store "
                        "only the results reported in the 'input' files. "
                        "(By default, CodeChecker would keep reports "
                        "that were coming from files not affected by the "
                        "analysis, and only incrementally update defect "
                        "reports for source files that were analysed.)")

    parser.add_argument('-j',
                        '--jobs',
                        type=int,
                        dest="jobs",
                        required=False,
                        default=1,
                        help="Number of threads to use in parsing and storing "
                        "of results. More threads mean faster analysis "
                        "at the cost of using more memory.")

    # TODO: Parse does not know '-s' or '--steps' for this.
    parser.add_argument('-s',
                        '--steps',
                        '--print-steps',
                        dest="print_steps",
                        action="store_true",
                        required=False,
                        help="Print the steps the analyzers took in finding "
                        "the reported defect.")

    parser.add_argument('--stdout',
                        dest="stdout",
                        action='store_true',
                        required=False,
                        default=False,
                        help="Print the analysis results to the standard "
                        "output instead of storing to the database.")

    dbmodes = parser.add_argument_group("database arguments")

    dbmodes = dbmodes.add_mutually_exclusive_group(required=False)

    # SQLite is the default, and for 'check', it was deprecated.
    # TODO: In 'store', --sqlite has been replaced as an option to specify the
    # .sqlite file, essentially replacing the concept of 'workspace'.
    dbmodes.add_argument('--sqlite', action=DeprecatedOptionAction)

    dbmodes.add_argument('--postgresql',
                         dest="postgresql",
                         action='store_true',
                         required=False,
                         default=argparse.SUPPRESS,
                         help="Specifies that a PostgreSQL database is to be "
                         "used instead of SQLite. See the \"PostgreSQL "
                         "arguments\" section on how to configure the "
                         "database connection.")

    pgsql = parser.add_argument_group(
        "PostgreSQL arguments", "Values of these arguments are ignored, "
        "unless '--postgresql' is specified!")

    # WARNING: '--dbaddress' default value influences workspace creation
    # in SQLite.
    # TODO: These are '--db-something' in 'store', not '--dbsomething'.
    pgsql.add_argument('--dbaddress',
                       type=str,
                       dest="dbaddress",
                       default="localhost",
                       required=False,
                       help="Database server address.")

    pgsql.add_argument('--dbport',
                       type=int,
                       dest="dbport",
                       default=5432,
                       required=False,
                       help="Database server port.")

    pgsql.add_argument('--dbusername',
                       type=str,
                       dest="dbusername",
                       default='codechecker',
                       required=False,
                       help="Username to use for connection.")

    pgsql.add_argument('--dbname',
                       type=str,
                       dest="dbname",
                       default="codechecker",
                       required=False,
                       help="Name of the database to use.")

    add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 25
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('input',
                        type=str,
                        nargs='*',
                        metavar='file/folder',
                        default=os.path.join(util.get_default_workspace(),
                                             'reports'),
                        help="The analysis result files and/or folders "
                        "containing analysis results which should be "
                        "parsed and printed.")

    parser.add_argument('-t',
                        '--type',
                        '--input-format',
                        dest="input_format",
                        required=False,
                        choices=['plist'],
                        default='plist',
                        help="Specify the format the analysis results were "
                        "created as.")

    parser.add_argument('-j',
                        '--jobs',
                        type=int,
                        dest="jobs",
                        required=False,
                        default=1,
                        help="Number of threads to use in storing results. "
                        "More threads mean faster operation at the cost "
                        "of using more memory.")

    parser.add_argument('-n',
                        '--name',
                        type=str,
                        dest="name",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="The name of the analysis run to use in storing "
                        "the reports to the database. If not specified, "
                        "the '--name' parameter given to 'codechecker-"
                        "analyze' will be used, if exists.")

    # Upcoming feature planned for v6.0. Argument name and help RESERVED.
    # parser.add_argument('--group', '--group-name',
    #                    type=str,
    #                    dest="group_name",
    #                    required=False,
    #                    default=argparse.SUPPRESS,
    #                    help="Specify the \"analysis group\" the results "
    #                         "stored will belong to. An analysis group "
    #                         "consists of multiple analyses whose reports "
    #                         "are showed together in a common view -- e.g. "
    #                         "a project's view for every subproject analysed "
    #                         "separately, or all analyses of a user or a "
    #                         "team.")

    parser.add_argument('--suppress',
                        type=str,
                        dest="suppress",
                        default=argparse.SUPPRESS,
                        required=False,
                        help="Path of the suppress file to use. Records in "
                        "the suppress file are used to mark certain "
                        "stored analysis results as 'suppressed'. "
                        "(Reports to an analysis result can also be "
                        "suppressed in the source code -- please "
                        "consult the manual on how to do so.) NOTE: The "
                        "suppress file relies on the \"bug identifier\" "
                        "generated by the analyzers which is "
                        "experimental, take care when relying on it.")

    parser.add_argument('-f',
                        '--force',
                        dest="force",
                        default=False,
                        action='store_true',
                        required=False,
                        help="Delete analysis results stored in the database "
                        "for the current analysis run's name and store "
                        "only the results reported in the 'input' files. "
                        "(By default, CodeChecker would keep reports "
                        "that were coming from files not affected by the "
                        "analysis, and only incrementally update defect "
                        "reports for source files that were analysed.)")

    dbmodes = parser.add_argument_group("database arguments")

    dbmodes = dbmodes.add_mutually_exclusive_group(required=False)

    dbmodes.add_argument('--sqlite',
                         type=str,
                         dest="sqlite",
                         metavar='SQLITE_FILE',
                         default=os.path.join(util.get_default_workspace(),
                                              "codechecker.sqlite"),
                         required=False,
                         help="Path of the SQLite database file to use.")

    dbmodes.add_argument('--postgresql',
                         dest="postgresql",
                         action='store_true',
                         required=False,
                         default=argparse.SUPPRESS,
                         help="Specifies that a PostgreSQL database is to be "
                         "used instead of SQLite. See the \"PostgreSQL "
                         "arguments\" section on how to configure the "
                         "database connection.")

    pgsql = parser.add_argument_group(
        "PostgreSQL arguments", "Values of these arguments are ignored, "
        "unless '--postgresql' is specified!")

    # WARNING: '--dbaddress' default value influences workspace creation
    # in SQLite.
    pgsql.add_argument('--db-host',
                       type=str,
                       dest="dbaddress",
                       default="localhost",
                       required=False,
                       help="Database server address.")

    pgsql.add_argument('--db-port',
                       type=int,
                       dest="dbport",
                       default=5432,
                       required=False,
                       help="Database server port.")

    pgsql.add_argument('--db-username',
                       type=str,
                       dest="dbusername",
                       default='codechecker',
                       required=False,
                       help="Username to use for connection.")

    pgsql.add_argument('--db-name',
                       type=str,
                       dest="dbname",
                       default="codechecker",
                       required=False,
                       help="Name of the database to use.")

    add_verbose_arguments(parser)

    def __handle(args):
        """Custom handler for 'store' so custom error messages can be
        printed without having to capture 'parser' in main."""
        def arg_match(options):
            """Checks and selects the option string specified in 'options'
            that are present in the invocation argv."""
            matched_args = []
            for option in options:
                if any([
                        arg if option.startswith(arg) else None
                        for arg in sys.argv[1:]
                ]):
                    matched_args.append(option)
                    continue

            return matched_args

        # See if there is a "PostgreSQL argument" specified in the invocation
        # without '--postgresql' being there. There is no way to distinguish
        # a default argument and a deliberately specified argument without
        # inspecting sys.argv.
        options = ['--db-host', '--db-port', '--db-username', '--db-name']
        psql_args_matching = arg_match(options)
        if any(psql_args_matching) and \
                'postgresql' not in args:
            first_matching_arg = next(
                iter([match for match in psql_args_matching]))
            parser.error("argument {0}: not allowed without "
                         "argument --postgresql".format(first_matching_arg))
            # parser.error() terminates with return code 2.

        if 'postgresql' not in args:
            # Later called database modules need the argument to be actually
            # present, even though the default is suppressed in the optstring.
            setattr(args, 'postgresql', False)
        else:
            # If --postgresql is given, --sqlite is useless.
            delattr(args, 'sqlite')

        # If everything is fine, do call the handler for the subcommand.
        main(args)

    parser.set_defaults(func=__handle)
Ejemplo n.º 26
0
def add_arguments_to_parser(parser):
    """
    Add the subcommand's arguments to the given argparse.ArgumentParser.
    """

    parser.add_argument('-o',
                        '--output',
                        type=str,
                        dest="output_dir",
                        required=False,
                        default=argparse.SUPPRESS,
                        help="Store the analysis output in the given folder. "
                        "If it is not given then the results go into a "
                        "temporary directory which will be removed after "
                        "the analysis.")

    parser.add_argument('-t',
                        '--type',
                        '--output-format',
                        dest="output_format",
                        required=False,
                        choices=['plist'],
                        default='plist',
                        help="Specify the format the analysis results "
                        "should use.")

    parser.add_argument('-q',
                        '--quiet',
                        dest="quiet",
                        action='store_true',
                        required=False,
                        default=argparse.SUPPRESS,
                        help="If specified, the build tool's and the "
                        "analyzers' output will not be printed to the "
                        "standard output.")

    parser.add_argument('-f',
                        '--force',
                        dest="force",
                        default=argparse.SUPPRESS,
                        action='store_true',
                        required=False,
                        help="Delete analysis results stored in the database "
                        "for the current analysis run's name and store "
                        "only the results reported in the 'input' files. "
                        "(By default, CodeChecker would keep reports "
                        "that were coming from files not affected by the "
                        "analysis, and only incrementally update defect "
                        "reports for source files that were analysed.)")

    log_args = parser.add_argument_group(
        "log arguments", """
Specify how the build information database should be obtained. You need to
specify either an already existing log file, or a build command which will be
used to generate a log file on the fly.""")

    log_args = log_args.add_mutually_exclusive_group(required=True)

    log_args.add_argument('-b',
                          '--build',
                          type=str,
                          dest="command",
                          default=argparse.SUPPRESS,
                          help="Execute and record a build command. Build "
                          "commands can be simple calls to 'g++' or "
                          "'clang++' or 'make', but a more complex "
                          "command, or the call of a custom script file "
                          "is also supported.")

    log_args.add_argument('-l',
                          '--logfile',
                          type=str,
                          dest="logfile",
                          default=argparse.SUPPRESS,
                          help="Use an already existing JSON compilation "
                          "command database file specified at this path.")

    analyzer_opts = parser.add_argument_group("analyzer arguments")
    analyzer_opts.add_argument('-j',
                               '--jobs',
                               type=int,
                               dest="jobs",
                               required=False,
                               default=1,
                               help="Number of threads to use in analysis. "
                               "More threads mean faster analysis at "
                               "the cost of using more memory.")

    analyzer_opts.add_argument('-c',
                               '--clean',
                               dest="clean",
                               required=False,
                               action='store_true',
                               default=argparse.SUPPRESS,
                               help="Delete analysis reports stored in the "
                               "output directory. (By default, "
                               "CodeChecker would keep reports and "
                               "overwrites only those files that were "
                               "update by the current build command).")

    analyzer_opts.add_argument('--report-hash',
                               dest="report_hash",
                               default=argparse.SUPPRESS,
                               required=False,
                               choices=['context-free'],
                               help="EXPERIMENTAL feature. "
                               "Specify the hash calculation method for "
                               "reports. If this option is not set, the "
                               "default calculation method for Clang "
                               "Static Analyzer will be context "
                               "sensitive and for Clang Tidy it will be "
                               "context insensitive. If this option is "
                               "set to 'context-free' bugs will be "
                               "identified with the CodeChecker "
                               "generated context free hash for every "
                               "analyzers. USE WISELY AND AT YOUR OWN "
                               "RISK!")

    analyzer_opts.add_argument('-i',
                               '--ignore',
                               '--skip',
                               dest="skipfile",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="Path to the Skipfile dictating which "
                               "project files should be omitted from "
                               "analysis. Please consult the User guide "
                               "on how a Skipfile should be laid out.")

    analyzer_opts.add_argument(
        '--analyzers',
        nargs='+',
        dest='analyzers',
        metavar='ANALYZER',
        required=False,
        choices=analyzer_types.supported_analyzers,
        default=argparse.SUPPRESS,
        help="Run analysis only with the analyzers "
        "specified. Currently supported analyzers "
        "are: " + ', '.join(analyzer_types.supported_analyzers) + ".")

    analyzer_opts.add_argument('--add-compiler-defaults',
                               action='store_true',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="DEPRECATED. Always True. Retrieve "
                               " compiler-specific configuration "
                               "from the analyzers themselves, and use "
                               "them with Clang. This is used when the "
                               "compiler on the system is special, e.g. "
                               "when doing cross-compilation.")

    analyzer_opts.add_argument('--capture-analysis-output',
                               dest='capture_analysis_output',
                               action='store_true',
                               default=argparse.SUPPRESS,
                               required=False,
                               help="Store standard output and standard error "
                               "of successful analyzer invocations "
                               "into the '<OUTPUT_DIR>/success' "
                               "directory.")

    # TODO: One day, get rid of these. See Issue #36, #427.
    analyzer_opts.add_argument('--saargs',
                               dest="clangsa_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for the Clang Static "
                               "analyzer.")

    analyzer_opts.add_argument('--tidyargs',
                               dest="tidy_args_cfg_file",
                               required=False,
                               default=argparse.SUPPRESS,
                               help="File containing argument which will be "
                               "forwarded verbatim for the Clang-Tidy "
                               "analyzer.")

    analyzer_opts.add_argument('--tidy-config',
                               dest='tidy_config',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="A file in YAML format containing the "
                               "configuration of clang-tidy checkers. "
                               "The file can be dumped by "
                               "'CodeChecker analyzers --dump-config "
                               "clang-tidy' command.")

    analyzer_opts.add_argument('--timeout',
                               type=int,
                               dest='timeout',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="The amount of time (in seconds) that "
                               "each analyzer can spend, individually, "
                               "to analyze the project. If the analysis "
                               "of a particular file takes longer than "
                               "this time, the analyzer is killed and "
                               "the analysis is considered as a failed "
                               "one.")

    if host_check.is_ctu_capable():
        ctu_opts = parser.add_argument_group(
            "cross translation unit analysis arguments", """
These arguments are only available if the Clang Static Analyzer supports
Cross-TU analysis. By default, no CTU analysis is run when 'CodeChecker check'
is called.""")

        ctu_modes = ctu_opts.add_mutually_exclusive_group()

        ctu_modes.add_argument('--ctu',
                               '--ctu-all',
                               action='store_const',
                               const=[True, True],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform Cross Translation Unit (CTU) "
                               "analysis, both 'collect' and 'analyze' "
                               "phases. In this mode, the extra files "
                               "created by 'collect' are cleaned up "
                               "after the analysis.")

        ctu_modes.add_argument('--ctu-collect',
                               action='store_const',
                               const=[True, False],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform the first, 'collect' phase of "
                               "Cross-TU analysis. This phase generates "
                               "extra files needed by CTU analysis, and "
                               "puts them into '<OUTPUT_DIR>/ctu-dir'. "
                               "NOTE: If this argument is present, "
                               "CodeChecker will NOT execute the "
                               "analyzers!")

        ctu_modes.add_argument('--ctu-analyze',
                               action='store_const',
                               const=[False, True],
                               dest='ctu_phases',
                               default=argparse.SUPPRESS,
                               help="Perform the second, 'analyze' phase of "
                               "Cross-TU analysis, using already "
                               "available extra files in "
                               "'<OUTPUT_DIR>/ctu-dir'. (These files "
                               "will not be cleaned up in this mode.)")

    if host_check.is_statistics_capable():
        stat_opts = parser.add_argument_group(
            "EXPERIMENTAL statistics analysis feature arguments", """
These arguments are only available if the Clang Static Analyzer supports
Statistics-based analysis (e.g. statisticsCollector.ReturnValueCheck,
statisticsCollector.SpecialReturnValue checkers are available).""")

        stat_opts.add_argument('--stats-collect',
                               '--stats-collect',
                               action='store',
                               default=argparse.SUPPRESS,
                               dest='stats_output',
                               help="EXPERIMENTAL feature. "
                               "Perform the first, 'collect' phase of "
                               "Statistical analysis. This phase "
                               "generates extra files needed by "
                               "statistics analysis, and "
                               "puts them into "
                               "'<STATS_OUTPUT>'."
                               " NOTE: If this argument is present, "
                               "CodeChecker will NOT execute the "
                               "analyzers!")

        stat_opts.add_argument('--stats-use',
                               '--stats-use',
                               action='store',
                               default=argparse.SUPPRESS,
                               dest='stats_dir',
                               help="EXPERIMENTAL feature. "
                               "Use the previously generated statistics "
                               "results for the analysis from the given "
                               "'<STATS_DIR>'.")

        stat_opts.add_argument('--stats',
                               action='store_true',
                               default=argparse.SUPPRESS,
                               dest='stats_enabled',
                               help="EXPERIMENTAL feature. "
                               "Perform both phases of "
                               "Statistical analysis. This phase "
                               "generates extra files needed by "
                               "statistics analysis and enables "
                               "the statistical checkers. "
                               "No need to enable them explicitly.")

        stat_opts.add_argument('--stats-min-sample-count',
                               action='store',
                               default="10",
                               type=int,
                               dest='stats_min_sample_count',
                               help="EXPERIMENTAL feature. "
                               "Minimum number of samples (function call"
                               " occurrences) to be collected"
                               " for a statistics to be relevant.")

        stat_opts.add_argument('--stats-relevance-threshold',
                               action='store',
                               default="0.85",
                               type=float,
                               dest='stats_relevance_threshold',
                               help="EXPERIMENTAL feature. "
                               "The minimum ratio of calls of function "
                               "f that must have a certain property "
                               "property to consider it true for that "
                               "function (calculated as calls "
                               "with a property/all calls)."
                               " CodeChecker will warn for"
                               " calls of f do not have that property.")

    checkers_opts = parser.add_argument_group(
        "checker configuration", """
Checkers
------------------------------------------------
The analyzer performs checks that are categorized into families or "checkers".
See 'CodeChecker checkers' for the list of available checkers. You can
fine-tune which checkers to use in the analysis by setting the enabled and
disabled flags starting from the bigger groups and going inwards, e.g.
'-e core -d core.uninitialized -e core.uninitialized.Assign' will enable every
'core' checker, but only 'core.uninitialized.Assign' from the
'core.uninitialized' group. Please consult the manual for details. Disabling
certain checkers - such as the 'core' group - is unsupported by the LLVM/Clang
community, and thus discouraged.

Compiler warnings
------------------------------------------------
Compiler warnings are diagnostic messages that report constructions that are
not inherently erroneous but that are risky or suggest there may have been an
error. Compiler warnings are named 'clang-diagnostic-<warning-option>', e.g.
Clang warning controlled by '-Wliteral-conversion' will be reported with check
name 'clang-diagnostic-literal-conversion'. You can fine-tune which warnings to
use in the analysis by setting the enabled and disabled flags starting from the
bigger groups and going inwards, e.g. '-e Wunused -d Wno-unused-parameter' will
enable every 'unused' warnings except 'unused-parameter'. These flags should
start with a capital 'W' or 'Wno-' prefix followed by the waning name (E.g.:
'-e Wliteral-conversion', '-d Wno-literal-conversion'). By default '-Wall' and
'-Wextra' warnings are enabled. For more information see:
https://clang.llvm.org/docs/DiagnosticsReference.html.""")

    checkers_opts.add_argument('-e',
                               '--enable',
                               dest="enable",
                               metavar='checker/group/profile',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE USED in the analysis.")

    checkers_opts.add_argument('-d',
                               '--disable',
                               dest="disable",
                               metavar='checker/group/profile',
                               default=argparse.SUPPRESS,
                               action=OrderedCheckersAction,
                               help="Set a checker (or checker group) "
                               "to BE PROHIBITED from use in the "
                               "analysis.")

    checkers_opts.add_argument('--enable-all',
                               dest="enable_all",
                               action='store_true',
                               required=False,
                               default=argparse.SUPPRESS,
                               help="Force the running analyzers to use "
                               "almost every checker available. The "
                               "checker groups 'alpha.', 'debug.' and "
                               "'osx.' (on Linux) are NOT enabled "
                               "automatically and must be EXPLICITLY "
                               "specified. WARNING! Enabling all "
                               "checkers might result in the analysis "
                               "losing precision and stability, and "
                               "could even result in a total failure of "
                               "the analysis. USE WISELY AND AT YOUR "
                               "OWN RISK!")

    output_opts = parser.add_argument_group("output arguments")

    output_opts.add_argument('--print-steps',
                             dest="print_steps",
                             action="store_true",
                             required=False,
                             default=argparse.SUPPRESS,
                             help="Print the steps the analyzers took in "
                             "finding the reported defect.")

    logger.add_verbose_arguments(parser)
    parser.set_defaults(func=main)
Ejemplo n.º 27
0
def register_client_command_line(argument_parser):
    """ Should be used to extend the already existing arguments
    extend the argument parser with extra commands."""

    subparsers = argument_parser.add_subparsers()

    # List runs.
    listruns_parser = subparsers.add_parser('runs',
                                            formatter_class=ADHFormatter,
                                            help='Get the run data.')
    add_server_arguments(listruns_parser)
    listruns_parser.add_argument('-o',
                                 choices=['plaintext', 'json', 'csv'],
                                 default='plaintext',
                                 type=str,
                                 dest="output_format",
                                 help='Output format.')
    logger.add_verbose_arguments(listruns_parser)
    listruns_parser.set_defaults(func=handle_list_runs)

    # List results.
    listresults_parser = subparsers.add_parser('results',
                                               formatter_class=ADHFormatter,
                                               help='List results.')
    add_server_arguments(listresults_parser)
    listresults_parser.add_argument('-n',
                                    '--name',
                                    type=str,
                                    dest="name",
                                    required=True,
                                    help='Check name.')
    listresults_parser.add_argument('-s',
                                    '--suppressed',
                                    action="store_true",
                                    dest="suppressed",
                                    help='Suppressed results.')
    listresults_parser.add_argument('--filter',
                                    dest='filter',
                                    type=str,
                                    default='::',
                                    help='Filter string in the '
                                    'following format: '
                                    '<severity>:<checker_name>:<file_path>')
    listresults_parser.add_argument('-o',
                                    choices=['plaintext', 'json', 'csv'],
                                    default='plaintext',
                                    type=str,
                                    dest="output_format",
                                    help='Output format.')
    logger.add_verbose_arguments(listresults_parser)
    listresults_parser.set_defaults(func=handle_list_results)

    # List diffs.
    diff_parser = subparsers.add_parser('diff',
                                        formatter_class=ADHFormatter,
                                        help='Diff two run.')
    listresults_parser.set_defaults(func=handle_list_results)

    # List diffs.
    add_server_arguments(diff_parser)
    diff_parser.add_argument('-b',
                             '--basename',
                             type=str,
                             dest="basename",
                             required=True,
                             help='Base name.')
    diff_parser.add_argument('-n',
                             '--newname',
                             type=str,
                             dest="newname",
                             required=True,
                             help='New name.')
    diff_parser.add_argument('-s',
                             '--suppressed',
                             action="store_true",
                             dest="suppressed",
                             default=False,
                             required=False,
                             help='Show suppressed bugs.')
    diff_parser.add_argument('-o',
                             choices=['plaintext', 'json', 'csv'],
                             default='plaintext',
                             type=str,
                             dest="output_format",
                             help='Output format.')
    diff_parser.add_argument('--filter',
                             dest='filter',
                             type=str,
                             default='::',
                             help='Filter string in the '
                             'following format: '
                             '<severity>:<checker_name>:<file_path>')
    group = diff_parser.add_mutually_exclusive_group(required=True)
    group.add_argument('--new',
                       action="store_true",
                       dest="new",
                       help="Show new results.")
    group.add_argument('--unresolved',
                       action="store_true",
                       dest="unresolved",
                       help="Show unresolved results.")
    group.add_argument('--resolved',
                       action="store_true",
                       dest="resolved",
                       help="Show resolved results.")
    logger.add_verbose_arguments(diff_parser)
    diff_parser.set_defaults(func=handle_diff_results)

    # List resulttypes.
    sum_parser = subparsers.add_parser('sum',
                                       formatter_class=ADHFormatter,
                                       help='Sum results.')
    add_server_arguments(sum_parser)
    name_group = sum_parser.add_mutually_exclusive_group(required=True)
    name_group.add_argument('-n',
                            '--name',
                            nargs='+',
                            type=str,
                            dest="names",
                            help='Check name.')
    name_group.add_argument('-a',
                            '--all',
                            action='store_true',
                            dest="all_results",
                            help='All results.')

    sum_parser.add_argument('-s',
                            '--suppressed',
                            action="store_true",
                            dest="suppressed",
                            help='Suppressed results.')
    sum_parser.add_argument('--filter',
                            dest='filter',
                            type=str,
                            default='::',
                            help='Filter string in the '
                            'following format: '
                            '<severity>:<checker_name>:<source_file_path>')
    sum_parser.add_argument('-o',
                            choices=['plaintext', 'json', 'csv'],
                            default='plaintext',
                            type=str,
                            dest="output_format",
                            help='Output format.')
    logger.add_verbose_arguments(sum_parser)
    sum_parser.set_defaults(func=handle_list_result_types)

    # Delete run results.
    del_parser = subparsers.add_parser('del',
                                       formatter_class=ADHFormatter,
                                       help='Remove run results.')
    group = del_parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-n',
                       '--name',
                       nargs='+',
                       type=str,
                       dest="name",
                       help='Server port.')
    group.add_argument('--all-after-run',
                       type=str,
                       dest='all_after_run',
                       help='Delete all runs checked after this run.')
    group.add_argument('--all-before-run',
                       type=str,
                       dest='all_before_run',
                       help='Delete all runs checked before this run.')
    group.add_argument('--all-after-time',
                       type=valid_time,
                       dest='all_after_time',
                       help='Delete all runs checked after this timestamp. '
                       'The format should be year:month:day:hour:min:sec. '
                       'The last three parts can be omitted from the right '
                       'in which case the default values are 0.')
    group.add_argument('--all-before-time',
                       type=valid_time,
                       dest='all_before_time',
                       help='Delete all runs checked before this timestamp. '
                       'The format should be year:month:day:hour:min:sec. '
                       'The last three parts can be omitted from the right '
                       'in which case the default values are 0.')
    logger.add_verbose_arguments(del_parser)
    add_server_arguments(del_parser)
    del_parser.set_defaults(func=handle_remove_run_results)

    # Handle suppress file.
    suppress_parser = subparsers.add_parser('suppress',
                                            help='Handle suppress file.')
    group = suppress_parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-o',
                       '--output',
                       type=str,
                       dest='output',
                       help='Export suppress file from database.')
    group.add_argument('-i',
                       '--input',
                       type=str,
                       dest='input',
                       help='Import suppress file to database.')
    group.add_argument('--bugid',
                       type=str,
                       dest='bugid',
                       help='Suppress a specific bug by bug ID.')
    suppress_parser.add_argument('-x',
                                 action='store_true',
                                 dest='x',
                                 help='If this flag is given then the bug '
                                 'provided by --bugid will be unsuppressed.')
    suppress_parser.add_argument('-f',
                                 '--force',
                                 action='store_true',
                                 dest='force',
                                 help="By default already suppressed bugs "
                                 "can't be suppressed again unless --force "
                                 "is given.")
    suppress_parser.add_argument('-c',
                                 '--comment',
                                 type=str,
                                 dest='comment',
                                 default='',
                                 help='Comment for bug suppression. It has '
                                 'sense only when --bughash is also provided.')
    suppress_parser.add_argument('--file',
                                 type=str,
                                 dest='file',
                                 default='',
                                 help='File name in which the bug will be '
                                 'suppressed. It has sense only when '
                                 '--bugid is also provided. If this parameter '
                                 'is not given then all reports with the '
                                 '--bugid will be suppressed/unsuppressed '
                                 'regardless of the file.')
    suppress_parser.add_argument('-n',
                                 '--name',
                                 type=str,
                                 dest='name',
                                 required=True,
                                 help='Run name.')
    logger.add_verbose_arguments(suppress_parser)
    add_server_arguments(suppress_parser)
    suppress_parser.set_defaults(func=handle_suppress)

    # Handle authentication.
    auth_parser = subparsers.add_parser('login',
                                        formatter_class=ADHFormatter,
                                        help='Log in onto a '
                                        'CodeChecker server.')
    auth_parser.add_argument('-u',
                             '--username',
                             type=str,
                             dest="username",
                             required=False,
                             help='Username to use on authentication.',
                             default=getpass.getuser())
    auth_parser.add_argument('-d',
                             '--deactivate',
                             '--logout',
                             action='store_true',
                             dest='logout',
                             help='Send a logout request for the server.')
    logger.add_verbose_arguments(auth_parser)
    add_server_arguments(auth_parser)
    auth_parser.set_defaults(func=handle_auth_requests)