Skip to content

Commit 396049e

Browse files
jiangxingitster
authored andcommitted
git-clean: refactor git-clean into two phases
Before introducing interactive git-clean, refactor git-clean operations into two phases: * hold cleaning items in del_list, * and remove them in a separate loop at the end. We will introduce interactive git-clean between the two phases. The interactive git-clean will show what would be done and must confirm before do real cleaning. Signed-off-by: Jiang Xin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e9a820c commit 396049e

File tree

1 file changed

+45
-19
lines changed

1 file changed

+45
-19
lines changed

builtin/clean.c

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "quote.h"
1616

1717
static int force = -1; /* unset */
18+
static struct string_list del_list = STRING_LIST_INIT_DUP;
1819

1920
static const char *const builtin_clean_usage[] = {
2021
N_("git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."),
@@ -148,12 +149,13 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
148149
int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
149150
int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
150151
int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
151-
struct strbuf directory = STRBUF_INIT;
152+
struct strbuf abs_path = STRBUF_INIT;
152153
struct dir_struct dir;
153154
static const char **pathspec;
154155
struct strbuf buf = STRBUF_INIT;
155156
struct string_list exclude_list = STRING_LIST_INIT_NODUP;
156157
struct exclude_list *el;
158+
struct string_list_item *item;
157159
const char *qname;
158160
char *seen = NULL;
159161
struct option options[] = {
@@ -223,6 +225,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
223225
int matches = 0;
224226
struct cache_entry *ce;
225227
struct stat st;
228+
const char *rel;
226229

227230
/*
228231
* Remove the '/' at the end that directory
@@ -242,13 +245,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
242245
continue; /* Yup, this one exists unmerged */
243246
}
244247

245-
/*
246-
* we might have removed this as part of earlier
247-
* recursive directory removal, so lstat() here could
248-
* fail with ENOENT.
249-
*/
250248
if (lstat(ent->name, &st))
251-
continue;
249+
die_errno("Cannot lstat '%s'", ent->name);
252250

253251
if (pathspec) {
254252
memset(seen, 0, argc > 0 ? argc : 1);
@@ -257,33 +255,61 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
257255
}
258256

259257
if (S_ISDIR(st.st_mode)) {
260-
strbuf_addstr(&directory, ent->name);
261258
if (remove_directories || (matches == MATCHED_EXACTLY)) {
262-
if (remove_dirs(&directory, prefix, rm_flags, dry_run, quiet, &gone))
263-
errors++;
264-
if (gone && !quiet) {
265-
qname = quote_path_relative(directory.buf, prefix, &buf);
266-
printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
267-
}
259+
rel = relative_path(ent->name, prefix, &buf);
260+
string_list_append(&del_list, rel);
268261
}
269-
strbuf_reset(&directory);
270262
} else {
271263
if (pathspec && !matches)
272264
continue;
273-
res = dry_run ? 0 : unlink(ent->name);
265+
rel = relative_path(ent->name, prefix, &buf);
266+
string_list_append(&del_list, rel);
267+
}
268+
}
269+
270+
/* TODO: do interactive git-clean here, which will modify del_list */
271+
272+
for_each_string_list_item(item, &del_list) {
273+
struct stat st;
274+
275+
if (prefix)
276+
strbuf_addstr(&abs_path, prefix);
277+
278+
strbuf_addstr(&abs_path, item->string);
279+
280+
/*
281+
* we might have removed this as part of earlier
282+
* recursive directory removal, so lstat() here could
283+
* fail with ENOENT.
284+
*/
285+
if (lstat(abs_path.buf, &st))
286+
continue;
287+
288+
if (S_ISDIR(st.st_mode)) {
289+
if (remove_dirs(&abs_path, prefix, rm_flags, dry_run, quiet, &gone))
290+
errors++;
291+
if (gone && !quiet) {
292+
qname = quote_path_relative(item->string, NULL, &buf);
293+
printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
294+
}
295+
} else {
296+
res = dry_run ? 0 : unlink(abs_path.buf);
274297
if (res) {
275-
qname = quote_path_relative(ent->name, prefix, &buf);
298+
qname = quote_path_relative(item->string, NULL, &buf);
276299
warning(_(msg_warn_remove_failed), qname);
277300
errors++;
278301
} else if (!quiet) {
279-
qname = quote_path_relative(ent->name, prefix, &buf);
302+
qname = quote_path_relative(item->string, NULL, &buf);
280303
printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
281304
}
282305
}
306+
strbuf_reset(&abs_path);
283307
}
284308
free(seen);
285309

286-
strbuf_release(&directory);
310+
strbuf_release(&abs_path);
311+
strbuf_release(&buf);
312+
string_list_clear(&del_list, 0);
287313
string_list_clear(&exclude_list, 0);
288314
return (errors != 0);
289315
}

0 commit comments

Comments
 (0)