[PATCH] clean: Introduce -z for machine readable output

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



-z makes clean output only the names of paths which are or would be
deleted, and separates them with \0.

Use as "xargs -0 -a <(git clean -nz [-d]) rm -ri", e.g., as a quick
"git clean -i".

Signed-off-by: Michael J Gruber <git@xxxxxxxxxxxxxxxxxxxx>
---
Here's an alternative approach to that problem with a complete different attach
vector but a similar purpose. I've been using it for a while, but it's kind of
unpolished. My "git-clean-i" looks like:

--->%---
#!/bin/bash
xargs -0 -a <(git clean -n -z "$@") rm -ri
--->%---

 Documentation/git-clean.txt |  9 ++++++++-
 builtin/clean.c             | 27 +++++++++++++++++++--------
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index bdc3ab8..849e775 100644
--- a/Documentation/git-clean.txt
+++ b/Documentation/git-clean.txt
@@ -8,7 +8,7 @@ git-clean - Remove untracked files from the working tree
 SYNOPSIS
 --------
 [verse]
-'git clean' [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <path>...
+'git clean' [-d] [-f] [-n] [-q] [-z] [-e <pattern>] [-x | -X] [--] <path>...
 
 DESCRIPTION
 -----------
@@ -63,6 +63,13 @@ OPTIONS
 	Remove only files ignored by Git.  This may be useful to rebuild
 	everything from scratch, but keep manually created files.
 
+-z::
+	Use machine readable output for (to be) removed paths: Output the paths
+	which are or would be removed only (without extra wording) and
+	separate them with \0.
++
+This does not imply `-n` but can be combined with it.
+
 SEE ALSO
 --------
 linkgit:gitignore[5]
diff --git a/builtin/clean.c b/builtin/clean.c
index 04e396b..0ebba24 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -41,8 +41,18 @@ static int exclude_cb(const struct option *opt, const char *arg, int unset)
 	return 0;
 }
 
+void write_name(const char *fmt, const char *name, int nul_terminated)
+{
+	if (nul_terminated) {
+		fputs(name, stdout);
+		fputc(0, stdout);
+	} else {
+		printf(fmt, name);
+	}
+}
+
 static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
-		int dry_run, int quiet, int *dir_gone)
+		int dry_run, int quiet, int *dir_gone, int nul_terminated)
 {
 	DIR *dir;
 	struct strbuf quoted = STRBUF_INIT;
@@ -57,8 +67,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
 			!resolve_gitlink_ref(path->buf, "HEAD", submodule_head)) {
 		if (!quiet) {
 			quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
-			printf(dry_run ?  _(msg_would_skip_git_dir) : _(msg_skip_git_dir),
-					quoted.buf);
+			write_name(dry_run ?  _(msg_would_skip_git_dir) : _(msg_skip_git_dir),
+					quoted.buf, nul_terminated);
 		}
 
 		*dir_gone = 0;
@@ -91,7 +101,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
 		if (lstat(path->buf, &st))
 			; /* fall thru */
 		else if (S_ISDIR(st.st_mode)) {
-			if (remove_dirs(path, prefix, force_flag, dry_run, quiet, &gone))
+			if (remove_dirs(path, prefix, force_flag, dry_run, quiet, &gone, nul_terminated))
 				ret = 1;
 			if (gone) {
 				quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
@@ -136,7 +146,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
 
 	if (!*dir_gone && !quiet) {
 		for (i = 0; i < dels.nr; i++)
-			printf(dry_run ?  _(msg_would_remove) : _(msg_remove), dels.items[i].string);
+			write_name(dry_run ?  _(msg_would_remove) : _(msg_remove), dels.items[i].string, nul_terminated);
 	}
 	string_list_clear(&dels, 0);
 	return ret;
@@ -146,7 +156,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 {
 	int i, res;
 	int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
-	int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
+	int ignored_only = 0, config_set = 0, errors = 0, gone = 1, nul_terminated = 0;
 	int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
 	struct strbuf directory = STRBUF_INIT;
 	struct dir_struct dir;
@@ -167,6 +177,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 		OPT_BOOLEAN('x', NULL, &ignored, N_("remove ignored files, too")),
 		OPT_BOOLEAN('X', NULL, &ignored_only,
 				N_("remove only ignored files")),
+		OPT_BOOLEAN('z', NULL, &nul_terminated, "(actually or to be) removed paths are separated with NUL character"),
 		OPT_END()
 	};
 
@@ -259,7 +270,7 @@ 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))
+				if (remove_dirs(&directory, prefix, rm_flags, dry_run, quiet, &gone, nul_terminated))
 					errors++;
 				if (gone && !quiet) {
 					qname = quote_path_relative(directory.buf, directory.len, &buf, prefix);
@@ -277,7 +288,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 				errors++;
 			} else if (!quiet) {
 				qname = quote_path_relative(ent->name, -1, &buf, prefix);
-				printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
+				write_name(dry_run ? _(msg_would_remove) : _(msg_remove), qname, nul_terminated);
 			}
 		}
 	}
-- 
1.8.3.rc0.297.g8c90ec5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]