Skip to content

Commit ff4b95c

Browse files
committed
gix clean is interruptable
1 parent 26a5f86 commit ff4b95c

File tree

1 file changed

+28
-5
lines changed

1 file changed

+28
-5
lines changed

gitoxide-core/src/repository/clean.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ pub(crate) mod function {
2727
use gix::dir::entry::{Kind, Status};
2828
use gix::dir::walk::EmissionMode::CollapseDirectory;
2929
use gix::dir::walk::ForDeletionMode::*;
30+
use gix::dir::{walk, EntryRef};
3031
use std::borrow::Cow;
32+
use std::path::Path;
3133

3234
pub fn clean(
3335
repo: gix::Repository,
@@ -37,7 +39,7 @@ pub(crate) mod function {
3739
Options {
3840
debug,
3941
format,
40-
execute,
42+
mut execute,
4143
ignored,
4244
precious,
4345
directories,
@@ -55,7 +57,7 @@ pub(crate) mod function {
5557

5658
let index = repo.index()?;
5759
let has_patterns = !patterns.is_empty();
58-
let mut collect = gix::dir::walk::delegate::Collect::default();
60+
let mut collect = InterruptableCollect::default();
5961
let collapse_directories = CollapseDirectory;
6062
let options = repo
6163
.dirwalk_options()?
@@ -74,14 +76,14 @@ pub(crate) mod function {
7476
.emit_ignored(Some(collapse_directories))
7577
.emit_empty_directories(true);
7678
repo.dirwalk(&index, patterns, options, &mut collect)?;
77-
let prefix = repo.prefix()?.expect("worktree and valid current dir");
79+
let prefix = repo.prefix()?.unwrap_or(Path::new(""));
7880
let prefix_len = if prefix.as_os_str().is_empty() {
7981
0
8082
} else {
8183
prefix.to_str().map_or(0, |s| s.len() + 1 /* slash */)
8284
};
8385

84-
let entries = collect.into_entries_by_path();
86+
let entries = collect.inner.into_entries_by_path();
8587
let mut entries_to_clean = 0;
8688
let mut skipped_directories = 0;
8789
let mut skipped_ignored = 0;
@@ -143,7 +145,7 @@ pub(crate) mod function {
143145
&& gix::discover::is_git(&workdir.join(gix::path::from_bstr(entry.rela_path.as_bstr()))).is_ok()
144146
{
145147
if debug {
146-
writeln!(err, "DBG: upgraded directory '{}' to repository", entry.rela_path).ok();
148+
writeln!(err, "DBG: upgraded directory '{}' to bare repository", entry.rela_path).ok();
147149
}
148150
disk_kind = gix::dir::entry::Kind::Repository;
149151
}
@@ -215,6 +217,9 @@ pub(crate) mod function {
215217
},
216218
)?;
217219

220+
if gix::interrupt::is_triggered() {
221+
execute = false;
222+
}
218223
if execute {
219224
let path = workdir.join(gix::path::from_bstr(entry.rela_path));
220225
if disk_kind.is_dir() {
@@ -286,7 +291,25 @@ pub(crate) mod function {
286291
} else {
287292
writeln!(err, "Nothing to clean{}", wrap_in_parens(make_msg()))?;
288293
}
294+
if gix::interrupt::is_triggered() {
295+
writeln!(err, "Result may be incomplete as it was interrupted")?;
296+
}
289297
}
290298
Ok(())
291299
}
300+
301+
#[derive(Default)]
302+
struct InterruptableCollect {
303+
inner: gix::dir::walk::delegate::Collect,
304+
}
305+
306+
impl gix::dir::walk::Delegate for InterruptableCollect {
307+
fn emit(&mut self, entry: EntryRef<'_>, collapsed_directory_status: Option<Status>) -> walk::Action {
308+
let res = self.inner.emit(entry, collapsed_directory_status);
309+
if gix::interrupt::is_triggered() {
310+
return walk::Action::Cancel;
311+
}
312+
res
313+
}
314+
}
292315
}

0 commit comments

Comments
 (0)