Skip to content

Commit 671c8c8

Browse files
committed
feat: add gix clean --patterns-for-entries|-m to help with wildcards.
1 parent accdf22 commit 671c8c8

File tree

3 files changed

+42
-6
lines changed

3 files changed

+42
-6
lines changed

gitoxide-core/src/repository/clean.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub struct Options {
1515
pub precious: bool,
1616
pub directories: bool,
1717
pub repositories: bool,
18+
pub patterns_for_entries: bool,
1819
pub skip_hidden_repositories: Option<FindRepository>,
1920
pub find_untracked_repositories: FindRepository,
2021
}
@@ -46,6 +47,7 @@ pub(crate) mod function {
4647
repositories,
4748
skip_hidden_repositories,
4849
find_untracked_repositories,
50+
patterns_for_entries,
4951
}: Options,
5052
) -> anyhow::Result<()> {
5153
if format != OutputFormat::Human {
@@ -56,7 +58,8 @@ pub(crate) mod function {
5658
};
5759

5860
let index = repo.index_or_empty()?;
59-
let has_patterns = !patterns.is_empty();
61+
let patterns_for_dirwalk = !patterns_for_entries;
62+
let has_patterns = patterns_for_dirwalk && !patterns.is_empty();
6063
let mut collect = InterruptableCollect::default();
6164
let collapse_directories = CollapseDirectory;
6265
let options = repo
@@ -76,9 +79,29 @@ pub(crate) mod function {
7679
.emit_ignored(Some(collapse_directories))
7780
.empty_patterns_match_prefix(true)
7881
.emit_empty_directories(true);
79-
repo.dirwalk(&index, patterns, options, &mut collect)?;
80-
let prefix = repo.prefix()?.unwrap_or(Path::new(""));
82+
repo.dirwalk(
83+
&index,
84+
if patterns_for_dirwalk {
85+
patterns.clone()
86+
} else {
87+
Vec::new()
88+
},
89+
options,
90+
&mut collect,
91+
)?;
8192

93+
let mut pathspec = if patterns_for_entries {
94+
Some(repo.pathspec(
95+
true,
96+
patterns,
97+
true,
98+
&index,
99+
gix::worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
100+
)?)
101+
} else {
102+
None
103+
};
104+
let prefix = repo.prefix()?.unwrap_or(Path::new(""));
82105
let entries = collect.inner.into_entries_by_path();
83106
let mut entries_to_clean = 0;
84107
let mut skipped_directories = 0;
@@ -101,9 +124,14 @@ pub(crate) mod function {
101124
continue;
102125
}
103126

104-
let pathspec_includes_entry = entry
105-
.pathspec_match
106-
.map_or(false, |m| m != gix::dir::entry::PathspecMatch::Excluded);
127+
let pathspec_includes_entry = match pathspec.as_mut() {
128+
None => entry
129+
.pathspec_match
130+
.map_or(false, |m| m != gix::dir::entry::PathspecMatch::Excluded),
131+
Some(pathspec) => pathspec
132+
.pattern_matching_relative_path(entry.rela_path.as_bstr(), entry.disk_kind.map(|k| k.is_dir()))
133+
.map_or(false, |m| !m.is_excluded()),
134+
};
107135
pruned_entries += usize::from(!pathspec_includes_entry);
108136
if !pathspec_includes_entry && debug {
109137
writeln!(err, "DBG: prune '{}'", entry.rela_path).ok();

src/plumbing/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ pub fn main() -> Result<()> {
155155
directories,
156156
pathspec,
157157
repositories,
158+
patterns_for_entries,
158159
skip_hidden_repositories,
159160
find_untracked_repositories,
160161
}) => prepare_and_run(
@@ -178,6 +179,7 @@ pub fn main() -> Result<()> {
178179
precious,
179180
directories,
180181
repositories,
182+
patterns_for_entries,
181183
skip_hidden_repositories: skip_hidden_repositories.map(Into::into),
182184
find_untracked_repositories: find_untracked_repositories.into(),
183185
},

src/plumbing/options/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,12 @@ pub mod clean {
521521
/// Remove nested repositories.
522522
#[arg(long, short = 'r')]
523523
pub repositories: bool,
524+
/// Patterns are used to match the result of the dirwalk, not for the dirwalk itself.
525+
///
526+
/// Use this if there is trouble using wildcard pathspecs, which affect the directory walk
527+
/// in reasonable, but often unexpected ways.
528+
#[arg(long, short = 'm')]
529+
pub patterns_for_entries: bool,
524530
/// Enter ignored directories to skip repositories contained within.
525531
#[arg(long)]
526532
pub skip_hidden_repositories: Option<FindRepository>,

0 commit comments

Comments
 (0)