#!/usr/bin/env python3
# pylint: disable=line-too-long, subprocess-run-check, unused-argument
# Copyright 2021 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.
"""Convert Cargo metadata to ebuilds using cros-rust.

Used to add new Rust projects and building up ebuilds for the dependency tree.
"""

import argparse
from collections import defaultdict
from datetime import datetime
import json
import logging
import os
from pprint import pprint
import re
import shutil
import subprocess
import sys

SCRIPT_NAME = 'cargo2ebuild.py'
AUTOGEN_NOTICE = '\n# This file was automatically generated by {}'.format(
    SCRIPT_NAME)

CRATE_DL_URI = 'https://crates.io/api/v1/crates/{PN}/{PV}/download'

# Required parameters
#   copyright_year: Current year for copyright assignment.
#   description: Description of the crates.
#   homepage: Homepage of the crates.
#   license: Ebuild compatible license string.
#   dependencies: Ebuild compatible dependency string.
#   autogen_notice: Autogenerated notification string.
EBUILD_TEMPLATE = (
  """# Copyright {copyright_year} The Chromium OS Authors. All rights reserved.
# Distributed under the terms of the GNU General Public License v2

EAPI="7"

CROS_RUST_REMOVE_DEV_DEPS=1{remove_target_var}

inherit cros-rust

DESCRIPTION='{description}'
HOMEPAGE='{homepage}'
SRC_URI="https://crates.io/api/v1/crates/${{PN}}/${{PV}}/download -> ${{P}}.crate"

LICENSE="{license}"
SLOT="${{PV}}/${{PR}}"
KEYWORDS="*"

{dependencies}{autogen_notice}
""")

# Required parameters:
#   copyright_year: Current year for copyright assignment.
#   crate_features: Features to add to this empty crate.
#   autogen_notice: Autogenerated notification string.
EMPTY_CRATE = (
  """# Copyright {copyright_year} The Chromium OS Authors. All rights reserved.
# Distributed under the terms of the GNU General Public License v2

EAPI="7"

CROS_RUST_EMPTY_CRATE=1
{crate_features}
inherit cros-rust

DESCRIPTION="Empty crate"
HOMEPAGE=""

LICENSE="BSD-Google"
SLOT="${{PV}}/${{PR}}"
KEYWORDS="*"
{autogen_notice}
""")

LICENSES = {
    'Apache-2.0': 'Apache-2.0',
    'MIT': 'MIT',
    'BSD-2-Clause': 'BSD-2',
    'BSD-3-Clause': 'BSD',
    '0BSD': '0BSD',
    'ISC': 'ISC',
}

VERSION_RE = (
    '^(?P<dep>([\\^~=]|>=))?'  # Dependency type: ^, ~, =, >=
    '(?P<major>[0-9]+|[*])'  # Major version (can be *)
    '(.(?P<minor>[0-9]+|[*]))?'  # Minor version
    '(.(?P<patch>[0-9]+|[*]))?'  # Patch version
    '([+\\-].*)?$'  # Any semver values beyond patch version
)

EBUILD_RE = (
    '^(?P<name>[-a-zA-Z0-9_]+)?'  # Ebuild name
    '-(?P<version>[0-9]+(.[0-9]+)?(.[0-9]+)?)'
    '([-_].*)?\\.ebuild$'  # Any semver values beyond patch version
)

FEATURES_RE = (
    '^CROS_RUST_EMPTY_CRATE_FEATURES=\\('
    '(?P<features>([^)]|$)*)'  # Features array
    '\\)'
)

DEP_GRAPH_ROOT = '*root*'


class VersionParseError(Exception):
    """Error that is returned when parsing a version fails."""


class VersionRange:
    """Represents a range of Rust crate versions."""
    @staticmethod
    def from_str(value):
        """Generate a VersionRange from a crate requirement string."""
        if value == '*':
            return VersionRange(v_min=(0, 0, 0))

        v_min = None
        v_min_inclusive = True
        v_max = None
        v_max_inclusive = False

        # Handle a pair of constraints.
        parts = value.split(', ')
        if len(parts) == 2:
            for part in parts:
                if part.startswith('>='):
                    dep, major, minor, patch = version_to_tuple(part[2:], missing=0)
                    v_min = (major, minor, patch)
                elif part.startswith('<='):
                    v_max_inclusive = True
                    dep, major, minor, patch = version_to_tuple(part[2:], missing=0)
                    v_max = (major, minor, patch)
                elif part.startswith('>'):
                    v_min_inclusive = False
                    dep, major, minor, patch = version_to_tuple(part[1:], missing=0)
                    v_min = (major, minor, patch)
                elif part.startswith('<'):
                    dep, major, minor, patch = version_to_tuple(part[1:], missing=0)
                    v_max = (major, minor, patch)
                if v_max and v_min and v_max < v_min:
                    raise VersionParseError
        # We are not going to worry about more than two constraints until we see it.
        elif len(parts) != 1:
            raise VersionParseError(
                'Version constraint has more than two parts: {}'.format(parts))
        # Handle the typical case of a single constraint operator.
        else:
            dep, major, minor, patch = version_to_tuple(value, missing=-1)
            v_min = (major, minor, patch)

            if dep == '=':
                v_max = v_min
                v_max_inclusive = True
            elif dep == '~':
                major = max(v_min[0], 0)
                minor = max(v_min[1], 0)
                patch = max(v_min[2], 0)
                if v_min[0] < 0:
                    raise VersionParseError(
                        'The ~ constraint operator requires a major version: {}'.format(value))
                if v_min[1] < 0 and v_min[2] < 0:
                    v_max = (major + 1, 0, 0)
                else:
                    v_max = (major, minor + 1, 0)
                v_min = (major, minor, patch)
            elif dep == '>=':
                major = max(v_min[0], 0)
                minor = max(v_min[1], 0)
                patch = max(v_min[2], 0)
                v_min = (major, minor, patch)
                v_min_inclusive = True
                v_max = None
            elif dep and dep != '^':
                raise VersionParseError('Unrecognized operator: "{}"'.format(dep))
            else:
                major = max(v_min[0], 0)
                minor = max(v_min[1], 0)
                patch = max(v_min[2], 0)

                v_min = (major, minor, patch)
                if major > 0:
                    v_max = (major + 1, 0, 0)
                elif minor > 0:
                    v_max = (0, minor + 1, 0)
                else:
                    v_max_inclusive = True
                    v_max = v_min

        return VersionRange(v_min=v_min, v_min_inclusive=v_min_inclusive, v_max=v_max,
                            v_max_inclusive=v_max_inclusive)

    def __init__(self, v_min=None, v_min_inclusive=True, v_max=None, v_max_inclusive=False):
        self.min = v_min
        self.min_inclusive = v_min_inclusive
        self.max = v_max
        self.max_inclusive = v_max_inclusive

    def contains(self, version):
        """Returns `True` if version is inside the range; `False` otherwise.

        Args:
            version: Can be either a tuple of integers (major, minor, patch) or a string that will be converted to a
                tuple of integers. Trailing characters will be removed from the version (e.g. "+openssl-1.0.1").
        """
        if isinstance(version, str):
            try:
                filtered_version = re.sub(r'([0-9]+\.[0-9]+\.[0-9]+)[^0-9].*$', r'\1', version)
                if filtered_version != version:
                    logging.warning('Filtered version "%s" to "%s"', version, filtered_version)
                version = tuple([int(a) for a in filtered_version.split('.')])
            except Exception as e:
                print(version)
                raise e

        if self.min:
            if self.min_inclusive:
                if self.min > version:
                    return False
            elif self.min >= version:
                return False
        if self.max:
            if self.max_inclusive:
                if self.max < version:
                    return False
            elif self.max <= version:
                return False
        return True

    def to_ebuild_str(self, category_and_name):
        """Return an ebuild DEPEND entry equivalent to the range.

        Args:
            category_and_name: A string of the form 'dev-rust/crate-name' where 'dev-rust' is the category and
                'crate-name' is the name of the ebuild.

        Returns:
            A string that can be used in an ebuild's DEPEND field.
        """
        if not self.min or self.min == (0, 0, 0) and not self.max:
            return '{}:='.format(category_and_name)

        min_bound = '>=' if self.min_inclusive else '>'
        if self.max_inclusive:
            max_bound = '<='
            suffix = ''
        else:
            max_bound = '<'
            # The _alpha suffix is needed because pre-release versions are treated as less than the actual release
            # by portage so 3.0.0_beta2 is treated as less than 3.0.0. Consequently, 3.0.0_beta2 may satisfy the
            # requirement >=2.0.1:= <3.0.0 for portage but not meet the requirement for cargo. Adding the _alpha
            # suffix covers this edge case.
            suffix = '_alpha'
        if not self.max:
            return '{}{}-{}.{}.{}:='.format(min_bound, category_and_name, self.min[0], self.min[1],
                                            self.min[2])

        for x in range(len(self.min)):
            if self.min[x] != self.max[x]:
                break
        else:
            # We want to allow revisions other than -r0, so use `~` instead of `=`.
            return '~{}-{}.{}.{}:='.format(category_and_name, self.min[0], self.min[1],
                                           self.min[2])

        if self.min_inclusive and not self.max_inclusive and self.min[x] + 1 == self.max[x]:
            if x == 0 and self.min[1] == 0 and self.min[2] == 0:
                return '={}-{}*:='.format(category_and_name, self.min[0])
            if x == 1 and self.min[2] == 0:
                return '={}-{}.{}*:='.format(category_and_name, self.min[0], self.min[1])

        # The slot operator needs to be on the upper bound (b/199734226) otherwise the depgraph operation pulls in the
        # wrong slot for the lower bound that may violate the upper bound. This issue shows up in the DEPEND string for
        # binary packages.
        return '{0}{1}-{2}.{3}.{4} {5}{1}-{6}.{7}.{8}{9}:='.format(
            min_bound, category_and_name, self.min[0], self.min[1], self.min[2],
            max_bound, self.max[0], self.max[1], self.max[2], suffix)


class DepGraphNode:
    """A node in the dep-graph for a specific version of a package used by DepGraph."""
    def __init__(self, package):
        self.package = package
        self.dependencies = []

    def __repr__(self):
        return '{}'.format([(a['name'], a['req']) for a in self.dependencies])

    def add_dependency(self, dep):
        """Adds a dependency to the list."""
        self.dependencies.append(dep)


class DepGraph:
    """A model of the dependency relationships between crates.

    The functionality this provides over using the Cargo metadata directly is:
    * Filtering based on cros-rust.eclass features.
    * Tracking of system ebuilds for detecting edge cases such as:
        * Already fulfilled dependencies.
        * Optional crates that would replace or supersede non-empty ebuilds.
        * Empty crates that are missing definitions for required features.
    """
    def __init__(self):
        # name -> version -> DepGraphNode
        self.graph = defaultdict(dict)

        # name -> version -> None or [features]
        self.system_crates = defaultdict(dict)

        # The crate that will be initially checked when flattening the depgraph into a list of required and optional
        # crates.
        self.roots = []

    def add_package(self, package):
        """Add a crate to the dependency graph from a parsed metadata.json generated by cargo.

        Args:
            package: A parsed package from the Cargo metadata.

        Returns:
            filter_target: True if CROS_RUST_REMOVE_TARGET_CFG=1 should be set in the ebuild.
            deps: A list of dependencies from the Cargo metadata JSON that still apply after filtering.
        """
        dependencies = package['dependencies']

        # Check if there are target specific dependencies and if so if they can be handled by
        # CROS_RUST_REMOVE_TARGET_CFG. This requires that there not be complicated cfg blocks since the cros-rust eclass
        # only applies simplistic filtering.
        has_filterable_target = False
        has_unfilterable_target = False
        for dep in dependencies:
            # Skip all dev dependencies. We will still handle normal and build deps.
            if dep.get('kind', None) == 'dev':
                continue

            target = dep.get('target', None)
            if target is None:
                continue

            if target_applies_to_chromeos(target):
                continue

            if not target_is_filterable(target):
                logging.debug('target "%s" is unfilterable.', target)
                has_unfilterable_target = True
            else:
                has_filterable_target = True
        if has_unfilterable_target:
            logging.warning('"%s-%s" might benefit from better target specific dependency filtering',
                            package['name'], package['version'])
        filter_target = has_filterable_target and not has_unfilterable_target

        graph_node = DepGraphNode(package)
        self.graph[package['name']][package['version']] = graph_node

        # Check each dependency and add it if it is relevant to Chrome OS.
        deps = []
        for dep in dependencies:
            # Skip all dev dependencies. We will still handle normal and build deps.
            if dep.get('kind', None) == 'dev':
                continue

            # Skip filterable configuration dependant dependencies.
            target = dep.get('target', None)
            if filter_target and target is not None and not target_applies_to_chromeos(target):
                continue

            graph_node.add_dependency(dep)
            deps.append(dep)
        return filter_target, deps

    def find_system_crates(self, target_dir, names=None):
        """Take note of crates already present in the target directory.

        Args:
            target_dir: The overlay directory where the ebuilds exist.
            names: A list of package names to check. If unspecified all the crates present in the DepGraph are checked.
        """
        if names is None:
            names = self.graph

        for name in names:
            # Skip if we have already done this crate.
            if name in self.system_crates:
                continue
            available = self.system_crates[name]

            # Check if an empty package already has a non-empty ebuild.
            ebuild_target_dir = get_ebuild_dir(name, target_dir)

            # Find all ebuilds in ebuild_target dir and if they have
            # CROS_RUST_EMPTY_CRATE in them, check if features are set.
            for root, _, files in os.walk(ebuild_target_dir):
                files.sort()
                for efile in files:
                    if not efile.endswith('.ebuild'):
                        continue
                    efile_path = os.path.join(root, efile)

                    m = re.match(EBUILD_RE, efile)
                    if not m or m.group('name') != name:
                        logging.warning("Found misplaced ebuild: '%s'.", efile_path)
                        continue

                    version = m.group('version')

                    with open(efile_path, 'r') as ebuild:
                        contents = ebuild.read()
                        if 'CROS_RUST_EMPTY_CRATE' not in contents:
                            features = None
                        else:
                            m = re.search(FEATURES_RE, contents, re.MULTILINE)
                            if m:
                                sanitized = re.sub('[^a-zA-Z0-9_ \t\n-]+', '', m.group('features'))
                                features = set(a.strip() for a in sanitized.split() if a)
                            else:
                                features = set()
                    logging.debug("Found ebuild: '%s'.", efile_path[len(target_dir):])
                    available[version] = features

    def add_root(self, package):
        """Add a root of the dependency graph used when flattening the graph into a list of dependencies."""
        self.roots.append(package)

    def resolve_version_range(self, name, version_range):
        """Find a dependency graph entry that fits the constraints.

        Optional dependencies often are not found, so the minimum version in version_range is returned in those cases.

        Args:
            name: crate name
            version_range: A VersionRange used to match against crate versions.

        Returns:
            version: Returns the version of the match or the minimum matching version if no match is found.
            node: None if no match is found otherwise returns the DepGraphNode of the match.
        """
        for version, node in self.graph[name].items():
            if version_range.contains(version):
                return version, node
        if not version_range.min:
            return '0.0.0', None
        return '.'.join(map(str, version_range.min)), None

    def check_dependencies(self, args, package, features, optional, features_only=False):
        """Check the dependencies of a specified package with the specified features enabled.

        Args:
            args: The command line flags set for cargo2ebuild.
            package: A parsed package from the Cargo metadata.
            features: A set containing the enabled features for this package. This will be expanded by the function to
                include any additional features implied by the original set of features (e.g. if default is set, all the
                default features will be added).
            optional: A dictionary of sets to which any new optional dependencies are added. It has the format:
                (package_name, package_version): set()
                where the set contains the required features.
            features_only: If True, this function only checks the optional dependencies for ones that are enabled if
                the features specified by `features` are enabled.

        Returns:
            A list of (package_name, package_version) that are required by the specified package with the specified
            features enabled.
        """
        name = package['name']
        version = package['version']
        node = self.graph[name][version]

        enabled_optional_deps = get_feature_dependencies(package, features)

        new_required = []
        for dep in node.dependencies:
            dep_name = dep['name']
            if features_only and dep_name not in enabled_optional_deps:
                continue
            req = VersionRange.from_str(dep['req'])
            dep_version, dep_node = self.resolve_version_range(dep_name, req)
            identifier = (dep_name, dep_version)

            dep_features = set(dep['features'])
            if dep_node and dep.get('uses_default_features', False):
                dep_features.add('default')

            is_required = not dep.get('optional', False) or dep_name in enabled_optional_deps
            if dep_name in enabled_optional_deps:
                if not features_only:
                    logging.info('Optional dependency required by feature: "%s-%s"', dep_name, dep_version)
                dep_features.update(enabled_optional_deps[dep_name])

            found = False
            sys_version = None
            repl_versions = []
            if dep_name not in self.system_crates:
                self.find_system_crates(args.target_dir, names=[dep_name])
            for sys_version, sys_features in self.system_crates[dep_name].items():
                sys_crate_is_empty = sys_features is not None
                missing_features = dep_features.difference(sys_features) if sys_crate_is_empty else set()
                if not args.overwrite_existing_ebuilds and sys_version == dep_version:
                    if sys_crate_is_empty:
                        if is_required:
                            logging.error('Empty crate "%s-%s" should be replaced with full version.',
                                          dep_name, dep_version)
                        elif missing_features:
                            logging.error('Empty crate "%s-%s" has missing features: %s.',
                                          dep_name, dep_version, missing_features)
                    found = True
                    break
                if not sys_crate_is_empty and req.contains(sys_version):
                    if not args.no_substitute or (not is_required and dep_node is None):
                        found = True
                        break
                if VersionRange.from_str('^{}'.format(sys_version)).contains(dep_version):
                    if sys_crate_is_empty:
                        dep_features.update(sys_features)
                    else:
                        repl_versions.append(sys_version)
            if found and not features_only:
                logging.debug('Using system crate: "%s-%s".', dep_name, sys_version)
                continue

            if is_required:
                if dep_node is None:
                    logging.error('Required crate "%s" "%s" not in dep-graph. It will be omitted.',
                                  dep_name, dep['req'])
                else:
                    logging.debug('New crate required: "%s-%s".', dep_name, dep_version)
                    new_required.append((dep_node.package, dep_features))
            else:
                # If the empty crate would replace a non-empty version of the same crate, treat it as required.
                if repl_versions:
                    if dep_node is not None:
                        logging.info('Empty crate for "%s-%s" would replace non-empty versions %s. '
                                     'Upgrading to non-empty.', dep_name, dep_version, repl_versions)
                        new_required.append((dep_node.package, dep_features))
                    else:
                        logging.error('Required crate "%s-%s" not in metadata. Fix: add it to Cargo.toml',
                                      dep_name, dep_version)
                else:
                    logging.debug('New optional crate required: "%s-%s".', dep_name, dep_version)
                    # Include all features supported by the crate.
                    if dep_node is not None:
                        dep_features = dep_node.package['features'].keys()
                    optional[identifier].update(dep_features if features else ())
        return new_required

    def flatten(self, args):
        """Flatten the dependency graph into a list of required and optional crates.

        Returns:
            Two dictionaries that map tuples of package names and versions to sets of features:
                (name, version) -> set(features)
            The first dictionary contains the required crates with their required features, while the second contains
            the optional crates, versions, and their features.
        """
        # (name, version) -> set(features)
        required = defaultdict(set)
        optional = defaultdict(set)
        remaining = [(root, {'default'}) for root in self.roots]
        while remaining:
            to_check, features = remaining.pop(0)
            name = to_check['name']
            version = to_check['version']

            identifier = (name, version)
            if identifier in required:
                features_to_enable = features.difference(required[identifier])
                if not features_to_enable:
                    continue
                logging.debug('Extending dependencies for "%s-%s" to include features: "%s"',
                              name, version, features_to_enable)
                remaining.extend(self.check_dependencies(args, to_check, features_to_enable, optional,
                                                         features_only=True))
            else:
                logging.debug('Resolving dependencies for "%s-%s".', name, version)
                remaining.extend(self.check_dependencies(args, to_check, features, optional))
            required[identifier].update(features)

        return dict(required), {a: b for a, b in optional.items() if a not in required}


def target_applies_to_chromeos(target):
    """Return true if the target would be accepted by the cros-rust eclass."""
    return (
            target.startswith('cfg(unix') or
            target.startswith('cfg(linux') or
            target.startswith('cfg(not(windows)') or
            '-linux-gnu' in target
    )


def target_is_filterable(target):
    """Checks to see if the cros-rust eclass would probably handle this target properly.

    Returns:
        False if the Cargo.toml target configuration block would not be accepted by the cros-rust eclass, but is probably needed.
    """
    if target_applies_to_chromeos(target):
        return True
    if 'unix' in target or 'linux' in target or 'not(' in target:
        return False
    return True


def get_feature_dependencies(package, features):
    """Expand the features set to include implied features and return the enabled optional dependencies.

    Args:
        package: A parsed package from the Cargo metadata.
        features: A set() of features that is expanded to include any additional dependencies implied by the original
            set of features.

    Returns:
        A dictionary that maps crate names to the required features for the specific crate.
        Note: that no version is supplied; it must be obtained by finding the named dependency in the package's
        optional dependency requirements.
    """
    feature_list = list(features)
    enabled_deps = defaultdict(set)
    lookup = package.get('features', {})
    for feature in feature_list:
        if feature not in lookup:
            if feature != 'default':
                logging.error('Requested feature "%s" not listed in crate "%s".',
                              feature, package['name'])
            continue
        for dep in lookup[feature]:
            # Check if it is a feature instead of a dependency.
            if dep in lookup:
                if dep not in features:
                    feature_list.append(dep)
                    features.add(dep)
                continue
            parts = dep.split('/')

            # This creates an empty set if there is not one already.
            entry = enabled_deps[parts[0]]
            if len(parts) > 1:
                entry.add(parts[1])
    return dict(enabled_deps)


def prepare_staging(args):
    """Prepare staging directory."""
    sdir = args.staging_dir
    dirs = [
        os.path.join(sdir, 'ebuild', 'dev-rust'),
        os.path.join(sdir, 'crates')
    ]
    for d in dirs:
        os.makedirs(d, exist_ok=True)


def load_metadata(manifest_path):
    """Run cargo metadata and get metadata for build."""
    cwd = os.path.dirname(manifest_path)
    cmd = [
        'cargo', 'metadata', '--format-version', '1', '--manifest-path',
        manifest_path
    ]
    output = subprocess.check_output(cmd, cwd=cwd)

    return json.loads(output)


def get_crate_path(package, staging_dir):
    """Get path to crate in staging directory."""
    return os.path.join(
        staging_dir, 'crates', '{}-{}.crate'.format(package['name'],
                                                    package['version']))


def get_clean_crate_name(package):
    """Clean up crate name to {name}-{major}.{minor}.{patch}."""
    return '{}-{}.crate'.format(package['name'],
                                get_clean_package_version(package['version']))


def version_to_tuple(version, missing=-1):
    """Extract dependency type and semver from a given version string."""
    def version_to_int(num):
        if not num or num == '*':
            return missing
        return int(num)

    m = re.match(VERSION_RE, version)
    if not m:
        raise VersionParseError(
            'Invalid SemVer: {}'.format(version))

    dep = m.group('dep')
    major = m.group('major')
    minor = m.group('minor')
    patch = m.group('patch')

    has_star = any([x == '*' for x in [major, minor, patch]])

    major = version_to_int(major)
    minor = version_to_int(minor)
    patch = version_to_int(patch)

    if has_star:
        dep = '~'
    elif not dep:
        dep = '^'

    return dep, major, minor, patch


def get_clean_package_version(version):
    """Get package version in the format {major}.{minor}.{patch}."""
    (_, major, minor, patch) = version_to_tuple(version, missing=0)
    return '{}.{}.{}'.format(major, minor, patch)


def get_ebuild_dir(name, staging_dir):
    """Get the directory that contains specific ebuilds."""
    return os.path.join(staging_dir, 'dev-rust', name)


def get_ebuild_path(name, version, staging_dir, make_dir=False):
    """Get path to ebuild in given directory."""
    ebuild_dir = get_ebuild_dir(name, staging_dir)

    ebuild_path = os.path.join(
        ebuild_dir,
        '{}-{}.ebuild'.format(name, get_clean_package_version(version)))

    if make_dir:
        os.makedirs(ebuild_dir, exist_ok=True)

    return ebuild_path


def download_package(package, staging_dir):
    """Download the crate from crates.io."""
    dl_uri = CRATE_DL_URI.format(PN=package['name'], PV=package['version'])
    crate_path = get_crate_path(package, staging_dir)

    # Already downloaded previously
    if os.path.isfile(crate_path):
        return

    ret = subprocess.run(
        ['curl', '-L', dl_uri, '-o', crate_path],
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL).returncode

    if ret:
        logging.error('Failed to download "%s": %s', dl_uri, ret)


def get_description(package):
    """Get a description of the crate from metadata."""
    if package.get('description', None):
        desc = re.sub("[`']", '"', package['description'])
        return desc.strip()

    return ''


def get_homepage(package):
    """Get the homepage of the crate from metadata or use crates.io."""
    if package.get('homepage', None):
        return package['homepage']

    return 'https://crates.io/crates/{}'.format(package['name'])


def convert_license(cargo_license, package):
    """Convert licenses from cargo to a format usable in ebuilds."""
    cargo_license = '' if not cargo_license else cargo_license
    has_or = ' OR ' in cargo_license
    delim = ' OR ' if has_or else '/'

    found = [a.strip() for a in cargo_license.split(delim) if a]
    licenses_or = []
    for f in found:
        if f in LICENSES:
            licenses_or.append(LICENSES[f])

    if not licenses_or:
        logging.error('"%s" is missing an appropriate license: "%s"', package['name'], cargo_license)
        return "$(die 'Please replace with appropriate license')"

    if len(licenses_or) > 1:
        lstr = '|| ( {} )'.format(' '.join(licenses_or))
    else:
        lstr = licenses_or[0]

    return lstr


def convert_dependencies(dependencies, filter_target=False):
    """Convert crate dependencies to ebuild dependencies."""
    deps = []
    for dep in dependencies:
        # Convert version requirement to ebuild DEPEND.
        try:
            # Convert requirement to version tuple
            bounds = (
                VersionRange.from_str(dep['req'])
                            .to_ebuild_str('dev-rust/{}'.format(dep['name']))
            )
            deps.append('\t{}'.format(bounds))
        except VersionParseError:
            logging.error('Failed to parse dep version for "%s": %s',
                          dep['name'], dep['req'], exc_info=True)
            # Rarely dependencies look something like ">=0.6, <0.8"
            deps.append("\t$(die 'Please replace with proper DEPEND: {} = {}')".format(
                dep['name'], dep['req']))

    remove_target_var = '\nCROS_RUST_REMOVE_TARGET_CFG=1' if filter_target else ''
    if not deps:
        return '', remove_target_var

    # Add DEPEND= into template with all dependencies
    # RDEPEND="${DEPEND}" required for race in cros-rust
    fmtstring = 'DEPEND="\n{}\n"\nRDEPEND="${{DEPEND}}"\n'
    return fmtstring.format('\n'.join(deps)), remove_target_var


def package_ebuild(package, ebuild_dir, crate_dependencies, filter_target):
    """Create ebuild from metadata and write to ebuild directory."""
    logging.debug('Processing "%s-%s"', package['name'], package['version'])
    ebuild_path = get_ebuild_path(package['name'], package['version'], ebuild_dir, make_dir=True)

    autogen_notice = AUTOGEN_NOTICE

    # Check if version matches clean version or modify the autogen notice
    if package['version'] != get_clean_package_version(package['version']):
        autogen_notice = '\n'.join([
            autogen_notice,
            '# ${{PV}} was changed from the original {}'.format(
                package['version'])
        ])

    (ebuild_dependencies, remove_target_var) = convert_dependencies(crate_dependencies, filter_target)
    template_info = {
        'copyright_year': datetime.now().year,
        'remove_target_var': remove_target_var,
        'description': get_description(package),
        'homepage': get_homepage(package),
        'license': convert_license(package['license'], package),
        'dependencies': ebuild_dependencies,
        'autogen_notice': autogen_notice,
    }

    with open(ebuild_path, 'w') as ebuild:
        ebuild.write(EBUILD_TEMPLATE.format(**template_info))


def upload_gsutil(package, staging_dir, no_upload=False):
    """Upload crate to distfiles."""
    if no_upload:
        return

    crate_path = get_crate_path(package, staging_dir)
    crate_name = get_clean_crate_name(package)
    ret = subprocess.run([
        'gsutil', 'cp', '-a', 'public-read', crate_path,
        'gs://chromeos-localmirror/distfiles/{}'.format(crate_name)
    ]).returncode

    if ret:
        logging.error('Failed to upload "%s" to chromeos-localmirror: %s', crate_name, ret)


def update_ebuild(package, args):
    """Update ebuild with generated one and generate MANIFEST."""
    staging_dir = args.staging_dir
    ebuild_dir = os.path.join(staging_dir, 'ebuild')
    target_dir = args.target_dir
    ebuild_src = get_ebuild_path(package['name'], package['version'], ebuild_dir)
    ebuild_dest = get_ebuild_path(package['name'], package['version'], target_dir, make_dir=True)

    # TODO make this aware of the revision numbers of existing versions
    # when doing a replacement.

    # Do not overwrite existing ebuilds unless explicitly asked to.
    if args.overwrite_existing_ebuilds or not os.path.exists(ebuild_dest):
        shutil.copy(ebuild_src, ebuild_dest)
        upload_gsutil(package, staging_dir, no_upload=args.no_upload)
    else:
        logging.info('ebuild %s already exists, skipping.', ebuild_dest)

    # Generate manifest w/ ebuild digest
    ret = subprocess.run(['ebuild', ebuild_dest, 'digest']).returncode
    if ret:
        logging.error('ebuild %s digest failed: %s', ebuild_dest, ret)


def process_package(package, staging_dir, dep_graph):
    """Process each package listed in the metadata.

    This includes following:
    * Setting the package as the root of the dep graph if it is included by source (rather than from crates.io).
    * Adding the package to the the dep_graph.
    * Downloading the crate file, so it can be potentially uploaded to localmirror.
    * Generating an ebuild for the crate in the staging directory.
    """
    ebuild_dir = os.path.join(staging_dir, 'ebuild')

    # Add the user submitted package to the set of required packages.
    if package.get('source', None) is None:
        dep_graph.add_root(package)
    filter_target, crate_dependencies = dep_graph.add_package(package)

    download_package(package, staging_dir)
    package_ebuild(package, ebuild_dir, crate_dependencies, filter_target)


def process_empty_package(name, version, features, args):
    """Process packages that should generate empty ebuilds."""
    staging_dir = args.staging_dir
    ebuild_dir = os.path.join(staging_dir, 'ebuild')
    target_dir = args.target_dir

    ebuild_src = get_ebuild_path(name, version, ebuild_dir, make_dir=True)
    ebuild_dest = get_ebuild_path(name, version, target_dir, make_dir=True)

    crate_features = ''
    if features:
        crate_features = 'CROS_RUST_EMPTY_CRATE_FEATURES=( {} )'.format(
            ' '.join(['"{}"'.format(x) for x in features]))

    template_info = {
        'copyright_year': datetime.now().year,
        'crate_features': crate_features,
        'autogen_notice': AUTOGEN_NOTICE,
    }

    logging.debug('Writing empty crate: %s', ebuild_src)
    with open(ebuild_src, 'w') as ebuild:
        ebuild.write(EMPTY_CRATE.format(**template_info))

    # Do not overwrite existing ebuilds unless explicitly asked to.
    if not args.overwrite_existing_ebuilds and os.path.exists(ebuild_dest):
        logging.info('ebuild %s already exists, skipping.', ebuild_dest)
        return

    if not args.dry_run and name not in args.skip:
        shutil.copy(ebuild_src, ebuild_dest)


def main(argv):
    """Convert dependencies from Cargo.toml into ebuilds."""
    args = parse_args(argv)

    logging_kwargs = {'stream': sys.stderr, 'format': '%(levelname)s: %(message)s'}
    if args.verbose > 1:
        logging_kwargs['level'] = logging.DEBUG
    elif args.verbose > 0:
        logging_kwargs['level'] = logging.INFO
    else:
        logging_kwargs['level'] = logging.WARNING
    logging.basicConfig(**logging_kwargs)

    prepare_staging(args)

    dep_graph = DepGraph()
    metadata = load_metadata(args.manifest_path)
    for p in metadata['packages']:
        process_package(p, args.staging_dir, dep_graph)

    dep_graph.find_system_crates(args.target_dir)

    required_packages, optional_packages = dep_graph.flatten(args)
    if args.verbose > 2:
        print('Dependency graph:')
        pprint(dict(dep_graph.graph))
        print('System versions:')
        pprint(dict(dep_graph.system_crates))
    print('Required versions:')
    pprint(required_packages)
    print('Optional versions:')
    pprint(optional_packages)

    for (name, version), features in optional_packages.items():
        process_empty_package(name, version, features, args)

    if not args.dry_run:
        for p in metadata['packages']:
            if p['name'] in args.skip:
                continue
            identifier = (p['name'], p['version'])
            if identifier in required_packages:
                update_ebuild(p, args)
        display_dir = args.target_dir
    else:
        display_dir = '/'.join((args.staging_dir, 'ebuild'))
    print('Generated ebuilds can be found in: {}'.format(display_dir))


def parse_args(argv):
    """Parse the command-line arguments."""
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        '-s',
        '--staging-dir',
        default='/tmp/cargo2ebuild-staging',
        help='Staging directory for temporary and generated files')

    parser.add_argument(
        '-d',
        '--dry-run',
        action='store_true',
        help='Generate dependency tree but do not upload anything')

    parser.add_argument('-t',
                        '--target-dir',
                        default='/mnt/host/source/src/third_party/chromiumos-overlay',
                        help='Path to chromiumos-overlay')

    parser.add_argument('-k',
                        '--skip',
                        action='append',
                        help='Skip these packages when updating ebuilds')
    parser.add_argument('-n',
                        '--no-upload',
                        action='store_true',
                        help='Skip uploading crates to distfiles')
    parser.add_argument('-X',
                        '--no-substitute',
                        action='store_true',
                        help='Do not substitute system versions for required crates')
    parser.add_argument('-x',
                        '--overwrite-existing-ebuilds',
                        action='store_true',
                        help='If an ebuild already exists, overwrite it.')
    parser.add_argument('-v',
                        '--verbose',
                        action='count',
                        default=0,
                        help='Enable verbose logging')

    parser.add_argument('manifest_path',
                        nargs='?',
                        default='./Cargo.toml',
                        help='Cargo.toml used to generate ebuilds.')

    args = parser.parse_args(argv)

    # Require target directory if not dry run
    if not args.target_dir and not args.dry_run:
        raise Exception('Target directory must be set unless dry-run is True.')

    if not args.skip:
        args.skip = []

    return args


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