Hi, this is the second version of my patch series that introduces a new NUL terminated output format to git-cat-file(1) in order to make its output unambiguously parsable in the case where the input contains newlines. Changes compared to v1: - Improved the commit subject of v5 to mention that the new option changes both input and output to be NUL delimited. - Extended the commit message to make a better case for why `-Z` changes both input and output format to be NUL terminated, instead of having `-z` change the input and `-Z` change the output format. - The `-Z` option is now sorted before `-z` in git-cat-file(1). - The `-z` option is now deprecated "even more", where it is hidden from the synopsis as well as from the `-h` output. - A small change to pass the delimiter to `batch_write()` directly instead of storing it in a temporary array first. Thanks for your feedback, Junio and Phillip! Patrick Patrick Steinhardt (5): t1006: don't strip timestamps from expected results t1006: modernize test style to use `test_cmp` strbuf: provide CRLF-aware helper to read until a specified delimiter cat-file: simplify reading from standard input cat-file: introduce option to delimit input and output with NUL Documentation/git-cat-file.txt | 15 +- builtin/cat-file.c | 85 +++++------ strbuf.c | 11 +- strbuf.h | 12 ++ t/t1006-cat-file.sh | 249 +++++++++++++++++++++------------ 5 files changed, 233 insertions(+), 139 deletions(-) Range-diff against v1: 1: 5c8b4a1d70 = 1: 5c8b4a1d70 t1006: don't strip timestamps from expected results 2: 251fc2a387 = 2: 251fc2a387 t1006: modernize test style to use `test_cmp` 3: 8127eeac97 = 3: 8127eeac97 strbuf: provide CRLF-aware helper to read until a specified delimiter 4: e7cba8dc4c = 4: e7cba8dc4c cat-file: simplify reading from standard input 5: 07a7c34615 ! 5: 79ed618c84 cat-file: Introduce new option to delimit output with NUL characters @@ Metadata Author: Patrick Steinhardt ## Commit message ## - cat-file: Introduce new option to delimit output with NUL characters + cat-file: introduce option to delimit input and output with NUL In db9d67f2e9 (builtin/cat-file.c: support NUL-delimited input with `-z`, 2022-07-22), we have introduced a new mode to read the input via @@ Commit message given that revisions containing newlines are quite exotic. Instead, introduce a new option `-Z` that switches to NUL-delimited - input and output. The old `-z` option is marked as deprecated with a - hint that its output may become unparsable. + input and output. While this new option could arguably only switch the + output format to be NUL-delimited, the consequence would be that users + have to always specify both `-z` and `-Z` when the input may contain + newlines. On the other hand, if the user knows that there never will be + newlines in the input, they don't have to use either of those options. + There is thus no usecase that would warrant treating input and output + format separately, which is why we instead opt to "do the right thing" + and have `-Z` mean to NUL-terminate both formats. + + The old `-z` option is marked as deprecated with a hint that its output + may become unparsable. It is thus hidden both from the synopsis as well + as the command's help output. Co-authored-by: Toon Claes Signed-off-by: Patrick Steinhardt @@ Documentation/git-cat-file.txt: SYNOPSIS 'git cat-file' (--batch | --batch-check | --batch-command) [--batch-all-objects] [--buffer] [--follow-symlinks] [--unordered] - [--textconv | --filters] [-z] -+ [--textconv | --filters] [-z] [-Z] ++ [--textconv | --filters] [-Z] 'git cat-file' (--textconv | --filters) [: | --path= ] @@ Documentation/git-cat-file.txt: respectively print: - -z:: - Only meaningful with `--batch`, `--batch-check`, or - `--batch-command`; input is NUL-delimited instead of -+ newline-delimited. This option is deprecated in favor of -+ `-Z` as the output can otherwise be ambiguous. -+ + /etc/passwd + -- + +-Z:: + Only meaningful with `--batch`, `--batch-check`, or + `--batch-command`; input and output is NUL-delimited instead of - newline-delimited. ++ newline-delimited. ++ + -z:: + Only meaningful with `--batch`, `--batch-check`, or + `--batch-command`; input is NUL-delimited instead of +- newline-delimited. ++ newline-delimited. This option is deprecated in favor of ++ `-Z` as the output can otherwise be ambiguous. + OUTPUT @@ Documentation/git-cat-file.txt: notdir SP LF is printed when, during symlink resolution, a file is used as a directory name. @@ builtin/cat-file.c: static void batch_object_write(const char *obj_name, batch_write(opt, scratch->buf, scratch->len); if (opt->batch_mode == BATCH_MODE_CONTENTS) { -+ char buf[] = {opt->output_delim}; print_object_or_die(opt, data); - batch_write(opt, "\n", 1); -+ batch_write(opt, buf, 1); ++ batch_write(opt, &opt->output_delim, 1); } } @@ builtin/cat-file.c: int cmd_cat_file(int argc, const char **argv, const char *pr N_("git cat-file (--batch | --batch-check | --batch-command) [--batch-all-objects]\n" " [--buffer] [--follow-symlinks] [--unordered]\n" - " [--textconv | --filters] [-z]"), -+ " [--textconv | --filters] [-z] [-Z]"), ++ " [--textconv | --filters] [-Z]"), N_("git cat-file (--textconv | --filters)\n" " [: | --path= ]"), NULL @@ builtin/cat-file.c: int cmd_cat_file(int argc, const char **argv, const char *prefix) + N_("like --batch, but don't emit "), PARSE_OPT_OPTARG | PARSE_OPT_NONEG, batch_option_callback), - OPT_BOOL('z', NULL, &input_nul_terminated, N_("stdin is NUL-terminated")), +- OPT_BOOL('z', NULL, &input_nul_terminated, N_("stdin is NUL-terminated")), ++ OPT_BOOL_F('z', NULL, &input_nul_terminated, N_("stdin is NUL-terminated"), ++ PARSE_OPT_HIDDEN), + OPT_BOOL('Z', NULL, &nul_terminated, N_("stdin and stdout is NUL-terminated")), OPT_CALLBACK_F(0, "batch-command", &batch, N_("format"), N_("read commands from stdin"), -- 2.41.0