Browse Source

config: teach "git config --file -" to read from the standard input

The patch extends git config --file interface to allow read config from
stdin.

Editing stdin or setting value in stdin is an error.

Include by absolute path is allowed in stdin config, but not by relative
path.

Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Kirill A. Shutemov 11 years ago committed by Junio C Hamano
parent
commit
3caec73b55
  1. 11
      builtin/config.c
  2. 1
      cache.h
  3. 41
      config.c
  4. 17
      t/t1300-repo-config.sh
  5. 16
      t/t1305-config-include.sh

11
builtin/config.c

@ -360,6 +360,9 @@ static int get_colorbool(int print)


static void check_write(void) static void check_write(void)
{ {
if (given_config_source.use_stdin)
die("writing to stdin is not supported");

if (given_config_source.blob) if (given_config_source.blob)
die("writing config blobs is not supported"); die("writing config blobs is not supported");
} }
@ -472,6 +475,12 @@ int cmd_config(int argc, const char **argv, const char *prefix)
usage_with_options(builtin_config_usage, builtin_config_options); usage_with_options(builtin_config_usage, builtin_config_options);
} }


if (given_config_source.file &&
!strcmp(given_config_source.file, "-")) {
given_config_source.file = NULL;
given_config_source.use_stdin = 1;
}

if (use_global_config) { if (use_global_config) {
char *user_config = NULL; char *user_config = NULL;
char *xdg_config = NULL; char *xdg_config = NULL;
@ -558,6 +567,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
check_argc(argc, 0, 0); check_argc(argc, 0, 0);
if (!given_config_source.file && nongit) if (!given_config_source.file && nongit)
die("not in a git directory"); die("not in a git directory");
if (given_config_source.use_stdin)
die("editing stdin is not supported");
if (given_config_source.blob) if (given_config_source.blob)
die("editing blobs is not supported"); die("editing blobs is not supported");
git_config(git_default_config, NULL); git_config(git_default_config, NULL);

1
cache.h

@ -1147,6 +1147,7 @@ extern int update_server_info(int);
#define CONFIG_GENERIC_ERROR 7 #define CONFIG_GENERIC_ERROR 7


struct git_config_source { struct git_config_source {
unsigned int use_stdin:1;
const char *file; const char *file;
const char *blob; const char *blob;
}; };

41
config.c

@ -1031,24 +1031,35 @@ static int do_config_from(struct config_source *top, config_fn_t fn, void *data)
return ret; return ret;
} }


int git_config_from_file(config_fn_t fn, const char *filename, void *data) static int do_config_from_file(config_fn_t fn,
const char *name, const char *path, FILE *f, void *data)
{ {
int ret; struct config_source top;
FILE *f = fopen(filename, "r");


ret = -1; top.u.file = f;
if (f) { top.name = name;
struct config_source top; top.path = path;
top.die_on_error = 1;
top.do_fgetc = config_file_fgetc;
top.do_ungetc = config_file_ungetc;
top.do_ftell = config_file_ftell;


top.u.file = f; return do_config_from(&top, fn, data);
top.name = top.path = filename; }
top.die_on_error = 1;
top.do_fgetc = config_file_fgetc;
top.do_ungetc = config_file_ungetc;
top.do_ftell = config_file_ftell;


ret = do_config_from(&top, fn, data); static int git_config_from_stdin(config_fn_t fn, void *data)
{
return do_config_from_file(fn, "<stdin>", NULL, stdin, data);
}

int git_config_from_file(config_fn_t fn, const char *filename, void *data)
{
int ret = -1;
FILE *f;


f = fopen(filename, "r");
if (f) {
ret = do_config_from_file(fn, filename, filename, f, data);
fclose(f); fclose(f);
} }
return ret; return ret;
@ -1190,7 +1201,9 @@ int git_config_with_options(config_fn_t fn, void *data,
* If we have a specific filename, use it. Otherwise, follow the * If we have a specific filename, use it. Otherwise, follow the
* regular lookup sequence. * regular lookup sequence.
*/ */
if (config_source && config_source->file) if (config_source && config_source->use_stdin)
return git_config_from_stdin(fn, data);
else if (config_source && config_source->file)
return git_config_from_file(fn, config_source->file, data); return git_config_from_file(fn, config_source->file, data);
else if (config_source && config_source->blob) else if (config_source && config_source->blob)
return git_config_from_blob_ref(fn, config_source->blob, data); return git_config_from_blob_ref(fn, config_source->blob, data);

17
t/t1300-repo-config.sh

@ -475,15 +475,28 @@ ein.bahn=strasse
EOF EOF


test_expect_success 'alternative GIT_CONFIG' ' test_expect_success 'alternative GIT_CONFIG' '
GIT_CONFIG=other-config git config -l >output && GIT_CONFIG=other-config git config --list >output &&
test_cmp expect output test_cmp expect output
' '


test_expect_success 'alternative GIT_CONFIG (--file)' ' test_expect_success 'alternative GIT_CONFIG (--file)' '
git config --file other-config -l > output && git config --file other-config --list >output &&
test_cmp expect output test_cmp expect output
' '


test_expect_success 'alternative GIT_CONFIG (--file=-)' '
git config --file - --list <other-config >output &&
test_cmp expect output
'

test_expect_success 'setting a value in stdin is an error' '
test_must_fail git config --file - some.value foo
'

test_expect_success 'editing stdin is an error' '
test_must_fail git config --file - --edit
'

test_expect_success 'refer config from subdirectory' ' test_expect_success 'refer config from subdirectory' '
mkdir x && mkdir x &&
( (

16
t/t1305-config-include.sh

@ -113,7 +113,7 @@ test_expect_success 'missing include files are ignored' '
test_expect_success 'absolute includes from command line work' ' test_expect_success 'absolute includes from command line work' '
echo "[test]one = 1" >one && echo "[test]one = 1" >one &&
echo 1 >expect && echo 1 >expect &&
git -c include.path="$PWD/one" config test.one >actual && git -c include.path="$(pwd)/one" config test.one >actual &&
test_cmp expect actual test_cmp expect actual
' '


@ -138,6 +138,20 @@ test_expect_success 'relative includes from blobs fail' '
test_must_fail git config --blob=$blob test.one test_must_fail git config --blob=$blob test.one
' '


test_expect_success 'absolute includes from stdin work' '
echo "[test]one = 1" >one &&
echo 1 >expect &&
echo "[include]path=\"$(pwd)/one\"" |
git config --file - test.one >actual &&
test_cmp expect actual
'

test_expect_success 'relative includes from stdin line fail' '
echo "[test]one = 1" >one &&
echo "[include]path=one" |
test_must_fail git config --file - test.one
'

test_expect_success 'include cycles are detected' ' test_expect_success 'include cycles are detected' '
cat >.gitconfig <<-\EOF && cat >.gitconfig <<-\EOF &&
[test]value = gitconfig [test]value = gitconfig

Loading…
Cancel
Save