Ejemplo n.º 1
0
    def process_file(filepath):
        nonlocal patch
        nonlocal file_scan_count
        nonlocal file_change_count
        nonlocal ARGS

        ext = file_ext(filepath)
        if ext not in formatters_by_ext:
            return
        formatter = formatters_by_ext[ext]

        create_patch = ARGS.output_patch_file != None
        needed_formatting, patch_partial = formatter.run(
            ARGS, filepath, ARGS.check, create_patch)

        # concatenate all patches together
        if ARGS.output_patch_file and needed_formatting:
            patch += patch_partial + "\n"

        file_scan_count += 1
        if needed_formatting:
            file_change_count += 1

            status = "✗" if ARGS.check else "✔"
            print_aligned(filepath, status)
        else:
            print_aligned("> %s: %s" % (ext[1:], filepath),
                          "[%d]" % file_scan_count,
                          end="\r")
Ejemplo n.º 2
0
def main():
    file_scan_count = file_change_count = 0

    # Command line options
    parser = argparse.ArgumentParser(
        description="Format and checkstyle C++ and Python code")
    parser.add_argument(
        "--check",
        action='store_true',
        help=
        "Determine if all code is in accordance with the style configs, but don't fix them if they're not. A nonzero exit code indicates that some files don't meet the style requirements.")
    parser.add_argument("--exclude_dirs",
                        type=str,
                        default=[],
                        nargs="+",
                        help="A list of directories to exclude")
    parser.add_argument(
        "--output_patch_file",
        type=str,
        default=None,
        help=
        "If specified, a patch file is generated at the given path that, when aplied to the project, will fix all style mistakes.")
    parser.add_argument(
        "--diffbase",
        help=
        "The git branch/tag/SHA1 to compare against.  If provided, only files that have changed since the diffbase will be scanned.")
    parser.add_argument("--version",
                        action='store_true',
                        help="Print version and exit.")

    formatters = [ClangFormatter(), YapfFormatter()]

    # register any formatter-specific arguments
    formatters_by_ext = {}
    for formatter in formatters:
        if formatter.get_command() == None:
            print(
                "[ERR] A required dependency was not found. Check to see if clang-format is available on your path.")
            return 1
        formatter.add_args(parser)
        for ext in formatter.file_extensions:
            formatters_by_ext[ext] = formatter

    ARGS = parser.parse_args()

    ARGS.exclude_dirs = [os.path.abspath(p) for p in ARGS.exclude_dirs
                         ] + [os.path.abspath('.git')]

    # version command
    if ARGS.version:
        print("stylize %s" % __version__)
        exit(0)

    # Print initial status info
    verb = "Checkstyling" if ARGS.check else "Formatting"
    if ARGS.diffbase:
        # A diffbase was given, so we run a git diff to see which files have
        # changed relative to the diffbase and only reformat those.  If a
        # formatter's config file has changed, we add all relevant files to the
        # list to format/checkstyle.

        print("%s files that differ from %s..." % (verb, ARGS.diffbase))

        changed_files = list(enumerate_changed_files(ARGS.exclude_dirs,
                                                     ARGS.diffbase))

        files_to_format = changed_files

        # Build a set of file extensions for which the config file has been modified.
        exts_requiring_full_reformat = set()
        for formatter in formatters:
            if formatter.config_file_name in changed_files:
                print(
                    "Config file '%s' changed.  %s all files with extensions: %s"
                    % (formatter.config_file_name, verb,
                       str(formatter.file_extensions)))
                exts_requiring_full_reformat |= set(formatter.file_extensions)

        if len(exts_requiring_full_reformat) > 0:
            files_with_relevant_extensions = filter(
                lambda file: file_ext(file) in exts_requiring_full_reformat,
                enumerate_all_files(ARGS.exclude_dirs))
            # use set() to eliminate any duplicates
            files_to_format = set(chain(changed_files,
                                        files_with_relevant_extensions))
    else:
        print("%s all c++ and python files in the project..." % verb)
        files_to_format = enumerate_all_files(ARGS.exclude_dirs)

    # This variable holds the final patch
    patch = ""

    def process_file(filepath):
        nonlocal patch
        nonlocal file_scan_count
        nonlocal file_change_count
        nonlocal ARGS

        ext = file_ext(filepath)
        if ext not in formatters_by_ext:
            return
        formatter = formatters_by_ext[ext]

        create_patch = ARGS.output_patch_file != None
        needed_formatting, patch_partial = formatter.run(
            ARGS, filepath, ARGS.check, create_patch)

        # concatenate all patches together
        if ARGS.output_patch_file and needed_formatting:
            patch += patch_partial + "\n"

        file_scan_count += 1
        if needed_formatting:
            file_change_count += 1

            status = "✗" if ARGS.check else "✔"
            print_aligned(filepath, status)
        else:
            print_aligned("> %s: %s" % (ext[1:], filepath),
                          "[%d]" % file_scan_count,
                          end="\r")

    # Use all the cores!
    workers = ThreadPool()
    workers.map(process_file, files_to_format)

    # Print final stats
    if ARGS.check:
        print_aligned("[%d / %d] files need formatting" %
                      (file_change_count, file_scan_count), "")
        retcode = 0 if file_change_count == 0 else 1
    else:
        print_aligned("[%d / %d] files formatted" %
                      (file_change_count, file_scan_count), "")
        retcode = 0

    if ARGS.output_patch_file:
        if file_change_count > 0:
            print("Writing patch to file: '%s'" % ARGS.output_patch_file)
            with open(ARGS.output_patch_file, 'w') as patchfile:
                patchfile.write(patch)
        else:
            print(
                "Skipping patch file generation, all files are style-compliant.")

    return retcode