From 012b99c84c2995bd3a36143f7b97eb6fe51dc399 Mon Sep 17 00:00:00 2001 From: Fabio Valentini Date: Thu, 2 Mar 2023 20:55:58 +0100 Subject: [PATCH] metadata: add interactive mode for guess_main_package --- rust2rpm/__main__.py | 7 ++++++ rust2rpm/cli.py | 6 ++++++ rust2rpm/generator.py | 6 +++--- rust2rpm/metadata.py | 37 ++++++++++++++++++++++++++++++-- rust2rpm/tests/test_generator.py | 6 ++++-- 5 files changed, 55 insertions(+), 7 deletions(-) diff --git a/rust2rpm/__main__.py b/rust2rpm/__main__.py index 2c333f9..91c3e36 100644 --- a/rust2rpm/__main__.py +++ b/rust2rpm/__main__.py @@ -12,6 +12,7 @@ from rust2rpm.cratesio import NoVersionsError from rust2rpm.distgit import get_package_info from rust2rpm.generator import spec_render_crate, spec_render_workspace from rust2rpm.licensing import dump_sdpx_to_fedora_map, translate_license +from rust2rpm.metadata import guess_main_package from rust2rpm.utils import ( detect_packager, detect_rpmautospec, @@ -129,8 +130,14 @@ def main(): ) else: + try: + main_package = guess_main_package(metadata, hint=project, interactive=args.interactive) + except ValueError: + sys.exit(1) + spec_contents = spec_render_workspace( metadata=metadata, + main_package=main_package, target=args.target, rpm_name=rpm_name, license_files=license_files, diff --git a/rust2rpm/cli.py b/rust2rpm/cli.py index 354a74f..7fca8df 100644 --- a/rust2rpm/cli.py +++ b/rust2rpm/cli.py @@ -87,6 +87,12 @@ def get_parser(): action="store", help="Package suffix", ) + parser.add_argument( + "-i", + "--interactive", + action="store_true", + help="Enable interactive mode", + ) parser.add_argument( "crate", help="crates.io name\n" "path/to/local.crate\n" "path/to/project/", diff --git a/rust2rpm/generator.py b/rust2rpm/generator.py index 087dded..dd39eb9 100644 --- a/rust2rpm/generator.py +++ b/rust2rpm/generator.py @@ -5,14 +5,14 @@ Functionality for rendering the spec file template. import time from typing import Optional -from cargo2rpm.metadata import Metadata, Version, FeatureFlags +from cargo2rpm.metadata import Metadata, Package, Version, FeatureFlags from cargo2rpm import rpm import jinja2 from rust2rpm import __version__, log from rust2rpm.conf import Rust2RpmConf from rust2rpm.licensing import translate_license -from rust2rpm.metadata import guess_main_package, package_uses_rust_1_60_feature_syntax +from rust2rpm.metadata import package_uses_rust_1_60_feature_syntax def to_list(s): @@ -247,6 +247,7 @@ def spec_render_crate( def spec_render_workspace( *, metadata: Metadata, + main_package: Package, target: str, rpm_name: str, license_files: list[str], @@ -266,7 +267,6 @@ def spec_render_workspace( is_cdylib = metadata.is_cdylib() - main_package = guess_main_package(metadata) rpm_version = Version.parse(main_package.version).to_rpm() rpm_description = main_package.get_description() rpm_summary = main_package.get_summary() diff --git a/rust2rpm/metadata.py b/rust2rpm/metadata.py index 6a9f1bd..3e9929a 100644 --- a/rust2rpm/metadata.py +++ b/rust2rpm/metadata.py @@ -1,7 +1,11 @@ +from typing import Optional + from cargo2rpm.metadata import Metadata, Package +from rust2rpm import log -def guess_main_package(metadata: Metadata) -> Package: + +def guess_main_package(metadata: Metadata, hint: Optional[str] = None, interactive: bool = False) -> Package: if not metadata.is_workspace(): return metadata.packages[0] @@ -21,7 +25,36 @@ def guess_main_package(metadata: Metadata) -> Package: if len(with_bin) == 1: return with_bin[0] - raise ValueError("Heuristic for determining the main crate of a cargo workspace failed. Please report a bug.") + if interactive: + choices = [package.name for package in with_bin] + [package.name for package in with_cdylib] + log.warn( + 'Heuristic for determining the "main" crate of the workspace failed. ' + + 'Please specify the name of the "main" crate (usually the crate which ' + + "provides the user-facing CLI) manually." + ) + log.info("Choices: " + ", ".join(choices)) + hint = input("Crate name: ") + + if hint not in choices: + log.error("Invalid crate name.") + raise ValueError + + for package in metadata.packages: + if package.name == hint: + return package + + if hint: + for package in metadata.packages: + if package.name == hint: + log.warn( + f'Using {hint!r} as the name of the "main" crate. If this is not correct, use interactive mode.' + ) + return package + + log.error("Heuristic for determining the main crate of the workspace failed.") + log.error("Please use '--interactive' mode.") + + raise ValueError def package_uses_rust_1_60_feature_syntax(features: dict[str, list[str]]) -> bool: diff --git a/rust2rpm/tests/test_generator.py b/rust2rpm/tests/test_generator.py index 73aa399..1c38dd9 100644 --- a/rust2rpm/tests/test_generator.py +++ b/rust2rpm/tests/test_generator.py @@ -10,6 +10,7 @@ import pytest from rust2rpm.cli import get_parser from rust2rpm.conf import Rust2RpmConf from rust2rpm.generator import to_list, spec_render_crate, spec_render_workspace +from rust2rpm.metadata import guess_main_package from rust2rpm.patching import drop_foreign_dependencies from rust2rpm.utils import package_name_suffixed @@ -34,7 +35,7 @@ FIXED_DATE = time.gmtime(12345) @pytest.mark.parametrize("filename", ["cxx-build-1.0.71.json", "nix-0.24.1.json", "tokio-1.19.2.json"]) @pytest.mark.parametrize("target", ["plain", "fedora", "mageia", "opensuse"]) -def test_spec_file_render_crate(filename: str, target: str, tmp_path: Path): +def test_spec_file_render_crate(filename: str, target: str): crate_name_version = filename.removesuffix(".json") crate = crate_name_version.rsplit("-", 1)[0] @@ -76,7 +77,7 @@ def test_spec_file_render_crate(filename: str, target: str, tmp_path: Path): @pytest.mark.parametrize("filename", ["zola-0.16.1.json"]) @pytest.mark.parametrize("target", ["plain", "fedora", "mageia", "opensuse"]) -def test_spec_file_render_workspace(filename: str, target: str, tmp_path: Path): +def test_spec_file_render_workspace(filename: str, target: str): crate_name_version = filename.removesuffix(".json") crate = crate_name_version.rsplit("-", 1)[0] @@ -85,6 +86,7 @@ def test_spec_file_render_workspace(filename: str, target: str, tmp_path: Path): rendered = spec_render_workspace( metadata=metadata, + main_package=guess_main_package(metadata), target=target, rpm_name=crate, license_files=["LIC1", "LIC2"],