#!/usr/bin/env python3.8
# Copyright 2021 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.
"""Determines the files that needed to be rebuilt by fx ninja.

The primary use of this script is to find which build targets were changed
by a particular CL or patch for use by the clang static analyzer.

The input will most likely be the compile_commands.json generated by either
an `fx set` or `fx gn gen --export-compile-commands=default <OUT_DIR>`.

The output is a json file containing the translation units (TUs) taken
from the input compile_commands.json of which the build targets were
modified by a fx ninja call.

The expectated workflow is:
  1. Check out the base fuchsia commit against which to apply the patch.
  1. Run `fx build`.
  1. Apply the patch.
  1. Run this script.
  1. Run analyze-build against the output of this script.
"""
import argparse
import json
import os
import subprocess
import sys
import tempfile
import time

import helper as color


def main(input_args):
  parser = argparse.ArgumentParser(
      description=
      'Runs `fx ninja build` on a set of targets for compile translation units '
      'and determines which files were modified since that change.')
  parser.add_argument(
      '-i',
      '--input',
      required=True,
      help='The path of a compile_commands.json generated '
      'by either `fx set` or `fx gn gen '
      '--export-compile-commands=default <OUT_DIR>`')
  parser.add_argument(
      '-o',
      '--output',
      required=True,
      help=
      'The path to write the output file of an array of paths for modified files in JSON format.'
  )
  parser.add_argument(
      '-n',
      '--ninja',
      required=True,
      help=
      'Path to the prebuilt ninja compiler.'
  )
  args = parser.parse_args(input_args)

  with open(args.input) as compile_commands:
    res = ninja_build_tu(json.load(compile_commands), args.ninja)

    if not res:
      print(color.white('Did not find any changed files.'))

    with open(args.output, 'w') as out:
      json.dump(res, out, indent=2)

    print(color.white('Wrote to output file'), color.yellow(args.output))
  return 0


def ninja_build_tu(compdb, ninja_path):
  """Find build targets that were modified since last build.

  Attemps to build all build targets specified, returning the subset
  of those that require a rebuild since the last build. Leverages `fx
  ninja` in order to determine which build targets needed rebuilding.

  Args:
      compdb: A json-style list containing dictionary-like entries
              for each translation unit.
      ninja_path: Path to the ninja executable.

  Returns:
      A subset of the input compdb, only keeping the translation units
      that correspond to build targets that had been modified by the
      `ninja` call.
  """
  files = {}
  tus = {}
  # Find all TU targets
  for tu in compdb:
    directory = tu['directory']
    command = tu['command']
    command_entries = command.split()

    # Gather all targets in this TU
    for i in range(0, len(command_entries) - 1):
      if command_entries[i] != '-o':
        continue

      target = command_entries[i + 1]

      if directory not in files:
        files[directory] = []

      files[directory].append(target)

      # Store TU for reverse lookup later
      target_path = os.path.join(directory, target)
      if target_path not in tus:
        tus[target_path] = []
      tus[target_path].append(tu)

  modified_files = [process_tu_dir_xargs(directory, files[directory],
                                         ninja_path) for directory in files]

  # Find all TUs that match modified files
  out_tus = []
  for files in modified_files:
    for target in files:
      if target in tus:
        out_tus.extend(tus[target])
      else:
        sys.exit('Expected %s to exist in reverse lookup dict.'%(target))
  return out_tus


def process_tu_dir_xargs(directory, build_targets, ninja_path):
  """Find build targets that were rebuilt.

  Takes an input directory (corresponding to the -C option in fx ninja) and
  a list of build targets. Based on system modified time, returns the list
  of build targets that have a new modified time.

  Args:
      directory: The string path name correpsonding to the build_targets.
      build_targets: A list of build targets to attempt to build.
      ninja_path: Path to the ninja executable.

  Returns:
      The subset of build_targets which were modified by `ninja`.
  """
  # Write targets to a temp file
  with tempfile.NamedTemporaryFile(mode='w') as fp:
    for f in build_targets:
      fp.write('%s\n' % (f))
    fp.flush()
    filename = os.path.realpath(fp.name)

    # The argument list may exceed the input buffer, so we use xargs to
    # call fx ninja multiple times, each with a subset of the arguments
    # commands = ['xargs', '-a', filename, 'fx', 'ninja', '-C', directory]
    commands = ['xargs', '-a', filename, ninja_path, '-C', directory]

    # Record the time before running fx ninja
    before = time.time()
    print(color.white('Running command'), color.yellow(' '.join(commands)))

    try:
      subprocess.run(commands, capture_output=True, check=True)
    except subprocess.CalledProcessError as err:
      print(color.red('Failed with exit code'), color.white(err.returncode))
      print(color.red(err.stderr))
      sys.exit('Error in fx ninja.')

  # Find all files that have a newer modified time than `before`
  modified_targets = []
  for file in build_targets:
    file_path = os.path.join(directory, file)
    if not os.path.isfile(file_path):
      continue
    mtime = os.path.getmtime(file_path)
    if mtime > before:
      modified_targets.append(file_path)

  return modified_targets


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
