# -*- coding: utf-8 -*-
# Copyright 2020 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Simple script to search a generated depgraph for package relationships.

This is meant to more quickly and easily explore a board's depgraph because it
can be generated once and reused rather than re-querying portage.

The script gives the ancestors common to all the packages (plus lists any of
the packages themselves that are in all the other packages' dependencies).
The output of that step is simply an ordered list of packages. It also
generates all the pair-wise builds-before relationships.

The depgraph used is the one generated from the
DependencyService/GetBuildDependencyGraph endpoint. Use gen_call_scripts to
easily call it. By default, this script will use the default output of the
gen_call_scripts script for the endpoint. i.e.:

$> cd ~/chromiumos/chromite/api/contrib/
$> ./gen_call_scripts --board=betty
$> ./call_scripts/dependency__get_build_dependency_graph
$> ./depgraph_common_inheritance dev-libs/libxml2 app-text/docbook-xml-dtd
"""

from __future__ import print_function

import copy
import json
import os
import sys

from chromite.lib import commandline
from chromite.lib import cros_logging as logging
from chromite.lib import osutils


assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'


def GetParser():
  """Build the argument parser."""
  parser = commandline.ArgumentParser(description=__doc__)

  default_depgraph = os.path.join(
      os.path.dirname(__file__), 'call_scripts',
      'dependency__get_build_dependency_graph_output.json')

  parser.add_argument(
      'packages',
      nargs='+',
      help='The packages to search for. They must be in the "category/package" '
           'format. At least 2 packages are required, but any number can be '
           'given.')
  parser.add_argument(
      '-d',
      '--depgraph',
      type='path',
      default=default_depgraph,
      help='The json output file containing the depgraph. By default uses the '
           'dependency__get_build_dependency_graph call_scripts output file.')
  parser.add_argument(
      '-b',
      '--backtrack',
      type=int,
      default=0,
      help='The number of layers to traverse back up the depgraph from the '
           'packages. 1 will search their immediate parents only, 2 will go '
           'through grandparents, and so on. Use 0 for unlimited, the default.')
  return parser


def _ParseArguments(argv):
  """Parse and validate arguments."""
  parser = GetParser()
  opts = parser.parse_args(argv)

  if not os.path.exists(opts.depgraph):
    parser.error('depgraph does not exist.')

  if len(opts.packages) < 2:
    parser.error('Must specify at least 2 packages.')

  opts.Freeze()
  return opts


def main(argv):
  opts = _ParseArguments(argv)

  depgraph = json.loads(osutils.ReadFile(opts.depgraph))

  # Build out the package: dependencies mapping from the depgraph.
  # Key depends on each of the values
  dependencies = {}
  for package_info in depgraph.get('depGraph', {}).get('packageDeps', []):
    pi = package_info['packageInfo']
    package = '%s/%s' % (pi['category'], pi['packageName'])

    packages = [
        '%s/%s' % (p['category'], p['packageName'])
        for p in package_info.get('dependencyPackages', [])
    ]
    dependencies[package] = set(packages)

  logging.info('Found %d packages.', len(dependencies))

  dep_lists = []
  for pkg in opts.packages:
    pkg_deps = set()
    if pkg not in dependencies:
      logging.notice('%s not found in depgraph.', pkg)
      dep_lists.append(pkg_deps)
      continue

    unprocessed = set(dependencies.get(pkg, []))
    # Include the package itself so that it will appear in the list if the
    # other packages depend on it.
    processed = {pkg}
    unlimited = not opts.backtrack
    limit = opts.backtrack if opts.backtrack else None
    while unprocessed and (limit or unlimited):
      parents = []
      for cur in unprocessed:
        if cur in processed:
          continue

        parents.extend(dependencies.get(cur, []))
        processed.add(cur)

      unprocessed = set(parents)
      if not unlimited:
        limit -= 1

    dep_lists.append(processed)

  # Combine them all into a single common list.
  common = copy.deepcopy(dep_lists[0])
  for deps in dep_lists[1:]:
    common &= deps

  if common:
    print('Common package dependencies:')
    print('\n'.join(sorted(list(common))))
  else:
    print('No common dependencies found.')

  # Find guaranteed build ordering pairs.
  # Try to find each package in the parent sets of the other packages.
  before = {pkg: [] for pkg in opts.packages}
  for pkg in opts.packages:
    others = set(opts.packages) - {pkg}
    unprocessed = set(dependencies.get(pkg, []))
    processed = set()
    while others and unprocessed:
      found = set()
      for other in others:
        if other in unprocessed:
          before[other].append(pkg)
          found.add(other)
      others = others - found
      parents = []
      for cur in unprocessed:
        if cur in processed:
          continue
        parents.extend(dependencies.get(cur, []))
        processed.add(cur)
      unprocessed = set(parents)

  # Remove cycles and build strings.
  before_strs = []
  for pkg, built_before in before.items():
    for cur in built_before:
      if pkg in before[cur]:
        continue
      before_strs.append('%s builds before %s' % (pkg, cur))

  print()
  if before_strs:
    print('Build order relations:')
    print('\n'.join(sorted(before_strs)))
  else:
    print('No guaranteed build order relations found.')
