text: #!/usr/bin/env python3.8
  # Copyright 2018 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.
  
  import argparse
  import json
  import os
  import sys
  
  
  class Source(object):
  
      def __init__(self, name, path, file):
          self.name = name
          self.path = path
          self.file = file
  
      def __str__(self):
          return '%s[%s]' % (self.name, self.path)
  
      def __hash__(self):
          return hash((self.name, self.path))
  
      def __eq__(self, other):
          return self.name == other.name and self.path == other.path
  
  
  def get_sources(dep_files, extra_sources=None):
      # Aggregate source data from dependencies.
      sources = set()
      if extra_sources:
          sources.update(extra_sources)
      for dep in dep_files:
          with open(dep, 'r') as dep_file:
              for name, path in json.load(dep_file).items():
                  sources.add(Source(name, path, dep))
  
      # Verify duplicates.
      sources_by_name = {}
      for src in sources:
          sources_by_name.setdefault(src.name, []).append(src)
      for name, srcs in sources_by_name.items():
          if len(srcs) <= 1:
              continue
          print('Error: source "%s" has multiple paths.' % name)
          for src in srcs:
              print(' - %s (%s)' % (src.path, src.file))
          raise Exception('Could not aggregate sources')
  
      return {s.name: s.path for s in sources}
  
  
  def main():
      parser = argparse.ArgumentParser()
      name_group = parser.add_mutually_exclusive_group(required=True)
      name_group.add_argument('--name', help='Name of the current library')
      name_group.add_argument(
          '--name-file',
          help='Path to a file containing the name of the current library')
      parser.add_argument(
          '--source-dir',
          help='Path to the library\'s source directory',
          required=True)
      parser.add_argument('--sources', help='List of source files', nargs='*')
      parser.add_argument(
          '--output', help='Path to the file to generate', required=True)
      parser.add_argument(
          '--deps', help='Dependencies of the current library', nargs='*')
      args = parser.parse_args()
      if args.name:
          name = args.name
      elif args.name_file:
          with open(args.name_file, 'r') as name_file:
              name = name_file.read()
  
      current_sources = []
      if args.sources:
          # TODO(BLD-228): verify that the sources are in a single folder.
          for source in args.sources:
              current_sources.append(
                  Source(
                      os.path.join(name, source),
                      os.path.join(args.source_dir, source), args.output))
      else:
          current_sources.append(Source(name, args.source_dir, args.output))
      result = get_sources(args.deps, extra_sources=current_sources)
      with open(args.output, 'w') as output_file:
          json.dump(result, output_file, indent=2, sort_keys=True)
  
  
  if __name__ == '__main__':
      sys.exit(main())
  