Skip to content

Commit 91e8af3

Browse files
committed
fix(source): Consolidate duplicate package warnings
1 parent 800a482 commit 91e8af3

File tree

2 files changed

+51
-29
lines changed

2 files changed

+51
-29
lines changed

src/cargo/sources/path.rs

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ pub struct RecursivePathSource<'gctx> {
226226
/// Whether this source has loaded all package information it may contain.
227227
loaded: bool,
228228
/// Packages that this sources has discovered.
229-
packages: HashMap<PackageId, Package>,
229+
packages: HashMap<PackageId, Vec<Package>>,
230230
gctx: &'gctx GlobalContext,
231231
}
232232

@@ -253,7 +253,7 @@ impl<'gctx> RecursivePathSource<'gctx> {
253253
/// filesystem if package information haven't yet loaded.
254254
pub fn read_packages(&mut self) -> CargoResult<Vec<Package>> {
255255
self.load()?;
256-
Ok(self.packages.iter().map(|(_, v)| v.clone()).collect())
256+
Ok(self.packages.iter().map(|(_, v)| v[0].clone()).collect())
257257
}
258258

259259
/// List all files relevant to building this package inside this source.
@@ -290,6 +290,32 @@ impl<'gctx> RecursivePathSource<'gctx> {
290290
pub fn load(&mut self) -> CargoResult<()> {
291291
if !self.loaded {
292292
self.packages = read_packages(&self.path, self.source_id, self.gctx)?;
293+
for (pkg_id, pkgs) in self.packages.iter() {
294+
if 1 < pkgs.len() {
295+
let ignored = pkgs[1..]
296+
.iter()
297+
// We can assume a package with publish = false isn't intended to be seen
298+
// by users so we can hide the warning about those since the user is unlikely
299+
// to care about those cases.
300+
.filter(|pkg| pkg.publish().is_none())
301+
.collect::<Vec<_>>();
302+
if !ignored.is_empty() {
303+
use std::fmt::Write as _;
304+
305+
let plural = if ignored.len() == 1 { "" } else { "s" };
306+
let mut msg = String::new();
307+
let _ =
308+
writeln!(&mut msg, "skipping duplicate package{plural} `{pkg_id}`:");
309+
for ignored in ignored {
310+
let manifest_path = ignored.manifest_path().display();
311+
let _ = writeln!(&mut msg, " {manifest_path}");
312+
}
313+
let manifest_path = pkgs[0].manifest_path().display();
314+
let _ = writeln!(&mut msg, "in favor of {manifest_path}");
315+
let _ = self.gctx.shell().warn(msg);
316+
}
317+
}
318+
}
293319
self.loaded = true;
294320
}
295321

@@ -311,7 +337,12 @@ impl<'gctx> Source for RecursivePathSource<'gctx> {
311337
f: &mut dyn FnMut(IndexSummary),
312338
) -> Poll<CargoResult<()>> {
313339
self.load()?;
314-
for s in self.packages.values().map(|p| p.summary()) {
340+
for s in self
341+
.packages
342+
.values()
343+
.map(|pkgs| &pkgs[0])
344+
.map(|p| p.summary())
345+
{
315346
let matched = match kind {
316347
QueryKind::Exact => dep.matches(s),
317348
QueryKind::Alternatives => true,
@@ -340,7 +371,7 @@ impl<'gctx> Source for RecursivePathSource<'gctx> {
340371
trace!("getting packages; id={}", id);
341372
self.load()?;
342373
let pkg = self.packages.get(&id);
343-
pkg.cloned()
374+
pkg.map(|pkgs| pkgs[0].clone())
344375
.map(MaybePackage::Ready)
345376
.ok_or_else(|| internal(format!("failed to find {} in path source", id)))
346377
}
@@ -758,7 +789,7 @@ fn read_packages(
758789
path: &Path,
759790
source_id: SourceId,
760791
gctx: &GlobalContext,
761-
) -> CargoResult<HashMap<PackageId, Package>> {
792+
) -> CargoResult<HashMap<PackageId, Vec<Package>>> {
762793
let mut all_packages = HashMap::new();
763794
let mut visited = HashSet::<PathBuf>::new();
764795
let mut errors = Vec::<anyhow::Error>::new();
@@ -899,7 +930,7 @@ fn has_manifest(path: &Path) -> bool {
899930

900931
fn read_nested_packages(
901932
path: &Path,
902-
all_packages: &mut HashMap<PackageId, Package>,
933+
all_packages: &mut HashMap<PackageId, Vec<Package>>,
903934
source_id: SourceId,
904935
gctx: &GlobalContext,
905936
visited: &mut HashSet<PathBuf>,
@@ -938,24 +969,10 @@ fn read_nested_packages(
938969
let pkg = Package::new(manifest, &manifest_path);
939970

940971
let pkg_id = pkg.package_id();
941-
use std::collections::hash_map::Entry;
942-
match all_packages.entry(pkg_id) {
943-
Entry::Vacant(v) => {
944-
v.insert(pkg);
945-
}
946-
Entry::Occupied(_) => {
947-
// We can assume a package with publish = false isn't intended to be seen
948-
// by users so we can hide the warning about those since the user is unlikely
949-
// to care about those cases.
950-
if pkg.publish().is_none() {
951-
let _ = gctx.shell().warn(format!(
952-
"skipping duplicate package `{}` found at `{}`",
953-
pkg.name(),
954-
path.display()
955-
));
956-
}
957-
}
958-
}
972+
all_packages
973+
.entry(pkg_id)
974+
.or_insert_with(Default::default)
975+
.push(pkg);
959976

960977
// Registry sources are not allowed to have `path=` dependencies because
961978
// they're all translated to actual registry dependencies.

tests/testsuite/git.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,12 +1182,14 @@ fn ambiguous_published_deps() {
11821182
p.cargo("build").run();
11831183
p.cargo("run")
11841184
.with_stderr_data(str![[r#"
1185-
[WARNING] skipping duplicate package `duplicate` found at `[ROOT]/home/.cargo/git/checkouts/dep-[HASH]/e916fc8/duplicate2`
1185+
[WARNING] skipping duplicate package `duplicate v0.5.0 ([ROOTURL]/dep#[..])`:
1186+
[ROOT]/home/.cargo/git/checkouts/dep-[HASH]/[..]/duplicate2/Cargo.toml
1187+
in favor of [ROOT]/home/.cargo/git/checkouts/dep-[HASH]/[..]/duplicate1/Cargo.toml
1188+
11861189
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
11871190
[RUNNING] `target/debug/foo[EXE]`
11881191
1189-
"#]],
1190-
)
1192+
"#]])
11911193
.run();
11921194
}
11931195

@@ -1276,12 +1278,15 @@ fn unused_ambiguous_published_deps() {
12761278
.with_stderr_data(str![[r#"
12771279
[ERROR] invalid table header
12781280
expected `.`, `]`
1279-
--> ../home/.cargo/git/checkouts/dep-[HASH]/caf7f52/invalid/Cargo.toml:2:29
1281+
--> ../home/.cargo/git/checkouts/dep-[HASH]/[..]/invalid/Cargo.toml:2:29
12801282
|
12811283
2 | [package
12821284
| ^
12831285
|
1284-
[WARNING] skipping duplicate package `duplicate` found at `[ROOT]/home/.cargo/git/checkouts/dep-[HASH]/caf7f52/duplicate2`
1286+
[WARNING] skipping duplicate package `duplicate v0.5.0 ([ROOTURL]/dep#[..])`:
1287+
[ROOT]/home/.cargo/git/checkouts/dep-[HASH]/[..]/duplicate2/Cargo.toml
1288+
in favor of [ROOT]/home/.cargo/git/checkouts/dep-[HASH]/[..]/duplicate1/Cargo.toml
1289+
12851290
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
12861291
[RUNNING] `target/debug/foo[EXE]`
12871292

0 commit comments

Comments
 (0)