#!/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:
                    v_max = (major + 1, 0, 0)
                elif v_min[2] < 0:
                    v_max = (0, minor + 1, 0)
                else:
                    v_max_inclusive = True
                    v_max = (major, minor, patch)
                v_min = (major, minor, patch)
            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 '>'
        max_bound = '<=' if self.max_inclusive else '<'
        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])

        return '{0}{1}-{2}.{3}.{4}:= {5}{1}-{6}.{7}.{8}'.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])


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.root = None

    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 set_root(self, package):
        """Set the root of the dependency graph used when flattening the graph into a list of dependencies."""
        self.root = 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 = [(self.root, {'default'})]
        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

    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.set_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:]))
