Skip to content

Commit 06aaa83

Browse files
committed
refactor(source): Delay the duplicate name check
1 parent 7c4fd75 commit 06aaa83

File tree

1 file changed

+47
-30
lines changed

1 file changed

+47
-30
lines changed

src/cargo/sources/path.rs

+47-30
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ pub struct RecursivePathSource<'gctx> {
227227
loaded: bool,
228228
/// Packages that this sources has discovered.
229229
packages: HashMap<PackageId, Vec<Package>>,
230+
warned_duplicate: HashSet<PackageId>,
230231
gctx: &'gctx GlobalContext,
231232
}
232233

@@ -245,6 +246,7 @@ impl<'gctx> RecursivePathSource<'gctx> {
245246
path: root.to_path_buf(),
246247
loaded: false,
247248
packages: Default::default(),
249+
warned_duplicate: Default::default(),
248250
gctx,
249251
}
250252
}
@@ -253,7 +255,13 @@ impl<'gctx> RecursivePathSource<'gctx> {
253255
/// filesystem if package information haven't yet loaded.
254256
pub fn read_packages(&mut self) -> CargoResult<Vec<Package>> {
255257
self.load()?;
256-
Ok(self.packages.iter().map(|(_, v)| v[0].clone()).collect())
258+
Ok(self
259+
.packages
260+
.iter()
261+
.map(|(pkg_id, v)| {
262+
first_package(*pkg_id, v, &mut self.warned_duplicate, self.gctx).clone()
263+
})
264+
.collect())
257265
}
258266

259267
/// List all files relevant to building this package inside this source.
@@ -290,32 +298,6 @@ impl<'gctx> RecursivePathSource<'gctx> {
290298
pub fn load(&mut self) -> CargoResult<()> {
291299
if !self.loaded {
292300
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-
}
319301
self.loaded = true;
320302
}
321303

@@ -337,10 +319,13 @@ impl<'gctx> Source for RecursivePathSource<'gctx> {
337319
f: &mut dyn FnMut(IndexSummary),
338320
) -> Poll<CargoResult<()>> {
339321
self.load()?;
322+
// TODO
340323
for s in self
341324
.packages
342-
.values()
343-
.map(|pkgs| &pkgs[0])
325+
.iter()
326+
.map(|(pkg_id, pkgs)| {
327+
first_package(*pkg_id, pkgs, &mut self.warned_duplicate, self.gctx)
328+
})
344329
.map(|p| p.summary())
345330
{
346331
let matched = match kind {
@@ -371,7 +356,7 @@ impl<'gctx> Source for RecursivePathSource<'gctx> {
371356
trace!("getting packages; id={}", id);
372357
self.load()?;
373358
let pkg = self.packages.get(&id);
374-
pkg.map(|pkgs| pkgs[0].clone())
359+
pkg.map(|pkgs| first_package(id, pkgs, &mut self.warned_duplicate, self.gctx).clone())
375360
.map(MaybePackage::Ready)
376361
.ok_or_else(|| internal(format!("failed to find {} in path source", id)))
377362
}
@@ -415,6 +400,38 @@ impl<'gctx> Source for RecursivePathSource<'gctx> {
415400
}
416401
}
417402

403+
fn first_package<'p>(
404+
pkg_id: PackageId,
405+
pkgs: &'p Vec<Package>,
406+
warned_duplicate: &mut HashSet<PackageId>,
407+
gctx: &GlobalContext,
408+
) -> &'p Package {
409+
if pkgs.len() != 1 && warned_duplicate.insert(pkg_id) {
410+
let ignored = pkgs[1..]
411+
.iter()
412+
// We can assume a package with publish = false isn't intended to be seen
413+
// by users so we can hide the warning about those since the user is unlikely
414+
// to care about those cases.
415+
.filter(|pkg| pkg.publish().is_none())
416+
.collect::<Vec<_>>();
417+
if !ignored.is_empty() {
418+
use std::fmt::Write as _;
419+
420+
let plural = if ignored.len() == 1 { "" } else { "s" };
421+
let mut msg = String::new();
422+
let _ = writeln!(&mut msg, "skipping duplicate package{plural} `{pkg_id}`:");
423+
for ignored in ignored {
424+
let manifest_path = ignored.manifest_path().display();
425+
let _ = writeln!(&mut msg, " {manifest_path}");
426+
}
427+
let manifest_path = pkgs[0].manifest_path().display();
428+
let _ = writeln!(&mut msg, "in favor of {manifest_path}");
429+
let _ = gctx.shell().warn(msg);
430+
}
431+
}
432+
&pkgs[0]
433+
}
434+
418435
/// List all files relevant to building this package inside this source.
419436
///
420437
/// This function will use the appropriate methods to determine the

0 commit comments

Comments
 (0)