Subject: Re: [PATCH 05/11] config-batch: add NUL-terminated I/O format

From: Jean-Noël Avila <[email-masked]>
Date: Fri, 6 Feb 2026 05:58:21 +0100

Le 04/02/2026 à 15:19, Derrick Stolee via GitGitGadget a écrit :
> From: Derrick Stolee <[email-masked]>
> 
> When using automated tools, it is critical to allow for input/output formats
> that include special characters such as spaces and newlines. While the
> existing protocol for 'git config-batch' is human-readable and has some
> capacity for some spaces in certain positions, it is not available for
> spaces in the config key or newlines in the config values.
> 
> Add the '-z' option to signal the use of NUL-terminated strings. To
> understand where commands end regardless of potential future formats, use
> two NUL bytes in a row to terminate a command. To allow for empty string
> values, each token is provided in a <length>:<value> format, making "0:"
> the empty string value.
> 
> Update the existing 'help' and 'get' commands to match this format. Create
> helper methods that make it easy to parse and print in both formats
> simultaneously.
> 
> Signed-off-by: Derrick Stolee <[email-masked]>
> ---
>  Documentation/git-config-batch.adoc |  57 ++++++++-
>  builtin/config-batch.c              | 188 +++++++++++++++++++++++++---
>  t/t1312-config-batch.sh             |  69 ++++++++++
>  3 files changed, 293 insertions(+), 21 deletions(-)
> 
> diff --git a/Documentation/git-config-batch.adoc b/Documentation/git-config-batch.adoc
> index 1fff68a13c..3c9a3bb763 100644
> --- a/Documentation/git-config-batch.adoc
> +++ b/Documentation/git-config-batch.adoc
> @@ -21,6 +21,15 @@ multiple configuration values, the `git config-batch` command allows a
>  single process to handle multiple requests using a machine-parseable
>  interface across `stdin` and `stdout`.
>  
> +OPTIONS
> +-------
> +
> +`-z`::
> +	If specified, then use the NUL-terminated input and output

This boilerplate preliminary does not convey information, it is simpler
to just jump to the action performed by the option:

Use the _NUL_-terminated input and output…

> +	format instead of the space and newline format. This format is
> +	useful when the strings involved may include spaces or newlines.
> +	See PROTOCOL for more details.
> +
>  PROTOCOL
>  --------
>  By default, the protocol uses line feeds (`LF`) to signal the end of a
> @@ -41,13 +50,13 @@ These are the commands that are currently understood:
>  `help` version 1::
>  	The `help` command lists the currently-available commands in
>  	this version of Git. The output is multi-line, but the first
> -	line provides the count of possible commands via `help count <N>`.
> -	The next `<N>` lines are of the form `help <command> <version>`
> +	line provides the count of possible commands via `help 1 count <N>`.
> +	The next `<N>` lines are of the form `help 1 <command> <version>`
>  	to state that this Git version supports that `<command>` at
>  	version `<version>`. Note that the same command may have multiple
>  	available versions.
>  +
> -Here is the currentl output of the help text at the latest version:
> +Here is the current output of the help text at the latest version:

OK, the typo was fixed here.

>  +
>  ------------
>  help 1 count 2
> @@ -102,6 +111,48 @@ get 1 missing <key> [<value-pattern>|<value>]
>  where `<value-pattern>` or `<value>` is only supplied if provided in
>  the command.
>  
> +NUL-Terminated Format
> +~~~~~~~~~~~~~~~~~~~~~
> +
> +When `-z` is given, the protocol changes in some structural ways.
> +
> +First, each command is terminated with two NUL bytes, providing a clear
> +boundary between commands regardless of future possibilities of new
> +command formats.
> +
> +Second, any time that a space _would_ be used to partition tokens in a
> +command, a NUL byte is used instead. Further, each token is prefixed
> +with `<N>:` where `<N>` is a decimal representation of the length of
> +the string between the `:` and the next NUL byte. Any disagreement in
> +these lengths is treated as a parsing error. This use of a length does

I thought this length encoding was used to allow _NUL_ in the config
values. But here it is considered a parse error.

> +imply that "`0:`" is the representation of an empty string, if relevant.
> +
> +The decimal representation must have at most five numerals, thus the
> +maximum length of a string token can have 99999 characters.
> +
> +For example, the `get` command, version 1, could have any of the
> +following forms:
> +
> +------------
> +3:get NUL 1:1 NUL 5:local NUL 14:key.with space NUL NUL
> +3:get NUL 1:1 NUL 9:inherit NUL 8:test.key NUL 9:arg:regex NUL 6:.*\ .* NUL NUL
> +3:get NUL 1:1 NUL 6:global NUL 8:test.key NUL 15:arg:fixed-value NUL 3:a b NUL NUL
> +------------
> +
> +The output is modified similarly, such as the following output examples,
> +as if the input has a parse error, a valid `help` command, a `get`
> +command that had a match, and a `get` command that did not match.
> +
> +------------
> +15:unknown_command NUL NUL
> +4:help NUL 1:1 NUL 5:count NUL 1:2 NUL NUL
> +4:help NUL 1:1 NUL 4:help NUL 1:1 NUL NUL
> +4:help NUL 1:1 NUL 3:get NUL 1:1 NUL NUL
> +3:get NUL 1:1 NUL 5:found NUL 8:test.key NUL 5:value NUL NUL
> +3:get NUL 1:1 NUL 7:missing NUL 8:test.key NUL NUL
> +------------
> +
> +
>  SEE ALSO
>  --------
>  linkgit:git-config[1]