Skip to content

Commit b8def77

Browse files
committed
Merge branch 'status'
2 parents a663e9f + 0af2fe6 commit b8def77

File tree

5 files changed

+349
-64
lines changed

5 files changed

+349
-64
lines changed

gitoxide-core/src/repository/clean.rs

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -103,44 +103,24 @@ pub(crate) mod function {
103103
continue;
104104
}
105105

106-
pruned_entries += usize::from(entry.pathspec_match.is_none());
107-
if entry.status.is_pruned() || entry.pathspec_match.is_none() {
108-
continue;
109-
}
110-
let mut disk_kind = entry.disk_kind.expect("present if not pruned");
111-
match disk_kind {
112-
Kind::File | Kind::Symlink => {}
113-
Kind::EmptyDirectory | Kind::Directory | Kind::Repository => {
114-
let keep = directories
115-
|| entry
116-
.pathspec_match
117-
.map_or(false, |m| m != gix::dir::entry::PathspecMatch::Always);
118-
if !keep {
119-
skipped_directories += 1;
120-
if debug {
121-
writeln!(err, "DBG: prune '{}' as -d is missing", entry.rela_path).ok();
122-
}
123-
continue;
124-
}
125-
}
126-
};
127-
128-
let keep = entry
106+
let pathspec_includes_entry = entry
129107
.pathspec_match
130-
.map_or(true, |m| m != gix::dir::entry::PathspecMatch::Excluded);
131-
if !keep {
132-
if debug {
133-
writeln!(err, "DBG: prune '{}' as it is excluded by pathspec", entry.rela_path).ok();
134-
}
108+
.map_or(false, |m| m != gix::dir::entry::PathspecMatch::Excluded);
109+
pruned_entries += usize::from(!pathspec_includes_entry);
110+
if !pathspec_includes_entry && debug {
111+
writeln!(err, "DBG: prune '{}' as it is excluded by pathspec", entry.rela_path).ok();
112+
}
113+
if entry.status.is_pruned() || !pathspec_includes_entry {
135114
continue;
136115
}
137116

117+
let mut disk_kind = entry.disk_kind.expect("present if not pruned");
138118
let keep = match entry.status {
139119
Status::DotGit | Status::Pruned | Status::TrackedExcluded => {
140-
unreachable!("Pruned aren't emitted")
120+
unreachable!("BUG: Pruned are skipped already as their pathspec is always None")
141121
}
142122
Status::Tracked => {
143-
unreachable!("tracked aren't emitted")
123+
unreachable!("BUG: tracked aren't emitted")
144124
}
145125
Status::Ignored(gix::ignore::Kind::Expendable) => {
146126
skipped_ignored += usize::from(!ignored);
@@ -168,18 +148,30 @@ pub(crate) mod function {
168148
disk_kind = gix::dir::entry::Kind::Repository;
169149
}
170150

171-
let is_ignored = matches!(entry.status, gix::dir::entry::Status::Ignored(_));
172-
let display_path = entry.rela_path[prefix_len..].as_bstr();
173-
if (!repositories || is_ignored) && disk_kind == gix::dir::entry::Kind::Repository {
174-
if !is_ignored {
175-
skipped_repositories += 1;
151+
match disk_kind {
152+
Kind::File | Kind::Symlink => {}
153+
Kind::EmptyDirectory | Kind::Directory => {
154+
if !directories {
155+
skipped_directories += 1;
156+
if debug {
157+
writeln!(err, "DBG: prune '{}' as -d is missing", entry.rela_path).ok();
158+
}
159+
continue;
160+
}
176161
}
177-
if debug {
178-
writeln!(err, "DBG: skipped repository at '{display_path}'")?;
162+
Kind::Repository => {
163+
if !repositories {
164+
skipped_repositories += 1;
165+
if debug {
166+
writeln!(err, "DBG: skipped repository at '{}'", entry.rela_path)?;
167+
}
168+
continue;
169+
}
179170
}
180-
continue;
181-
}
171+
};
182172

173+
let is_ignored = matches!(entry.status, gix::dir::entry::Status::Ignored(_));
174+
let display_path = entry.rela_path[prefix_len..].as_bstr();
183175
if disk_kind == gix::dir::entry::Kind::Directory {
184176
saw_ignored_directory |= is_ignored;
185177
saw_untracked_directory |= entry.status == gix::dir::entry::Status::Untracked;
@@ -194,8 +186,8 @@ pub(crate) mod function {
194186
Cow::Owned(format!(
195187
"({})",
196188
match kind {
197-
gix::ignore::Kind::Precious => "$",
198-
gix::ignore::Kind::Expendable => "",
189+
gix::ignore::Kind::Precious => "💲",
190+
gix::ignore::Kind::Expendable => "🗑️",
199191
}
200192
))
201193
}
@@ -210,10 +202,16 @@ pub(crate) mod function {
210202
},
211203
},
212204
maybe = if execute { "removing" } else { "WOULD remove" },
213-
suffix = if disk_kind == gix::dir::entry::Kind::Repository {
214-
" repository"
215-
} else {
216-
""
205+
suffix = match disk_kind {
206+
Kind::File | Kind::Symlink | Kind::Directory => {
207+
""
208+
}
209+
Kind::EmptyDirectory => {
210+
" empty"
211+
}
212+
Kind::Repository => {
213+
" repository"
214+
}
217215
},
218216
)?;
219217

gitoxide-core/src/repository/index/entries.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ pub(crate) mod function {
419419
buf.push_str(" ➡ ");
420420
}
421421
if a.is_excluded {
422-
buf.push_str(" ");
422+
buf.push_str(" 🗑️");
423423
}
424424
if !a.attributes.is_empty() {
425425
buf.push_str(" (");

gix-dir/src/walk/readdir.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub(super) fn recursive(
6666
if can_recurse(current_bstr.as_bstr(), info, opts.for_deletion, delegate) {
6767
let (action, subdir_prevent_collapse) =
6868
recursive(false, current, current_bstr, info, ctx, opts, delegate, out, state)?;
69-
prevent_collapse = subdir_prevent_collapse;
69+
prevent_collapse |= subdir_prevent_collapse;
7070
if action != Action::Continue {
7171
break;
7272
}
@@ -158,6 +158,7 @@ impl Mark {
158158
} else {
159159
dir_info.disk_kind
160160
},
161+
pathspec_match: filter_dir_pathspec(dir_info.pathspec_match),
161162
..dir_info
162163
};
163164
if opts.should_hold(empty_info.status) {
@@ -174,18 +175,10 @@ impl Mark {
174175
}
175176
} else if *prevent_collapse {
176177
self.emit_all_held(state, opts, out, delegate)
177-
} else if let Some(action) = self.try_collapse(
178-
dir_rela_path,
179-
dir_info,
180-
state,
181-
prevent_collapse,
182-
out,
183-
opts,
184-
ctx,
185-
delegate,
186-
) {
178+
} else if let Some(action) = self.try_collapse(dir_rela_path, dir_info, state, out, opts, ctx, delegate) {
187179
action
188180
} else {
181+
*prevent_collapse = true;
189182
self.emit_all_held(state, opts, out, delegate)
190183
}
191184
}
@@ -213,7 +206,6 @@ impl Mark {
213206
dir_rela_path: &BStr,
214207
dir_info: classify::Outcome,
215208
state: &mut State,
216-
prevent_collapse: &mut bool,
217209
out: &mut walk::Outcome,
218210
opts: Options,
219211
ctx: &mut Context<'_>,
@@ -229,7 +221,6 @@ impl Mark {
229221
{
230222
entries += 1;
231223
if kind == Some(entry::Kind::Repository) {
232-
*prevent_collapse = true;
233224
return None;
234225
}
235226
if pathspec_match.map_or(false, |m| {
@@ -287,12 +278,10 @@ impl Mark {
287278
.filter_map(|e| e.pathspec_match)
288279
.max()
289280
.or_else(|| {
290-
// Only take directory matches for value if they are above the 'guessed' ones.
281+
// Only take directory matches as value if they are above the 'guessed' ones.
291282
// Otherwise we end up with seemingly matched entries in the parent directory which
292283
// affects proper folding.
293-
dir_info
294-
.pathspec_match
295-
.filter(|m| matches!(m, PathspecMatch::WildcardMatch | PathspecMatch::Verbatim))
284+
filter_dir_pathspec(dir_info.pathspec_match)
296285
});
297286
let mut removed_without_emitting = 0;
298287
let mut action = Action::Continue;
@@ -317,6 +306,15 @@ impl Mark {
317306
}
318307
}
319308

309+
fn filter_dir_pathspec(current: Option<PathspecMatch>) -> Option<PathspecMatch> {
310+
current.filter(|m| {
311+
matches!(
312+
m,
313+
PathspecMatch::Always | PathspecMatch::WildcardMatch | PathspecMatch::Verbatim
314+
)
315+
})
316+
}
317+
320318
impl Options {
321319
fn should_hold(&self, status: entry::Status) -> bool {
322320
if status.is_pruned() {

gix-dir/tests/fixtures/many.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ cp -R ignored-dir ignored-dir-with-nested-bare-repository
5757
git init --bare bare
5858
)
5959

60+
cp -R ignored-dir-with-nested-bare-repository ignored-dir-nested-minimal
61+
(cd ignored-dir-nested-minimal
62+
(cd bare
63+
rm -Rf hooks config description
64+
)
65+
(cd dir/subdir/nested-bare
66+
rm -Rf refs hooks config description
67+
)
68+
)
69+
6070
mkdir untracked-hidden-bare
6171
(cd untracked-hidden-bare
6272
mkdir subdir
@@ -245,6 +255,17 @@ git init expendable-and-precious
245255
git commit -m "init"
246256
)
247257

258+
git init expendable-and-precious-nested-in-ignored-dir
259+
(cd expendable-and-precious-nested-in-ignored-dir
260+
echo 'ignored/' > .gitignore
261+
git add .gitignore && git commit -m "init"
262+
mkdir -p ignored/other
263+
cp -Rv ../expendable-and-precious ignored/d
264+
rm -Rf ignored/d/*-by-filematch ignored/d/some-*
265+
mkdir -p other/ignored && >other/ignored/a
266+
)
267+
268+
248269
mkdir empty-and-untracked-dir
249270
(cd empty-and-untracked-dir
250271
mkdir empty untracked

0 commit comments

Comments
 (0)