Skip to content
This repository has been archived by the owner on Aug 15, 2024. It is now read-only.

feat: allow version selection #53

Merged
merged 8 commits into from
Dec 2, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions src/bin/cargo-info/command/info.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cargo::util::command_prelude::*;
use cargo::{core::PackageIdSpec, util::command_prelude::*};
use cargo_information::ops;

pub fn cli() -> Command {
Expand All @@ -11,7 +11,13 @@ pub fn cli() -> Command {
fn info_subcommand() -> Command {
Command::new("info")
.about("Display info about a package in the registry")
.arg(Arg::new("pkgid").required(true).value_name("SPEC"))
.arg(
Arg::new("package")
.required(true)
.value_name("SPEC")
.help_heading(heading::PACKAGE_SELECTION)
Rustin170506 marked this conversation as resolved.
Show resolved Hide resolved
.help("Package to inspect"),
)
.arg_index("Registry index URL to search packages in")
.arg_registry("Registry to search packages in")
.arg(
Expand Down Expand Up @@ -91,9 +97,13 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
&config_args,
)?;

let pkgid = args.get_one::<String>("pkgid").map(String::as_str).unwrap();
let package = args
.get_one::<String>("package")
.map(String::as_str)
.unwrap();
let spec = PackageIdSpec::parse(package)?;
epage marked this conversation as resolved.
Show resolved Hide resolved
let reg_or_index = args.registry_or_index(config)?;
ops::info(pkgid, config, reg_or_index)?;
ops::info(&spec, config, reg_or_index)?;
Ok(())
}

Expand Down
30 changes: 22 additions & 8 deletions src/ops/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::task::Poll;

use anyhow::{bail, Context as _};
use cargo::core::registry::PackageRegistry;
use cargo::core::{Dependency, PackageId, Registry, SourceId, Summary, Workspace};
use cargo::core::{Dependency, PackageId, PackageIdSpec, Registry, SourceId, Summary, Workspace};
use cargo::ops::RegistryOrIndex;
use cargo::sources::source::{QueryKind, Source};
use cargo::sources::{RegistrySource, SourceConfigMap};
Expand All @@ -18,7 +18,11 @@ use crates_io::User;

use super::view::{pretty_view, suggest_cargo_tree};

pub fn info(spec: &str, config: &Config, reg_or_index: Option<RegistryOrIndex>) -> CargoResult<()> {
pub fn info(
spec: &PackageIdSpec,
config: &Config,
reg_or_index: Option<RegistryOrIndex>,
) -> CargoResult<()> {
let mut registry = PackageRegistry::new(config)?;
// Make sure we get the lock before we download anything.
let _lock = config.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;
Expand All @@ -29,12 +33,19 @@ pub fn info(spec: &str, config: &Config, reg_or_index: Option<RegistryOrIndex>)
if let Ok(root) = root_manifest(None, config) {
let ws = Workspace::new(&root, config)?;
if let Some(resolve) = ops::load_pkg_lockfile(&ws)? {
if let Ok(p) = resolve.query(spec) {
if let Ok(p) = resolve.query(spec.name()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You likely want to call specs_to_ids. It can return multiple results, just pick the highest.

  • Avoids the need for the matches call below
  • Picks a value when there is ambiguity, rather than erroring and falling through to the registry (we should have a test case added for this)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a little bit confused. It seems the specs_to_ids API also uses the query API internally.

It can only return one matched package or bail out an error:

    /// Checks a list of `PackageId`s to find 1 that matches this `PackageIdSpec`. If 0, 2, or
    /// more are found, then this returns an error.
    pub fn query<I>(&self, i: I) -> CargoResult<PackageId>

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overlooked that. We likely want to just call .iter() and do our own calls to matches...

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

package_id = Some(p)
}
}
}

// If the locked version is not matched, ignore it.
if let Some(pkg_id) = package_id {
if !spec.matches(pkg_id) {
package_id = None;
}
}

let (use_package_source_id, source_ids) = get_source_id(config, reg_or_index, package_id)?;
// If we don't use the package's source, we need to query the package ID from the specified registry.
if !use_package_source_id {
Expand All @@ -47,7 +58,7 @@ pub fn info(spec: &str, config: &Config, reg_or_index: Option<RegistryOrIndex>)
// Query the package registry and pretty print the result.
// If package_id is None, find the latest version.
fn query_and_pretty_view(
spec: &str,
spec: &PackageIdSpec,
package_id: Option<PackageId>,
config: &Config,
mut registry: PackageRegistry,
Expand All @@ -65,7 +76,7 @@ fn query_and_pretty_view(
}
}
// Query without version requirement to get all index summaries.
let dep = Dependency::parse(spec, None, source_ids.original)?;
let dep = Dependency::parse(spec.name(), None, source_ids.original)?;
let summaries = loop {
// Exact to avoid returning all for path/git
match registry.query_vec(&dep, QueryKind::Exact) {
Expand All @@ -79,9 +90,12 @@ fn query_and_pretty_view(
let package_id = match package_id {
Some(id) => id,
None => {
// Find the latest version.
let summary = summaries.iter().max_by_key(|s| s.package_id().version());

// If no matching summary is found, it defaults to the summary with the highest version number.
let summary = summaries
.iter()
.filter(|s| spec.matches(s.package_id()))
.max_by_key(|s| s.package_id().version())
.or(summaries.iter().max_by_key(|s| s.package_id().version()));
// If can not find the latest version, return an error.
match summary {
Some(summary) => summary.package_id(),
Expand Down
6 changes: 3 additions & 3 deletions tests/testsuite/cargo_information/help/stdout.log
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ Display info about a package in the registry

Usage: cargo info [OPTIONS] <SPEC>

Arguments:
<SPEC>

Options:
--index <INDEX> Registry index URL to search packages in
--registry <REGISTRY> Registry to search packages in
Expand All @@ -15,6 +12,9 @@ Options:
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
-h, --help Print help

Package Selection:
<SPEC> Package to inspect

Manifest Options:
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
Expand Down
3 changes: 3 additions & 0 deletions tests/testsuite/cargo_information/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ mod basic;
mod features;
mod help;
mod not_found;
mod specify_version_outside_workspace;
mod specify_version_within_ws_and_conflict_with_lockfile;
mod specify_version_within_ws_and_match_with_lockfile;
epage marked this conversation as resolved.
Show resolved Hide resolved
mod with_frozen_outside_workspace;
mod with_frozen_within_workspace;
mod with_locked_outside_workspace;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use cargo_test_macro::cargo_test;
use cargo_test_support::curr_dir;

use super::{cargo_info, init_registry_without_token};

#[cargo_test]
fn case() {
init_registry_without_token();
for ver in ["0.1.1+my-package", "0.2.0+my-package", "0.2.3+my-package"] {
cargo_test_support::registry::Package::new("my-package", ver).publish();
}
cargo_info()
.arg("my-package@0.2")
.arg("--registry=dummy-registry")
.assert()
.success()
.stdout_matches_path(curr_dir!().join("stdout.log"))
.stderr_matches_path(curr_dir!().join("stderr.log"));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Updating `dummy-registry` index
Downloading crates ...
Downloaded my-package v0.2.3+my-package (registry `dummy-registry`)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
my-package
version: 0.2.3+my-package
license: unknown
rust-version: unknown
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use cargo_test_macro::cargo_test;
use cargo_test_support::{compare::assert_ui, curr_dir, Project};

use super::{cargo_info, init_registry_without_token};

#[cargo_test]
fn case() {
init_registry_without_token();
for ver in [
"0.1.1+my-package",
"0.2.0+my-package",
"0.2.3+my-package",
"0.4.1+my-package",
"20.0.0+my-package",
"99999.0.0+my-package",
"99999.0.0-alpha.1+my-package",
] {
cargo_test_support::registry::Package::new("my-package", ver).publish();
}

let project = Project::from_template(curr_dir!().join("in"));
let project_root = project.root();
let cwd = &project_root;

cargo_info()
.arg("my-package@0.4")
.arg("--registry=dummy-registry")
.current_dir(cwd)
.assert()
.success()
.stdout_matches_path(curr_dir!().join("stdout.log"))
.stderr_matches_path(curr_dir!().join("stderr.log"));

assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[workspace]

[package]
name = "cargo-list-test-fixture"
version = "0.0.0"

[dependencies]
my-package = "0.1"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Updating `dummy-registry` index
Downloading crates ...
Downloaded my-package v0.4.1+my-package (registry `dummy-registry`)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
my-package
version: 0.4.1+my-package (latest 99999.0.0+my-package)
license: unknown
rust-version: unknown
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use cargo_test_macro::cargo_test;
use cargo_test_support::{compare::assert_ui, curr_dir, Project};

use super::{cargo_info, init_registry_without_token};

#[cargo_test]
fn case() {
init_registry_without_token();
for ver in [
"0.1.1+my-package",
"0.2.0+my-package",
"0.2.3+my-package",
"0.4.1+my-package",
"20.0.0+my-package",
"99999.0.0+my-package",
"99999.0.0-alpha.1+my-package",
] {
cargo_test_support::registry::Package::new("my-package", ver).publish();
}

let project = Project::from_template(curr_dir!().join("in"));
let project_root = project.root();
let cwd = &project_root;

cargo_info()
.arg("my-package@0.1")
.arg("--registry=dummy-registry")
.current_dir(cwd)
.assert()
.success()
.stdout_matches_path(curr_dir!().join("stdout.log"))
.stderr_matches_path(curr_dir!().join("stderr.log"));

assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[workspace]

[package]
name = "cargo-list-test-fixture"
version = "0.0.0"

[dependencies]
my-package = "0.1"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Updating `dummy-registry` index
Downloading crates ...
Downloaded my-package v0.1.1+my-package (registry `dummy-registry`)
Updating crates.io index
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
my-package
version: 0.1.1+my-package (latest 99999.0.0+my-package)
license: unknown
rust-version: unknown
documentation: https://docs.rs/my-package/0.1.1+my-package
note: to see how you depend on my-package, run `cargo tree --package my-package@0.1.1+my-package --invert`