#!/usr/bin/env python

"""Helps to keep BUILD.gn files in sync with the corresponding CMakeLists.txt.

For each BUILD.gn file in the tree, checks if the list of cpp files in
it is identical to the list of cpp files in the corresponding CMakeLists.txt
file, and prints the difference if not.

Also checks that each CMakeLists.txt file below unittests/ folders that define
binaries have corresponding BUILD.gn files.

If --write is passed, tries to write modified .gn files and adds one git
commit for each cmake commit this merges. If an error is reported, the state
of HEAD is unspecified; run `git reset --hard origin/master` if this happens.
"""

from __future__ import print_function

from collections import defaultdict
import os
import re
import subprocess
import sys


def patch_gn_file(gn_file, add, remove):
    with open(gn_file) as f:
        gn_contents = f.read()
    if add:
        srcs_tok = 'sources = ['
        tokloc = gn_contents.find(srcs_tok)
        while gn_contents.startswith('sources = []', tokloc):
            tokloc = gn_contents.find(srcs_tok, tokloc + 1)
        if tokloc == -1: raise ValueError(gn_file + ': No source list')
        if gn_contents.find(srcs_tok, tokloc + 1) != -1:
            raise ValueError(gn_file + ': Multiple source lists')
        if gn_contents.find('# NOSORT', 0, tokloc) != -1:
            raise ValueError(gn_file + ': Found # NOSORT, needs manual merge')
        tokloc += len(srcs_tok)
        for a in add:
            gn_contents = (gn_contents[:tokloc] + ('"%s",' % a) +
                           gn_contents[tokloc:])
    for r in remove:
        gn_contents = gn_contents.replace('"%s",' % r, '')
    with open(gn_file, 'w') as f:
        f.write(gn_contents)

    # Run `gn format`.
    gn = os.path.join(os.path.dirname(__file__), '..', 'gn.py')
    subprocess.check_call([sys.executable, gn, 'format', '-q', gn_file])


def sync_source_lists(write):
    # Use shell=True on Windows in case git is a bat file.
    def git(args): subprocess.check_call(['git'] + args, shell=os.name == 'nt')
    def git_out(args):
        return subprocess.check_output(['git'] + args, shell=os.name == 'nt')
    gn_files = git_out(['ls-files', '*BUILD.gn']).splitlines()

    # Matches e.g. |   "foo.cpp",|, captures |foo| in group 1.
    gn_cpp_re = re.compile(r'^\s*"([^$"]+\.(?:cpp|c|h|S))",$', re.MULTILINE)
    # Matches e.g. |   bar_sources = [ "foo.cpp" ]|, captures |foo| in group 1.
    gn_cpp_re2 = re.compile(
        r'^\s*(?:.*_)?sources \+?= \[ "([^$"]+\.(?:cpp|c|h|S))" ]$',
        re.MULTILINE)
    # Matches e.g. |   foo.cpp|, captures |foo| in group 1.
    cmake_cpp_re = re.compile(r'^\s*([A-Za-z_0-9./-]+\.(?:cpp|c|h|S))$',
                              re.MULTILINE)

    changes_by_rev = defaultdict(lambda: defaultdict(lambda: defaultdict(list)))

    def find_gitrev(touched_line, in_file):
        # re.escape() escapes e.g. '-', which works in practice but has
        # undefined behavior according to the POSIX extended regex spec.
        posix_re_escape = lambda s: re.sub(r'([.[{()\\*+?|^$])', r'\\\1', s)
        cmd = ['log', '--format=%h', '-1', '--pickaxe-regex',
               r'-S\b%s\b' % posix_re_escape(touched_line), in_file]
        return git_out(cmd).rstrip()

    # Collect changes to gn files, grouped by revision.
    for gn_file in gn_files:
        # The CMakeLists.txt for llvm/utils/gn/secondary/foo/BUILD.gn is
        # at foo/CMakeLists.txt.
        strip_prefix = 'llvm/utils/gn/secondary/'
        if not gn_file.startswith(strip_prefix):
            continue
        cmake_file = os.path.join(
                os.path.dirname(gn_file[len(strip_prefix):]), 'CMakeLists.txt')
        if not os.path.exists(cmake_file):
            continue

        def get_sources(source_re, text):
            return set([m.group(1) for m in source_re.finditer(text)])
        gn_cpp = get_sources(gn_cpp_re, open(gn_file).read())
        gn_cpp |= get_sources(gn_cpp_re2, open(gn_file).read())
        cmake_cpp = get_sources(cmake_cpp_re, open(cmake_file).read())

        if gn_cpp == cmake_cpp:
            continue

        def by_rev(files, key):
            for f in files:
                rev = find_gitrev(f, cmake_file)
                changes_by_rev[rev][gn_file][key].append(f)
        by_rev(sorted(cmake_cpp - gn_cpp), 'add')
        by_rev(sorted(gn_cpp - cmake_cpp), 'remove')

    # Output necessary changes grouped by revision.
    for rev in sorted(changes_by_rev):
        print('[gn build] Port {0} -- https://reviews.llvm.org/rG{0}'
            .format(rev))
        for gn_file, data in sorted(changes_by_rev[rev].items()):
            add = data.get('add', [])
            remove = data.get('remove', [])
            if write:
                patch_gn_file(gn_file, add, remove)
                git(['add', gn_file])
            else:
                print('  ' + gn_file)
                if add:
                    print('   add:\n' + '\n'.join('    "%s",' % a for a in add))
                if remove:
                    print('   remove:\n    ' + '\n    '.join(remove))
                print()
        if write:
            git(['commit', '-m', '[gn build] Port %s' % rev])
        else:
            print()

    return bool(changes_by_rev) and not write


def sync_unittests():
    # Matches e.g. |add_llvm_unittest_with_input_files|.
    unittest_re = re.compile(r'^add_\S+_unittest', re.MULTILINE)

    checked = [ 'clang', 'clang-tools-extra', 'lld', 'llvm' ]
    changed = False
    for c in checked:
        for root, _, _ in os.walk(os.path.join(c, 'unittests')):
            cmake_file = os.path.join(root, 'CMakeLists.txt')
            if not os.path.exists(cmake_file):
                continue
            if not unittest_re.search(open(cmake_file).read()):
                continue  # Skip CMake files that just add subdirectories.
            gn_file = os.path.join('llvm/utils/gn/secondary', root, 'BUILD.gn')
            if not os.path.exists(gn_file):
                changed = True
                print('missing GN file %s for unittest CMake file %s' %
                      (gn_file, cmake_file))
    return changed


def main():
    src = sync_source_lists(len(sys.argv) > 1 and sys.argv[1] == '--write')
    tests = sync_unittests()
    if src or tests:
        sys.exit(1)


if __name__ == '__main__':
    main()
