var: add "-z" output mode
Scripts that read from "git var" have no unambiguous way to parse its output. A value that itself contains a newline, and a variable that has more than one value, both run together with the newline that terminates each entry. Teach "git var" a "-z" option that terminates each entry with a NUL byte instead. With "-l", the variable name and its value are separated by a newline and each entry is terminated by NUL, which is the same convention "git config list -z" already uses. When a single variable is asked for, its bare value is terminated by NUL. Parsing of the command line is switched over to parse_options() in order to accept the new option; as a side effect, options now have to come before the variable name. Signed-off-by: Andrew Pleeter <andrewpleeter@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
1 parent
5e54624a8e
commit
e19f0779c6
3 files changed
+91
-21
No files matched your search
@@ -9,13 +9,19 @@ git-var - Show a Git logical variable
|
||||
SYNOPSIS
|
||||
--------
|
||||
[synopsis]
|
||||
git var (-l | <variable>)
|
||||
git var [-z] -l
|
||||
git var [-z] <variable>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Prints a Git logical variable. Exits with code 1 if the variable has
|
||||
no value.
|
||||
|
||||
If `-z` is given, the value is terminated by a NUL byte instead of a
|
||||
newline. With `-l`, the variable name and its value are separated by a
|
||||
newline, and each entry is terminated by a NUL byte
|
||||
(`VARIABLE\nvalue\0`), in the same way as `git config list -z`.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
`-l`::
|
||||
@@ -24,6 +30,11 @@ OPTIONS
|
||||
as well. (However, the configuration variables listing functionality
|
||||
is deprecated in favor of `git config list`.)
|
||||
|
||||
`-z`::
|
||||
Terminate entries with NUL instead of newline. When used with
|
||||
`-l`, the variable name and its value are separated by a
|
||||
newline, and each entry is terminated with a NUL byte.
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
$ git var GIT_AUTHOR_IDENT
|
||||
@@ -86,9 +97,9 @@ endif::git-default-pager[]
|
||||
This variable can have multiple values.
|
||||
|
||||
Most path values contain only one value. However, some can contain multiple
|
||||
values, which are separated by newlines, and are listed in order from highest to
|
||||
lowest priority. Callers should be prepared for any such path value to contain
|
||||
multiple items.
|
||||
values, which are separated by newlines (or NUL bytes if `-z` is given), and are
|
||||
listed in order from highest to lowest priority. Callers should be prepared for
|
||||
any such path value to contain multiple items.
|
||||
|
||||
Note that paths are printed even if they do not exist, but not if they are
|
||||
disabled by other environment variables.
|
||||
|
||||
+46
-17
@@ -14,13 +14,18 @@
|
||||
#include "environment.h"
|
||||
#include "ident.h"
|
||||
#include "pager.h"
|
||||
#include "parse-options.h"
|
||||
#include "path.h"
|
||||
#include "refs.h"
|
||||
#include "run-command.h"
|
||||
#include "strbuf.h"
|
||||
#include "string-list.h"
|
||||
|
||||
static const char var_usage[] = "git var (-l | <variable>)";
|
||||
static const char * const var_usage[] = {
|
||||
N_("git var [-z] -l"),
|
||||
N_("git var [-z] <variable>"),
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *committer(int ident_flag)
|
||||
{
|
||||
@@ -164,16 +169,18 @@ static struct git_var git_vars[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static void list_vars(void)
|
||||
static void list_vars(int nul_term)
|
||||
{
|
||||
struct git_var *ptr;
|
||||
char delim = nul_term ? '\n' : '=';
|
||||
char term = nul_term ? '\0' : '\n';
|
||||
|
||||
for (ptr = git_vars; ptr->read || ptr->multiread; ptr++) {
|
||||
if (ptr->read) {
|
||||
char *val = ptr->read(0);
|
||||
|
||||
if (val) {
|
||||
printf("%s=%s\n", ptr->name, val);
|
||||
printf("%s%c%s%c", ptr->name, delim, val, term);
|
||||
free(val);
|
||||
}
|
||||
} else {
|
||||
@@ -181,7 +188,8 @@ static void list_vars(void)
|
||||
|
||||
ptr->multiread(&list);
|
||||
for (size_t i = 0; i < list.nr; i++)
|
||||
printf("%s=%s\n", ptr->name, list.items[i].string);
|
||||
printf("%s%c%s%c", ptr->name, delim,
|
||||
list.items[i].string, term);
|
||||
string_list_clear(&list, 0);
|
||||
}
|
||||
}
|
||||
@@ -201,34 +209,55 @@ static const struct git_var *get_git_var(const char *var)
|
||||
static int show_config(const char *var, const char *value,
|
||||
const struct config_context *ctx, void *cb)
|
||||
{
|
||||
int *nul_term = cb;
|
||||
char delim = *nul_term ? '\n' : '=';
|
||||
char term = *nul_term ? '\0' : '\n';
|
||||
|
||||
if (value)
|
||||
printf("%s=%s\n", var, value);
|
||||
printf("%s%c%s%c", var, delim, value, term);
|
||||
else
|
||||
printf("%s\n", var);
|
||||
printf("%s%c", var, term);
|
||||
return git_default_config(var, value, ctx, cb);
|
||||
}
|
||||
|
||||
int cmd_var(int argc,
|
||||
const char **argv,
|
||||
const char *prefix UNUSED,
|
||||
const char *prefix,
|
||||
struct repository *repo UNUSED)
|
||||
{
|
||||
const struct git_var *git_var;
|
||||
int list = 0;
|
||||
int nul_term = 0;
|
||||
char term;
|
||||
struct option options[] = {
|
||||
OPT_BOOL('l', NULL, &list,
|
||||
N_("list all variables")),
|
||||
OPT_BOOL('z', NULL, &nul_term,
|
||||
N_("terminate entries with NUL")),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
show_usage_if_asked(argc, argv, var_usage);
|
||||
if (argc != 2)
|
||||
usage(var_usage);
|
||||
argc = parse_options(argc, argv, prefix, options,
|
||||
var_usage, PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
|
||||
if (strcmp(argv[1], "-l") == 0) {
|
||||
repo_config(the_repository, show_config, NULL);
|
||||
list_vars();
|
||||
if (list) {
|
||||
if (argc)
|
||||
usage_with_options(var_usage, options);
|
||||
repo_config(the_repository, show_config, &nul_term);
|
||||
list_vars(nul_term);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc != 1)
|
||||
usage_with_options(var_usage, options);
|
||||
|
||||
repo_config(the_repository, git_default_config, NULL);
|
||||
|
||||
git_var = get_git_var(argv[1]);
|
||||
term = nul_term ? '\0' : '\n';
|
||||
|
||||
git_var = get_git_var(argv[0]);
|
||||
if (!git_var)
|
||||
usage(var_usage);
|
||||
usage_with_options(var_usage, options);
|
||||
|
||||
if (git_var->read) {
|
||||
char *val = git_var->read(IDENT_STRICT);
|
||||
@@ -236,7 +265,7 @@ int cmd_var(int argc,
|
||||
if (!val)
|
||||
return 1;
|
||||
|
||||
printf("%s\n", val);
|
||||
printf("%s%c", val, term);
|
||||
free(val);
|
||||
} else {
|
||||
struct string_list list = STRING_LIST_INIT_DUP;
|
||||
@@ -247,7 +276,7 @@ int cmd_var(int argc,
|
||||
return 1;
|
||||
}
|
||||
for (size_t i = 0; i < list.nr; i++)
|
||||
printf("%s\n", list.items[i].string);
|
||||
printf("%s%c", list.items[i].string, term);
|
||||
string_list_clear(&list, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -276,4 +276,34 @@ test_expect_success '`git var -l` works even without HOME' '
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'get a variable with -z' '
|
||||
printf "%sQ" "$(git var GIT_AUTHOR_IDENT)" >expect &&
|
||||
git var -z GIT_AUTHOR_IDENT >actual.raw &&
|
||||
nul_to_q <actual.raw >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'get multi-valued variable with -z' '
|
||||
TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" &&
|
||||
HOME="$TRASHDIR" XDG_CONFIG_HOME="$TRASHDIR/foo" git var -z GIT_CONFIG_GLOBAL >actual.raw &&
|
||||
printf "%sQ%sQ" "$TRASHDIR/foo/git/config" "$TRASHDIR/.gitconfig" >expect &&
|
||||
nul_to_q <actual.raw >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'git var -l -z' '
|
||||
git var -l -z >actual &&
|
||||
tr "\0" "\n" <actual >actual.lines &&
|
||||
git var GIT_AUTHOR_IDENT >expect &&
|
||||
sed -n "/^GIT_AUTHOR_IDENT$/{n;p;}" actual.lines >actual.author &&
|
||||
test_cmp expect actual.author &&
|
||||
echo false >expect &&
|
||||
sed -n "/^core\.bare$/{n;p;}" actual.lines >actual.bare &&
|
||||
test_cmp expect actual.bare
|
||||
'
|
||||
|
||||
test_expect_success 'options must precede variable arguments' '
|
||||
test_must_fail git var GIT_AUTHOR_IDENT -z
|
||||
'
|
||||
|
||||
test_done
|
||||
Reference in new issue
Block a user