#!/usr/bin/env python
# Copyright (c) 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Helper script for PPAPI's PRESUBMIT.py to detect if additions or removals of
PPAPI interfaces have been propagated to the Native Client libraries (.dsc
files).

For example, if a user adds "ppapi/c/foo.h", we check that the interface has
been added to "native_client_sdk/src/libraries/ppapi/library.dsc".
"""

import argparse
import os
import sys

from build_paths import PPAPI_DIR, SRC_DIR, SDK_LIBRARY_DIR
import parse_dsc


# Add a file to this list if it should not be added to a .dsc file; i.e. if it
# should not be included in the Native Client SDK. This will silence the
# presubmit warning.
#
# Some examples of files that should not be added to the SDK are: Dev and
# Private interfaces that are either not available to NaCl plugins or are only
# available to Flash or other privileged plugins.
IGNORED_FILES = set([
  'pp_video_dev.h',
])


class VerifyException(Exception):
  def __init__(self, lib_path, expected, unexpected):
    self.expected = expected
    self.unexpected = unexpected

    msg = 'In %s:\n' % lib_path
    if expected:
      msg += '  these files are missing and should be added:\n'
      for filename in sorted(expected):
        msg += '    %s\n' % filename
    if unexpected:
      msg += '  these files no longer exist and should be removed:\n'
      for filename in sorted(unexpected):
        msg += '    %s\n' % filename

    Exception.__init__(self, msg)


def PartitionFiles(filenames):
  c_filenames = set()
  cpp_filenames = set()
  private_filenames = set()

  for filename in filenames:
    if os.path.splitext(filename)[1] not in ('.cc', '.h'):
      continue

    parts = filename.split(os.sep)
    basename = os.path.basename(filename)
    if basename in IGNORED_FILES:
      continue

    if 'private' in filename:
      if 'flash' in filename:
        continue
      private_filenames.add(filename)
    elif parts[0:2] == ['ppapi', 'c']:
      if len(parts) >= 2 and parts[2] in ('documentation', 'trusted'):
        continue
      c_filenames.add(filename)
    elif (parts[0:2] == ['ppapi', 'cpp'] or
          parts[0:2] == ['ppapi', 'utility']):
      if len(parts) >= 2 and parts[2] in ('documentation', 'trusted'):
        continue
      cpp_filenames.add(filename)
    else:
      continue

  return {
      'ppapi': c_filenames,
      'ppapi_cpp': cpp_filenames,
      'ppapi_cpp_private': private_filenames
  }


def GetDirectoryList(directory_path, relative_to):
  result = []
  for root, _, files in os.walk(directory_path):
    rel_root = os.path.relpath(root, relative_to)
    if rel_root == '.':
      rel_root = ''
    for base_name in files:
      result.append(os.path.join(rel_root, base_name))
  return result


def GetDscSourcesAndHeaders(dsc):
  result = []
  for headers_info in dsc.get('HEADERS', []):
    result.extend(headers_info['FILES'])
  for targets_info in dsc.get('TARGETS', []):
    result.extend(targets_info['SOURCES'])
  return result


def GetChangedAndRemovedFilenames(modified_filenames, directory_list):
  changed = set()
  removed = set()
  directory_list_set = set(directory_list)
  for filename in modified_filenames:
    if filename in directory_list_set:
      # We can't know if a file was added (that would require knowing the
      # previous state of the working directory). Instead, we assume that a
      # changed file may have been added, and check it accordingly.
      changed.add(filename)
    else:
      removed.add(filename)
  return changed, removed


def GetDscFilenameFromLibraryName(lib_name):
  return os.path.join(SDK_LIBRARY_DIR, lib_name, 'library.dsc')


def Verify(dsc_filename, dsc_sources_and_headers, changed_filenames,
           removed_filenames):
  expected_filenames = set()
  unexpected_filenames = set()

  for filename in changed_filenames:
    basename = os.path.basename(filename)
    if basename not in dsc_sources_and_headers:
      expected_filenames.add(filename)

  for filename in removed_filenames:
    basename = os.path.basename(filename)
    if basename in dsc_sources_and_headers:
      unexpected_filenames.add(filename)

  if expected_filenames or unexpected_filenames:
    raise VerifyException(dsc_filename, expected_filenames,
                          unexpected_filenames)


def VerifyOrPrintError(dsc_filename, dsc_sources_and_headers, changed_filenames,
                       removed_filenames, is_private=False):
  try:
    Verify(dsc_filename, dsc_sources_and_headers, changed_filenames,
           removed_filenames)
  except VerifyException as e:
    should_fail = True
    if is_private and e.expected:
      # For ppapi_cpp_private, we don't fail if there are expected filenames...
      # we may not want to include them. We still want to fail if there are
      # unexpected filenames, though.
      sys.stderr.write('>>> WARNING: private interface files changed. '
          'Should they be added to the Native Client SDK? <<<\n')
      if not e.unexpected:
        should_fail = False
    sys.stderr.write(str(e) + '\n')
    if should_fail:
      return False
  return True


def main(args):
  parser = argparse.ArgumentParser(description=__doc__)
  parser.add_argument('sources', nargs='+')
  options = parser.parse_args(args)

  retval = 0
  lib_files = PartitionFiles(options.sources)
  directory_list = GetDirectoryList(PPAPI_DIR, relative_to=SRC_DIR)
  for lib_name, filenames in lib_files.iteritems():
    if not filenames:
      continue

    changed_filenames, removed_filenames = \
        GetChangedAndRemovedFilenames(filenames, directory_list)

    dsc_filename = GetDscFilenameFromLibraryName(lib_name)
    dsc = parse_dsc.LoadProject(dsc_filename)
    dsc_sources_and_headers = GetDscSourcesAndHeaders(dsc)

    # Use the relative path to the .dsc to make the error messages shorter.
    rel_dsc_filename = os.path.relpath(dsc_filename, SRC_DIR)
    is_private = lib_name == 'ppapi_cpp_private'
    if not VerifyOrPrintError(rel_dsc_filename, dsc_sources_and_headers,
                              changed_filenames, removed_filenames,
                              is_private=is_private):
      retval = 1
  return retval


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