#!/usr/bin/env python3.8
# Copyright 2020 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.
'''Reads the contents of a manifest file generated by the build and verifies
   that there are no collisions among destination paths.
   '''

import argparse
import collections
import filecmp
import functools
import json
import sys

Entry = collections.namedtuple('Entry', ['source', 'destination', 'label'])

# List of destination paths for which conflicting entries are acceptable as long
# as the source files are identical.
# This is mostly use to soft-transition zbi contents.
DUPLICATION_EXCEPTIONS = []


def expand(items):
    '''Reads metadata produced by GN.
       Expands and flattens file references found within that metadata.
       See distribution_manifest.gni for a description of the metadata format.
       Also returns a list of files opened.
       '''
    entries = []
    opened_files = []
    for item in items:
        if 'source' in item:
            entries.append(item)
        elif 'file' in item:
            with open(item['file'], 'r') as data_file:
                opened_files.append(item['file'])
                data = json.load(data_file)
            for entry in data:
                entry['label'] = item['label']
                items.append(entry)
    return [Entry(**e) for e in entries], opened_files


def sources_are_different(entries):
    '''Returns true if the given entries do not all point to identical source
       files.'''
    sources = [entry.source for entry in entries]
    return any(not filecmp.cmp(sources[0], f) for f in sources[1:])


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        '--input', help='Path to original manifest', required=True)
    parser.add_argument(
        '--output', help='Path to the updated manifest', required=True)
    parser.add_argument(
        '--depfile', help='Path to GN style depfile', required=True)
    args = parser.parse_args()

    with open(args.input, 'r') as input_file:
        contents = json.load(input_file)

    entries, opened_files = expand(contents)
    entries_by_dest = {
        d: set(e for e in entries if e.destination == d) for d in set(
            e.destination for e in entries)
    }
    with open(args.depfile, 'w+') as depfile:
        depfile.write('%s: %s\n' % (args.output, ' '.join(opened_files)))

    # Filter entries for which is is ok to have duplication if the sources are
    # the same.
    for exception in DUPLICATION_EXCEPTIONS:
        if not exception in entries_by_dest:
            continue
        duplicates = list(entries_by_dest[exception])
        if sources_are_different(duplicates):
            # Treat this as a normal conflict.
            continue
        # This is an exception! Select the first entry as canon, and remove
        # the others.
        canon = duplicates[0]
        entries_by_dest[exception] = set([canon])
        for entry in duplicates[1:]:
            entries.remove(entry)

    conflicts = {d: e for d, e in entries_by_dest.items() if len(e) > 1}
    # Only report a conflict if the source files differ.
    # TODO(fxbug.dev/45680): remove this additional filtering when dependency trees are
    # cleaned up and //build/package.gni has gone the way of the dodo.
    conflicts = {
        d: e
        for d, e in conflicts.items()
        if len(set(entry.source for entry in e)) >= 2
    }
    if conflicts:
        for destination in conflicts:
            print('Conflicts for path ' + destination + ':')
            for conflict in conflicts[destination]:
                print(' - ' + conflict.source)
                print('   from ' + conflict.label)
        print('Error: conflicting distribution entries!')
        return 1

    with open(args.output, 'w') as output_file:
        json.dump(
            [e._asdict() for e in sorted(entries)],
            output_file,
            indent=2,
            sort_keys=True,
            separators=(',', ': '))

    return 0


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