Skip to content

Commit b0aa390

Browse files
committed
more natural top-level handling
- when deleting items, we will always list them according to the prefix - when listing items otherwise, the top-level only if the traversal starts in the worktree.
1 parent ec0bcb5 commit b0aa390

File tree

6 files changed

+293
-117
lines changed

6 files changed

+293
-117
lines changed

gix-dir/src/walk/function.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ use crate::{entry, EntryRef};
1818
/// * `ctx` - everything needed to classify the paths seen during the traversal.
1919
/// * `delegate` - an implementation of [`Delegate`] to control details of the traversal and receive its results.
2020
///
21+
/// Returns `(outcome, traversal_root)`, with the `traversal_root` actually being used for the traversal,
22+
/// useful to transform the paths returned for the user. It's always within the `worktree_root`, or the same,
23+
/// but is hard to guess due to additional logic affecting it.
24+
///
2125
/// ### Performance Notes
2226
///
2327
/// In theory, parallel directory traversal can be significantly faster, and what's possible for our current
@@ -40,7 +44,7 @@ pub fn walk(
4044
mut ctx: Context<'_>,
4145
options: Options,
4246
delegate: &mut dyn Delegate,
43-
) -> Result<Outcome, Error> {
47+
) -> Result<(Outcome, PathBuf), Error> {
4448
let root = match ctx.explicit_traversal_root {
4549
Some(root) => root.to_owned(),
4650
None => ctx
@@ -78,12 +82,17 @@ pub fn walk(
7882
&mut out,
7983
delegate,
8084
);
81-
return Ok(out);
85+
return Ok((out, root.to_owned()));
8286
}
8387

8488
let mut state = readdir::State::default();
85-
let _ = readdir::recursive(
86-
true,
89+
let is_top_level = if options.for_deletion.is_some() {
90+
true
91+
} else {
92+
root == worktree_root
93+
};
94+
let (action, _) = readdir::recursive(
95+
is_top_level,
8796
&mut current,
8897
&mut buf,
8998
root_info,
@@ -93,8 +102,12 @@ pub fn walk(
93102
&mut out,
94103
&mut state,
95104
)?;
105+
if action != Action::Cancel {
106+
state.emit_remaining(is_top_level, options, &mut out, delegate);
107+
assert_eq!(state.on_hold.len(), 0, "BUG: after emission, on hold must be empty");
108+
}
96109
gix_trace::debug!(statistics = ?out);
97-
Ok(out)
110+
Ok((out, root.to_owned()))
98111
}
99112

100113
/// Note that we only check symlinks on the way from `worktree_root` to `root`,

gix-dir/src/walk/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ pub struct Context<'a> {
233233
}
234234

235235
/// Additional information collected as outcome of [`walk()`](function::walk()).
236-
#[derive(Default, Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
236+
#[derive(Default, Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
237237
pub struct Outcome {
238238
/// The amount of calls to read the directory contents.
239239
pub read_dir_calls: u32,

gix-dir/src/walk/readdir.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,24 @@ impl State {
125125
is_top_level,
126126
}
127127
}
128+
129+
pub(super) fn emit_remaining(
130+
&mut self,
131+
is_top_level: bool,
132+
opts: Options,
133+
out: &mut walk::Outcome,
134+
delegate: &mut dyn walk::Delegate,
135+
) {
136+
if self.on_hold.is_empty() {
137+
return;
138+
}
139+
140+
_ = Mark {
141+
start_index: 0,
142+
is_top_level,
143+
}
144+
.emit_all_held(self, opts, out, delegate);
145+
}
128146
}
129147

130148
struct Mark {

gix-dir/tests/dir_walk_cwd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn prefixes_work_as_expected() -> gix_testtools::Result {
1313
let root = fixture("only-untracked");
1414
std::env::set_current_dir(root.join("d"))?;
1515
let troot = Path::new("..").join("d");
16-
let (out, entries) = collect(Path::new(".."), Some(&troot), |keep, ctx| {
16+
let ((out, _root), entries) = collect(Path::new(".."), Some(&troot), |keep, ctx| {
1717
walk(Path::new(".."), ctx, options(), keep)
1818
});
1919
assert_eq!(

0 commit comments

Comments
 (0)