Skip to content

Commit 9bf9149

Browse files
committed
Use the new dirwalk iterator for comparable ergonomics
1 parent 5312586 commit 9bf9149

File tree

1 file changed

+46
-131
lines changed

1 file changed

+46
-131
lines changed

src/cargo/sources/path.rs

Lines changed: 46 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use anyhow::Context as _;
1414
use cargo_util::paths;
1515
use filetime::FileTime;
1616
use gix::bstr::ByteVec;
17+
use gix::dir::entry::Status;
1718
use ignore::gitignore::GitignoreBuilder;
1819
use tracing::{trace, warn};
1920
use walkdir::WalkDir;
@@ -475,7 +476,6 @@ impl<'gctx> PathSource<'gctx> {
475476
repo: &gix::Repository,
476477
filter: &dyn Fn(&Path, bool) -> bool,
477478
) -> CargoResult<Vec<PathBuf>> {
478-
use gix::dir::entry::Status;
479479
warn!("list_files_gix {}", pkg.package_id());
480480
let options = repo
481481
.dirwalk_options()?
@@ -521,129 +521,45 @@ impl<'gctx> PathSource<'gctx> {
521521
};
522522
include.to_mut().insert_str(0, ":/");
523523

524-
vec![include, exclude]
524+
vec![include.into_owned(), exclude.into_owned()]
525525
};
526526

527-
let mut delegate = Delegate::new(self, pkg, pkg_path, root, filter)?;
528-
repo.dirwalk(
529-
&index,
530-
pathspec,
531-
&Default::default(),
532-
options,
533-
&mut delegate,
534-
)?;
535-
536-
let (mut files, mut subpackages_found) = delegate.into_result()?;
537-
// Append all normal files that might be tracked in `target/`.
538-
for entry in index
539-
.prefixed_entries(target_prefix.as_ref())
540-
.unwrap_or_default()
541-
.iter()
542-
// probably not needed as conflicts prevent this to run, but let's be explicit.
543-
.filter(|entry| entry.stage() == 0)
544-
{
545-
handle_path(
546-
entry.path(&index),
547-
// Do not trust what's recorded in the index, enforce checking the disk.
548-
// This traversal is not part of a `status()`, and tracking things in `target/`
549-
// is rare.
550-
None,
551-
root,
552-
pkg,
553-
pkg_path,
554-
self,
555-
&mut files,
556-
&mut subpackages_found,
557-
filter,
558-
)?
559-
}
560-
return Ok(files);
561-
562-
struct Delegate<'a, 'gctx> {
563-
root: &'a Path,
564-
pkg: &'a Package,
565-
pkg_path: &'a Path,
566-
parent: &'a PathSource<'gctx>,
567-
paths: Vec<PathBuf>,
568-
subpackages_found: Vec<PathBuf>,
569-
filter: &'a dyn Fn(&Path, bool) -> bool,
570-
err: Option<anyhow::Error>,
571-
}
572-
573-
impl<'a, 'gctx> gix::dir::walk::Delegate for Delegate<'a, 'gctx> {
574-
fn emit(
575-
&mut self,
576-
entry: gix::dir::EntryRef<'_>,
577-
_collapsed_directory_status: Option<Status>,
578-
) -> gix::dir::walk::Action {
579-
match self.handle_entry(entry) {
580-
Ok(()) => gix::dir::walk::Action::Continue,
581-
Err(e) => {
582-
self.err = Some(e.into());
583-
gix::dir::walk::Action::Cancel
584-
}
585-
}
586-
}
587-
}
588-
589-
impl<'a, 'gctx> Delegate<'a, 'gctx> {
590-
fn new(
591-
parent: &'a PathSource<'gctx>,
592-
pkg: &'a Package,
593-
pkg_path: &'a Path,
594-
root: &'a Path,
595-
filter: &'a dyn Fn(&Path, bool) -> bool,
596-
) -> CargoResult<Self> {
597-
Ok(Self {
598-
root,
599-
pkg,
600-
pkg_path,
601-
parent,
602-
filter,
603-
paths: vec![],
604-
subpackages_found: vec![],
605-
err: None,
527+
let mut files = Vec::<PathBuf>::new();
528+
let mut subpackages_found = Vec::new();
529+
for item in repo
530+
.dirwalk_iter(index.clone(), pathspec, Default::default(), options)?
531+
.filter(|res| {
532+
// Don't include Cargo.lock if it is untracked. Packaging will
533+
// generate a new one as needed.
534+
res.as_ref().map_or(true, |item| {
535+
!(item.entry.status == Status::Untracked
536+
&& item.entry.rela_path == "Cargo.lock")
606537
})
607-
}
608-
609-
fn into_result(self) -> CargoResult<(Vec<PathBuf>, Vec<PathBuf>)> {
610-
match self.err {
611-
None => {
612-
return Ok((self.paths, self.subpackages_found));
613-
}
614-
Some(e) => return Err(e),
615-
}
616-
}
617-
618-
fn handle_entry(&mut self, entry: gix::dir::EntryRef<'_>) -> CargoResult<()> {
619-
if entry.status == Status::Untracked && entry.rela_path.as_ref() == "Cargo.lock" {
620-
return Ok(());
621-
}
622-
handle_path(
623-
entry.rela_path.as_ref(),
624-
entry.disk_kind,
625-
self.root,
626-
self.pkg,
627-
self.pkg_path,
628-
self.parent,
629-
&mut self.paths,
630-
&mut self.subpackages_found,
631-
self.filter,
632-
)
633-
}
634-
}
635-
636-
fn handle_path(
637-
rela_path: &gix::bstr::BStr,
638-
kind: Option<gix::dir::entry::Kind>,
639-
root: &Path,
640-
pkg: &Package,
641-
pkg_path: &Path,
642-
source: &PathSource<'_>,
643-
paths: &mut Vec<PathBuf>,
644-
subpackages_found: &mut Vec<PathBuf>,
645-
filter: &dyn Fn(&Path, bool) -> bool,
646-
) -> CargoResult<()> {
538+
})
539+
.map(|res| res.map(|item| (item.entry.rela_path, item.entry.disk_kind)))
540+
.chain(
541+
// Append entries that might be tracked in `<pkg_root>/target/`.
542+
index
543+
.prefixed_entries(target_prefix.as_ref())
544+
.unwrap_or_default()
545+
.iter()
546+
.filter(|entry| {
547+
// probably not needed as conflicts prevent this to run, but let's be explicit.
548+
entry.stage() == 0
549+
})
550+
.map(|entry| {
551+
(
552+
entry.path(&index).to_owned(),
553+
// Do not trust what's recorded in the index, enforce checking the disk.
554+
// This traversal is not part of a `status()`, and tracking things in `target/`
555+
// is rare.
556+
None,
557+
)
558+
})
559+
.map(Ok),
560+
)
561+
{
562+
let (rela_path, kind) = item?;
647563
let file_path = root.join(gix::path::from_bstr(rela_path));
648564
if file_path.file_name().and_then(|name| name.to_str()) == Some("Cargo.toml") {
649565
// Keep track of all sub-packages found and also strip out all
@@ -652,16 +568,16 @@ impl<'gctx> PathSource<'gctx> {
652568
let path = file_path.parent().unwrap();
653569
if path != pkg_path {
654570
warn!("subpackage found: {}", path.display());
655-
paths.retain(|p| !p.starts_with(path));
571+
files.retain(|p| !p.starts_with(path));
656572
subpackages_found.push(path.to_path_buf());
657-
return Ok(());
573+
continue;
658574
}
659575
}
660576

661577
// If this file is part of any other sub-package we've found so far,
662578
// skip it.
663579
if subpackages_found.iter().any(|p| file_path.starts_with(p)) {
664-
return Ok(());
580+
continue;
665581
}
666582

667583
let is_dir = kind.map_or(false, |kind| {
@@ -679,21 +595,20 @@ impl<'gctx> PathSource<'gctx> {
679595
// .git repositories.
680596
match gix::open_opts(&file_path, gix::open::Options::isolated()) {
681597
Ok(sub_repo) => {
682-
let files = source.list_files_gix(pkg, &sub_repo, filter)?;
683-
paths.extend(files);
598+
files.extend(self.list_files_gix(pkg, &sub_repo, filter)?);
684599
}
685-
_ => {
686-
source.walk(&file_path, paths, false, filter)?;
600+
Err(_) => {
601+
self.walk(&file_path, &mut files, false, filter)?;
687602
}
688603
}
689604
} else if (filter)(&file_path, is_dir) {
690605
assert!(!is_dir);
691-
// We found a file!
692606
warn!(" found {}", file_path.display());
693-
paths.push(file_path);
607+
files.push(file_path);
694608
}
695-
Ok(())
696609
}
610+
611+
return Ok(files);
697612
}
698613

699614
/// Lists files relevant to building this package inside this source by

0 commit comments

Comments
 (0)