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

2013-04-29 Thread Matthieu Moy
Michael J Gruber  writes:

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

My first reaction was: Is it not a job for "git ls-files"?

Actually, you already almost have it:

git clean -d  => git ls-files --exclude-standard --directory -o
git clean -dx => git ls-files -z --exclude-standard --directory -io

OTOH, the "git clean" without -d are not exposed directly AFAICT, and
the set of options of "git clean" may make more sense.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

2013-04-29 Thread Michael J Gruber
-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 
---
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 ] [-x | -X] [--] ...
+'git clean' [-d] [-f] [-n] [-q] [-z] [-e ] [-x | -X] [--] ...
 
 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), 
"ed, 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), "ed, 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(