Skip to content

Commit

Permalink
Auto merge of rust-lang#13335 - hi-rustin:rustin-patch-same-name, r=w…
Browse files Browse the repository at this point in the history
…eihanglo

fix: use spec id instead of name to match package
  • Loading branch information
bors committed Jan 30, 2024
2 parents 61debf8 + 7a13864 commit 8ed4cb1
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 23 deletions.
68 changes: 45 additions & 23 deletions src/cargo/ops/cargo_compile/packages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use std::collections::BTreeSet;

use crate::core::Package;
use crate::core::{Package, PackageIdSpecQuery};
use crate::core::{PackageIdSpec, Workspace};
use crate::util::restricted_names::is_glob_pattern;
use crate::util::CargoResult;
Expand Down Expand Up @@ -50,16 +50,24 @@ impl Packages {
.map(|id| id.to_spec())
.collect(),
Packages::OptOut(opt_out) => {
let (mut patterns, mut names) = opt_patterns_and_names(opt_out)?;
let (mut patterns, mut ids) = opt_patterns_and_ids(opt_out)?;
let specs = ws
.members()
.filter(|pkg| {
!names.remove(pkg.name().as_str()) && !match_patterns(pkg, &mut patterns)
let id = ids.iter().find(|id| id.matches(pkg.package_id())).cloned();
if let Some(id) = &id {
ids.remove(id);
}
!id.is_some() && !match_patterns(pkg, &mut patterns)
})
.map(Package::package_id)
.map(|id| id.to_spec())
.collect();
let warn = |e| ws.config().shell().warn(e);
let names = ids
.into_iter()
.map(|id| id.to_string())
.collect::<BTreeSet<_>>();
emit_package_not_found(ws, names, true).or_else(warn)?;
emit_pattern_not_found(ws, patterns, true).or_else(warn)?;
specs
Expand All @@ -68,11 +76,7 @@ impl Packages {
vec![ws.current()?.package_id().to_spec()]
}
Packages::Packages(opt_in) => {
let (mut patterns, packages) = opt_patterns_and_names(opt_in)?;
let mut specs = packages
.iter()
.map(|p| PackageIdSpec::parse(p))
.collect::<Result<Vec<_>, _>>()?;
let (mut patterns, mut specs) = opt_patterns_and_ids(opt_in)?;
if !patterns.is_empty() {
let matched_pkgs = ws
.members()
Expand All @@ -82,7 +86,7 @@ impl Packages {
specs.extend(matched_pkgs);
}
emit_pattern_not_found(ws, patterns, false)?;
specs
specs.into_iter().collect()
}
Packages::Default => ws
.default_members()
Expand All @@ -109,25 +113,41 @@ impl Packages {
Packages::Default => ws.default_members().collect(),
Packages::All => ws.members().collect(),
Packages::OptOut(opt_out) => {
let (mut patterns, mut names) = opt_patterns_and_names(opt_out)?;
let (mut patterns, mut ids) = opt_patterns_and_ids(opt_out)?;
let packages = ws
.members()
.filter(|pkg| {
!names.remove(pkg.name().as_str()) && !match_patterns(pkg, &mut patterns)
let id = ids.iter().find(|id| id.matches(pkg.package_id())).cloned();
if let Some(id) = &id {
ids.remove(id);
}
!id.is_some() && !match_patterns(pkg, &mut patterns)
})
.collect();
let names = ids
.into_iter()
.map(|id| id.to_string())
.collect::<BTreeSet<_>>();
emit_package_not_found(ws, names, true)?;
emit_pattern_not_found(ws, patterns, true)?;
packages
}
Packages::Packages(opt_in) => {
let (mut patterns, mut names) = opt_patterns_and_names(opt_in)?;
let (mut patterns, mut ids) = opt_patterns_and_ids(opt_in)?;
let packages = ws
.members()
.filter(|pkg| {
names.remove(pkg.name().as_str()) || match_patterns(pkg, &mut patterns)
let id = ids.iter().find(|id| id.matches(pkg.package_id())).cloned();
if let Some(id) = &id {
ids.remove(id);
}
id.is_some() || match_patterns(pkg, &mut patterns)
})
.collect();
let names = ids
.into_iter()
.map(|id| id.to_string())
.collect::<BTreeSet<_>>();
emit_package_not_found(ws, names, false)?;
emit_pattern_not_found(ws, patterns, false)?;
packages
Expand All @@ -151,7 +171,7 @@ impl Packages {
/// Emits "package not found" error.
fn emit_package_not_found(
ws: &Workspace<'_>,
opt_names: BTreeSet<&str>,
opt_names: BTreeSet<String>,
opt_out: bool,
) -> CargoResult<()> {
if !opt_names.is_empty() {
Expand Down Expand Up @@ -188,20 +208,22 @@ fn emit_pattern_not_found(
}

/// Given a list opt-in or opt-out package selection strings, generates two
/// collections that represent glob patterns and package names respectively.
fn opt_patterns_and_names(
/// collections that represent glob patterns and package id specs respectively.
fn opt_patterns_and_ids(
opt: &[String],
) -> CargoResult<(Vec<(glob::Pattern, bool)>, BTreeSet<&str>)> {
) -> CargoResult<(Vec<(glob::Pattern, bool)>, BTreeSet<PackageIdSpec>)> {
let mut opt_patterns = Vec::new();
let mut opt_names = BTreeSet::new();
let mut opt_ids = BTreeSet::new();
for x in opt.iter() {
if PackageIdSpec::parse(x).is_err() && is_glob_pattern(x) {
opt_patterns.push((build_glob(x)?, false));
} else {
opt_names.insert(String::as_str(x));
match PackageIdSpec::parse(x) {
Ok(spec) => {
opt_ids.insert(spec);
}
Err(_) if is_glob_pattern(x) => opt_patterns.push((build_glob(x)?, false)),
Err(e) => return Err(e.into()),
}
}
Ok((opt_patterns, opt_names))
Ok((opt_patterns, opt_ids))
}

/// Checks whether a package matches any of a list of glob patterns generated
Expand Down
46 changes: 46 additions & 0 deletions tests/testsuite/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1566,3 +1566,49 @@ fn run_link_system_path_macos() {
p2.cargo("run").env(VAR, &libdir).run();
p2.cargo("test").env(VAR, &libdir).run();
}

#[cargo_test]
fn run_binary_with_same_name_as_dependency() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.5.0"
authors = []
[dependencies]
foo = { path = "foo" }
"#,
)
.file(
"src/main.rs",
r#"
fn main() {}
"#,
)
.file(
"foo/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = []
[lib]
name = "foo"
path = "foo.rs"
"#,
)
.file("foo/foo.rs", "")
.build();
p.cargo("run").run();
p.cargo("check -p [email protected]").run();
p.cargo("run -p [email protected]").run();
p.cargo("run -p [email protected]").run();
p.cargo("run -p [email protected]")
.with_status(101)
.with_stderr("[ERROR] package(s) `[email protected]` not found in workspace `[..]`")
.run();
}

0 comments on commit 8ed4cb1

Please sign in to comment.