Skip to content

Commit 2cde464

Browse files
committed
sparse-checkout: add --verbose option to 'clean'
The 'git sparse-checkout clean' subcommand is focused on directories, deleting any tracked sparse directories to clean up the worktree and make the sparse index feature work optimally. However, this directory-focused approach can leave users wondering why those directories exist at all. In my experience, these files are left over due to ignore or exclude patterns, Windows file handles, or possibly merge conflict resolutions. Add a new '--verbose' option for users to see all the files that are being deleted (with '--force') or would be deleted (with '--dry-run'). Based on usage, users may request further context on this list of files for states such as tracked/untracked, unstaged/staged/conflicted, etc. Signed-off-by: Derrick Stolee <[email protected]>
1 parent 6b29dda commit 2cde464

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

Documentation/git-sparse-checkout.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ The `--dry-run` option will list the directories that would be removed
136136
without deleting them. Running in this mode can be helpful to predict the
137137
behavior of the clean comand or to determine which kinds of files are left
138138
in the sparse directories.
139+
+
140+
The `--verbose` option will list every file within the directories that
141+
are considered for removal. This option is helpful to determine if those
142+
files are actually important or perhaps to explain why the directory is
143+
still present despite the current sparse-checkout.
139144

140145
'disable'::
141146
Disable the `core.sparseCheckout` config setting, and restore the

builtin/sparse-checkout.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,26 @@ static char const * const builtin_sparse_checkout_clean_usage[] = {
930930
NULL
931931
};
932932

933+
static int list_file_iterator(const char *path, const void *data)
934+
{
935+
const char *msg = data;
936+
937+
printf(msg, path);
938+
return 0;
939+
}
940+
941+
static void list_every_file_in_dir(const char *msg,
942+
const char *directory)
943+
{
944+
struct strbuf path = STRBUF_INIT;
945+
946+
strbuf_addstr(&path, directory);
947+
fprintf(stderr, "list every file in %s\n", directory);
948+
949+
for_each_file_in_dir(&path, list_file_iterator, msg);
950+
strbuf_release(&path);
951+
}
952+
933953
static const char *msg_remove = N_("Removing %s\n");
934954
static const char *msg_would_remove = N_("Would remove %s\n");
935955

@@ -940,12 +960,13 @@ static int sparse_checkout_clean(int argc, const char **argv,
940960
struct strbuf full_path = STRBUF_INIT;
941961
const char *msg = msg_remove;
942962
size_t worktree_len;
943-
int force = 0, dry_run = 0;
963+
int force = 0, dry_run = 0, verbose = 0;
944964
int require_force = 1;
945965

946966
struct option builtin_sparse_checkout_clean_options[] = {
947967
OPT__DRY_RUN(&dry_run, N_("dry run")),
948968
OPT__FORCE(&force, N_("force"), PARSE_OPT_NOCOMPLETE),
969+
OPT__VERBOSE(&verbose, N_("report each affected file, not just directories")),
949970
OPT_END(),
950971
};
951972

@@ -987,7 +1008,10 @@ static int sparse_checkout_clean(int argc, const char **argv,
9871008
if (!is_directory(full_path.buf))
9881009
continue;
9891010

990-
printf(msg, ce->name);
1011+
if (verbose)
1012+
list_every_file_in_dir(msg, ce->name);
1013+
else
1014+
printf(msg, ce->name);
9911015

9921016
if (dry_run <= 0 &&
9931017
remove_dir_recursively(&full_path, 0))

t/t1091-sparse-checkout-builtin.sh

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,11 +1053,11 @@ test_expect_success 'check-rules null termination' '
10531053
test_expect_success 'clean' '
10541054
git -C repo sparse-checkout set --cone deep/deeper1 &&
10551055
git -C repo sparse-checkout reapply &&
1056-
mkdir repo/deep/deeper2 repo/folder1 &&
1056+
mkdir -p repo/deep/deeper2 repo/folder1/extra/inside &&
10571057
10581058
# Add untracked files
10591059
touch repo/deep/deeper2/file &&
1060-
touch repo/folder1/file &&
1060+
touch repo/folder1/extra/inside/file &&
10611061
10621062
test_must_fail git -C repo sparse-checkout clean 2>err &&
10631063
grep "refusing to clean" err &&
@@ -1074,7 +1074,15 @@ test_expect_success 'clean' '
10741074
git -C repo sparse-checkout clean --dry-run >out &&
10751075
test_cmp expect out &&
10761076
test_path_exists repo/deep/deeper2 &&
1077-
test_path_exists repo/folder1 &&
1077+
test_path_exists repo/folder1/extra/inside/file &&
1078+
1079+
cat >expect <<-\EOF &&
1080+
Would remove deep/deeper2/file
1081+
Would remove folder1/extra/inside/file
1082+
EOF
1083+
1084+
git -C repo sparse-checkout clean --dry-run --verbose >out &&
1085+
test_cmp expect out &&
10781086
10791087
cat >expect <<-\EOF &&
10801088
Removing deep/deeper2/

0 commit comments

Comments
 (0)