#!/usr/bin/env python
# Copyright 2017 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Runs clang-tidy on modified files.

The tool uses `git diff-index` against the newest parent commit in the upstream
branch (or against HEAD if no such commit is found) in order to find the files
to be formatted. In result, the tool lints files that are locally modified,
staged or touched by any commits introduced on the local branch.
"""

import argparse
import multiprocessing
import os
import platform
import re
import subprocess
import sys

sys.path.append(os.path.dirname(os.path.dirname(__file__)))

import git_utils

FUCHSIA_ROOT = os.path.dirname(  # $root
    os.path.dirname(             # scripts
    os.path.dirname(             # git
    os.path.abspath(__file__))))
PREBUILT_ROOT = os.path.join(FUCHSIA_ROOT, "prebuilt/third_party")

local_os = "linux"
if platform.platform().startswith("Darwin"):
    local_os = "mac"
CLANG_TIDY_TOOL = os.path.join(PREBUILT_ROOT, "clang",
                               "%s-x64" % local_os, "bin",
                               "clang-tidy")
NINJA_TOOL = os.path.join(PREBUILT_ROOT, "ninja",
                               "%s-x64" % local_os, "ninja")

def find_ancestor_with(filepath, relpath):
    """Returns the lowest ancestor of |filepath| that contains |relpath|."""
    cur_dir_path = os.path.abspath(os.path.dirname(filepath))
    while True:
        if os.path.exists(os.path.join(cur_dir_path, relpath)):
            return cur_dir_path

        next_dir_path = os.path.dirname(cur_dir_path)
        if next_dir_path != cur_dir_path:
            cur_dir_path = next_dir_path
        else:
            return None


def get_out_dir(args):
    if args.out_dir:
        out_dir = args.out_dir

        if not os.path.isabs(out_dir):
            out_dir = os.path.join(FUCHSIA_ROOT, out_dir)

        if not os.path.isdir(out_dir):
            print out_dir + " is not a directory"
            sys.exit(-1)
        return out_dir

    fuchsia_config_file = os.path.join(FUCHSIA_ROOT, '.fx-build-dir')
    if os.path.isfile(fuchsia_config_file):
        fuchsia_config = open(fuchsia_config_file).read()
        return os.path.join(FUCHSIA_ROOT, fuchsia_config.strip())

    print("Couldn't find the output directory, pass --out-dir " +
          "(absolute or relative to Fuchsia root)")
    sys.exit(-1)


def generate_db(out_dir):
    cmd = [NINJA_TOOL, "-C", out_dir, "-t", "compdb", "cc", "cxx"]
    db = subprocess.check_output(
        cmd, cwd=FUCHSIA_ROOT, universal_newlines=True)

    # Strip away `gomacc` from the compile commands. This seems to fix problems
    # with clang-tidy not being able to load system headers.
    db = re.sub("\"/[\S]+/gomacc ", "\"", db)

    with open(os.path.join(out_dir, "compile_commands.json"), "w+") as db_file:
        db_file.write(db)


def go(args):
    out_dir = get_out_dir(args)

    # generate the compilation database
    generate_db(out_dir)

    # Find the files to be checked.
    if args.all:
        files = git_utils.get_all_files()
    else:
        files = git_utils.get_diff_files()

    filtered_files = []
    for file_path in files:
        # Skip deleted files.
        if not os.path.isfile(file_path):
            if args.verbose:
                print "skipping " + file_path + " (deleted)"
            continue

        # Skip files with parent directories containing .nolint
        if find_ancestor_with(file_path, ".nolint"):
            if args.verbose:
                print "skipping " + file_path + " (.nolint)"
            continue
        filtered_files.append(file_path)

    if args.verbose:
        print
        print "Files to be checked:"
        for file in filtered_files:
            print " - " + file
        if not filtered_files:
            print " (no files)"
        print

    # change the working directory to Fuchsia root.
    os.chdir(FUCHSIA_ROOT)

    # It's not safe to run in parallel with "--fix", as clang-tidy traverses and
    # fixes header files, and we might end up with concurrent writes to the same
    # header file.
    if args.no_parallel or args.fix:
        parallel_jobs = 1
    else:
        parallel_jobs = multiprocessing.cpu_count()
        print("Running " + str(parallel_jobs) +
              " jobs in parallel, pass --no-parallel to disable")

    jobs = set()

    for file_path in filtered_files:
        _, extension = os.path.splitext(file_path)
        if extension == ".cc":
            relpath = os.path.relpath(file_path)
            cmd = [CLANG_TIDY_TOOL, "-p", out_dir, relpath]
            if args.checks:
                cmd.append("-checks=" + args.checks)
            if args.fix:
                cmd.append("-fix")
            if not args.verbose:
                cmd.append("-quiet")

            if args.verbose:
                print "checking " + file_path + ": " + str(cmd)
            jobs.add(subprocess.Popen(cmd))
            if len(jobs) >= parallel_jobs:
                os.wait()
                jobs.difference_update(
                    [job for job in jobs if job.poll() is not None])
    for job in jobs:
        if job.poll() is None:
            job.wait()


def main():
    parser = argparse.ArgumentParser(description="Lint modified files.")
    parser.add_argument(
        "--all",
        dest="all",
        action="store_true",
        default=False,
        help="process all files in the repo under current working directory")
    parser.add_argument(
        "--fix",
        dest="fix",
        action="store_true",
        default=False,
        help="automatically generate fixes when possible")
    parser.add_argument("--checks", help="overrides the list of checks to use")
    parser.add_argument(
        "--out-dir",
        help="Output directory, needed to generate compilation db for clang.")
    parser.add_argument(
        "--no-parallel",
        action="store_true",
        default=False,
        help="Process one file at a time")
    parser.add_argument(
        "--verbose",
        dest="verbose",
        action="store_true",
        default=False,
        help="tell me what you're doing")
    args = parser.parse_args()
    go(args)

    return 0


if __name__ == "__main__":
    sys.exit(main())
