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 <worldhello.net@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									e9a820cefd
								
							
						
					
					
						commit
						396049e5fb
					
				|  | @ -15,6 +15,7 @@ | |||
| #include "quote.h" | ||||
|  | ||||
| static int force = -1; /* unset */ | ||||
| static struct string_list del_list = STRING_LIST_INIT_DUP; | ||||
|  | ||||
| static const char *const builtin_clean_usage[] = { | ||||
| 	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) | |||
| 	int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0; | ||||
| 	int ignored_only = 0, config_set = 0, errors = 0, gone = 1; | ||||
| 	int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT; | ||||
| 	struct strbuf directory = STRBUF_INIT; | ||||
| 	struct strbuf abs_path = STRBUF_INIT; | ||||
| 	struct dir_struct dir; | ||||
| 	static const char **pathspec; | ||||
| 	struct strbuf buf = STRBUF_INIT; | ||||
| 	struct string_list exclude_list = STRING_LIST_INIT_NODUP; | ||||
| 	struct exclude_list *el; | ||||
| 	struct string_list_item *item; | ||||
| 	const char *qname; | ||||
| 	char *seen = NULL; | ||||
| 	struct option options[] = { | ||||
|  | @ -223,6 +225,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) | |||
| 		int matches = 0; | ||||
| 		struct cache_entry *ce; | ||||
| 		struct stat st; | ||||
| 		const char *rel; | ||||
|  | ||||
| 		/* | ||||
| 		 * Remove the '/' at the end that directory | ||||
|  | @ -242,13 +245,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix) | |||
| 				continue; /* Yup, this one exists unmerged */ | ||||
| 		} | ||||
|  | ||||
| 		/* | ||||
| 		 * we might have removed this as part of earlier | ||||
| 		 * recursive directory removal, so lstat() here could | ||||
| 		 * fail with ENOENT. | ||||
| 		 */ | ||||
| 		if (lstat(ent->name, &st)) | ||||
| 			continue; | ||||
| 			die_errno("Cannot lstat '%s'", ent->name); | ||||
|  | ||||
| 		if (pathspec) { | ||||
| 			memset(seen, 0, argc > 0 ? argc : 1); | ||||
|  | @ -257,33 +255,61 @@ int cmd_clean(int argc, const char **argv, const char *prefix) | |||
| 		} | ||||
|  | ||||
| 		if (S_ISDIR(st.st_mode)) { | ||||
| 			strbuf_addstr(&directory, ent->name); | ||||
| 			if (remove_directories || (matches == MATCHED_EXACTLY)) { | ||||
| 				if (remove_dirs(&directory, prefix, rm_flags, dry_run, quiet, &gone)) | ||||
| 					errors++; | ||||
| 				if (gone && !quiet) { | ||||
| 					qname = quote_path_relative(directory.buf, prefix, &buf); | ||||
| 					printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname); | ||||
| 				} | ||||
| 				rel = relative_path(ent->name, prefix, &buf); | ||||
| 				string_list_append(&del_list, rel); | ||||
| 			} | ||||
| 			strbuf_reset(&directory); | ||||
| 		} else { | ||||
| 			if (pathspec && !matches) | ||||
| 				continue; | ||||
| 			res = dry_run ? 0 : unlink(ent->name); | ||||
| 			rel = relative_path(ent->name, prefix, &buf); | ||||
| 			string_list_append(&del_list, rel); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* TODO: do interactive git-clean here, which will modify del_list */ | ||||
|  | ||||
| 	for_each_string_list_item(item, &del_list) { | ||||
| 		struct stat st; | ||||
|  | ||||
| 		if (prefix) | ||||
| 			strbuf_addstr(&abs_path, prefix); | ||||
|  | ||||
| 		strbuf_addstr(&abs_path, item->string); | ||||
|  | ||||
| 		/* | ||||
| 		 * we might have removed this as part of earlier | ||||
| 		 * recursive directory removal, so lstat() here could | ||||
| 		 * fail with ENOENT. | ||||
| 		 */ | ||||
| 		if (lstat(abs_path.buf, &st)) | ||||
| 			continue; | ||||
|  | ||||
| 		if (S_ISDIR(st.st_mode)) { | ||||
| 			if (remove_dirs(&abs_path, prefix, rm_flags, dry_run, quiet, &gone)) | ||||
| 				errors++; | ||||
| 			if (gone && !quiet) { | ||||
| 				qname = quote_path_relative(item->string, NULL, &buf); | ||||
| 				printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname); | ||||
| 			} | ||||
| 		} else { | ||||
| 			res = dry_run ? 0 : unlink(abs_path.buf); | ||||
| 			if (res) { | ||||
| 				qname = quote_path_relative(ent->name, prefix, &buf); | ||||
| 				qname = quote_path_relative(item->string, NULL, &buf); | ||||
| 				warning(_(msg_warn_remove_failed), qname); | ||||
| 				errors++; | ||||
| 			} else if (!quiet) { | ||||
| 				qname = quote_path_relative(ent->name, prefix, &buf); | ||||
| 				qname = quote_path_relative(item->string, NULL, &buf); | ||||
| 				printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname); | ||||
| 			} | ||||
| 		} | ||||
| 		strbuf_reset(&abs_path); | ||||
| 	} | ||||
| 	free(seen); | ||||
|  | ||||
| 	strbuf_release(&directory); | ||||
| 	strbuf_release(&abs_path); | ||||
| 	strbuf_release(&buf); | ||||
| 	string_list_clear(&del_list, 0); | ||||
| 	string_list_clear(&exclude_list, 0); | ||||
| 	return (errors != 0); | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Jiang Xin
						Jiang Xin