#!/usr/bin/env vpython
# Copyright 2017 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.

"""Compares two orderfiles, from filenames or a commit.

This shows some statistics about two orderfiles, possibly extracted from an
updating commit made by the orderfile bot.
"""

import argparse
import collections
import logging
import os
import subprocess
import sys


def ParseOrderfile(filename):
  """Parses an orderfile into a list of symbols.

  Args:
    filename: (str) Path to the orderfile.

  Returns:
    [str] List of symbols.
  """
  symbols = []
  lines = []
  already_seen = set()
  with open(filename, 'r') as f:
    lines = [line.strip() for line in f]

  # The (new) orderfiles that are oriented at the LLD linker contain only symbol
  # names (i.e. not prefixed with '.text'). The (old) orderfiles aimed at the
  # Gold linker were patched by duplicating symbols prefixed with '.text.hot.',
  # '.text.unlikely.' and '.text.', hence the appearance of '.text' on the first
  # symbol indicates such a legacy orderfile.
  if not lines[0].startswith('.text.'):
    for entry in lines:
      symbol_name = entry.rstrip('\n')
      assert symbol_name != '*' and symbol_name != '.text'
      already_seen.add(symbol_name)
      symbols.append(symbol_name)
  else:
    for entry in lines:
      # Keep only (input) section names, not symbol names (only rare special
      # symbols contain '.'). We could only keep symbols, but then some even
      # older orderfiles would not be parsed.
      if '.' not in entry:
        continue
      # Example: .text.startup.BLA
      symbol_name = entry[entry.rindex('.'):]
      if symbol_name in already_seen or symbol_name == '*' or entry == '.text':
        continue
      already_seen.add(symbol_name)
      symbols.append(symbol_name)
  return symbols


def CommonSymbolsToOrder(symbols, common_symbols):
  """Returns s -> index for all s in common_symbols."""
  result = {}
  index = 0
  for s in symbols:
    if s not in common_symbols:
      continue
    result[s] = index
    index += 1
  return result


CompareResult = collections.namedtuple(
    'CompareResult', ('first_count', 'second_count',
                      'new_count', 'removed_count',
                      'average_fractional_distance'))

def Compare(first_filename, second_filename):
  """Outputs a comparison of two orderfiles to stdout.

  Args:
    first_filename: (str) First orderfile.
    second_filename: (str) Second orderfile.

  Returns:
    An instance of CompareResult.
  """
  first_symbols = ParseOrderfile(first_filename)
  second_symbols = ParseOrderfile(second_filename)
  print 'Symbols count:\n\tfirst:\t%d\n\tsecond:\t%d' % (
      len(first_symbols), len(second_symbols))
  first_symbols = set(first_symbols)
  second_symbols = set(second_symbols)
  new_symbols = second_symbols - first_symbols
  removed_symbols = first_symbols - second_symbols
  common_symbols = first_symbols & second_symbols
  # Distance between orderfiles.
  first_to_ordering = CommonSymbolsToOrder(first_symbols, common_symbols)
  second_to_ordering = CommonSymbolsToOrder(second_symbols, common_symbols)
  total_distance = sum(abs(first_to_ordering[s] - second_to_ordering[s])\
                       for s in first_to_ordering)
  # Each distance is in [0, len(common_symbols)] and there are
  # len(common_symbols) entries, hence the normalization.
  average_fractional_distance = float(total_distance) / (len(common_symbols)**2)
  print 'New symbols = %d' % len(new_symbols)
  print 'Removed symbols = %d' % len(removed_symbols)
  print 'Average fractional distance = %.2f%%' % (
      100. * average_fractional_distance)
  return CompareResult(len(first_symbols), len(second_symbols),
                       len(new_symbols), len(removed_symbols),
                       average_fractional_distance)


def CheckOrderfileCommit(commit_hash, clank_path):
  """Asserts that a commit is an orderfile update from the bot.

  Args:
    commit_hash: (str) Git hash of the orderfile roll commit.
    clank_path: (str) Path to the clank repository.
  """
  output = subprocess.check_output(
      ['git', 'show', r'--format=%an %s', commit_hash], cwd=clank_path)
  first_line = output.split('\n')[0]
  # Capitalization changed at some point.
  assert first_line.upper() == 'clank-autoroller Update Orderfile.'.upper(), (
      'Not an orderfile commit')


def GetBeforeAfterOrderfileHashes(commit_hash, clank_path):
  """Downloads the orderfiles before and afer an orderfile roll.

  Args:
    commit_hash: (str) Git hash of the orderfile roll commit.
    clank_path: (str) Path to the clank repository.

  Returns:
    (str, str) Path to the before and after commit orderfiles.
  """
  orderfile_hash_relative_path = 'orderfiles/orderfile.arm.out.sha1'
  before_output = subprocess.check_output(
      ['git', 'show', '%s^:%s' % (commit_hash, orderfile_hash_relative_path)],
      cwd=clank_path)
  before_hash = before_output.split('\n')[0]
  after_output = subprocess.check_output(
      ['git', 'show', '%s:%s' % (commit_hash, orderfile_hash_relative_path)],
      cwd=clank_path)
  after_hash = after_output.split('\n')[0]
  assert before_hash != after_hash
  return (before_hash, after_hash)


def DownloadOrderfile(orderfile_hash, output_filename):
  """Downloads an orderfile with a given hash to a given destination."""
  cloud_storage_path = (
      'gs://clank-archive/orderfile-clankium/%s' % orderfile_hash)
  subprocess.check_call(
      ['gsutil.py', 'cp', cloud_storage_path, output_filename])


def GetOrderfilesFromCommit(commit_hash):
  """Returns paths to the before and after orderfiles for a commit."""
  clank_path = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
                            'clank')
  logging.info('Checking that the commit is an orderfile')
  CheckOrderfileCommit(commit_hash, clank_path)
  (before_hash, after_hash) = GetBeforeAfterOrderfileHashes(
      commit_hash, clank_path)
  logging.info('Before / after hashes: %s %s', before_hash, after_hash)
  before_filename = os.path.join('/tmp/', before_hash)
  after_filename = os.path.join('/tmp/', after_hash)
  logging.info('Downloading files')
  DownloadOrderfile(before_hash, before_filename)
  DownloadOrderfile(after_hash, after_filename)
  return (before_filename, after_filename)


def CreateArgumentParser():
  """Returns the argumeng parser."""
  parser = argparse.ArgumentParser()
  parser.add_argument('--first', help='First orderfile')
  parser.add_argument('--second', help='Second orderfile')
  parser.add_argument('--keep', default=False, action='store_true',
                      help='Keep the downloaded orderfiles')
  parser.add_argument('--from-commit', help='Analyze the difference in the '
                      'orderfile from an orderfile bot commit.')
  parser.add_argument('--csv-output', help='Appends the result to a CSV file.')
  return parser


def main():
  logging.basicConfig(level=logging.INFO)
  parser = CreateArgumentParser()
  args = parser.parse_args()
  if args.first or args.second:
    assert args.first and args.second, 'Need both files.'
    Compare(args.first, args.second)
  elif args.from_commit:
    first, second = GetOrderfilesFromCommit(args.from_commit)
    try:
      logging.info('Comparing the orderfiles')
      result = Compare(first, second)
      if args.csv_output:
        with open(args.csv_output, 'a') as f:
          f.write('%s,%d,%d,%d,%d,%f\n' % tuple(
              [args.from_commit] + list(result)))
    finally:
      if not args.keep:
        os.remove(first)
        os.remove(second)
  else:
    return False
  return True


if __name__ == '__main__':
  sys.exit(0 if main() else 1)
