diff --git a/Documentation/technical/api-credentials.txt b/Documentation/technical/api-credentials.txt index 880db92c69..335a007354 100644 --- a/Documentation/technical/api-credentials.txt +++ b/Documentation/technical/api-credentials.txt @@ -25,8 +25,9 @@ Data Structures The credential functions take a `string_list` of methods for acquiring credentials. Each string specifies an external helper which will be run, in order, to acquire credentials, - until both a username and password have been acquired. A NULL or - empty methods list indicates that the internal + until both a username and password have been acquired. A NULL + parameter means to use the default list (as configured by + `credential.helper`); an empty list indicates that the internal `credential_getpass` function should be used. diff --git a/config.c b/config.c index 6b61a849d2..cd2d61e3cb 100644 --- a/config.c +++ b/config.c @@ -9,6 +9,7 @@ #include "exec_cmd.h" #include "strbuf.h" #include "quote.h" +#include "credential.h" #define MAXNAME (256) @@ -791,6 +792,9 @@ int git_default_config(const char *var, const char *value, void *dummy) return 0; } + if (!prefixcmp(var, "credential.")) + return git_default_credential_config(var, value); + /* Add other config variables here and to Documentation/config.txt. */ return 0; } diff --git a/credential.c b/credential.c index 907b90bad1..7a0c751363 100644 --- a/credential.c +++ b/credential.c @@ -4,6 +4,8 @@ #include "string-list.h" #include "run-command.h" +static struct string_list default_methods; + static int credential_config_callback(const char *var, const char *value, void *data) { @@ -173,15 +175,18 @@ void credential_fill(struct credential *c, const struct string_list *methods) { struct strbuf err = STRBUF_INIT; + if (!methods) + methods = &default_methods; + if (!credential_fill_gently(c, methods)) return; strbuf_addstr(&err, "unable to get credentials"); if (c->description) strbuf_addf(&err, "for '%s'", c->description); - if (methods && methods->nr == 1) + if (methods->nr == 1) strbuf_addf(&err, "; tried '%s'", methods->items[0].string); - else if (methods) { + else { int i; strbuf_addstr(&err, "; tried:"); for (i = 0; i < methods->nr; i++) @@ -198,7 +203,10 @@ int credential_fill_gently(struct credential *c, if (c->username && c->password) return 0; - if (!methods || !methods->nr) + if (!methods) + methods = &default_methods; + + if (!methods->nr) return credential_getpass(c); for (i = 0; i < methods->nr; i++) { @@ -214,7 +222,10 @@ void credential_reject(struct credential *c, const struct string_list *methods) { int i; - if (methods && c->username) { + if (!methods) + methods = &default_methods; + + if (c->username) { for (i = 0; i < methods->nr; i++) { /* ignore errors, there's nothing we can do */ credential_do(c, methods->items[i].string, "--reject"); @@ -226,3 +237,15 @@ void credential_reject(struct credential *c, const struct string_list *methods) free(c->password); c->password = NULL; } + +int git_default_credential_config(const char *var, const char *value) +{ + if (!strcmp(var, "credential.helper")) { + if (!value) + return config_error_nonbool(var); + string_list_append(&default_methods, xstrdup(value)); + return 0; + } + + return 0; +} diff --git a/credential.h b/credential.h index 30a0156c0f..788ed8e8bf 100644 --- a/credential.h +++ b/credential.h @@ -17,4 +17,6 @@ int credential_fill_gently(struct credential *, const struct string_list *method void credential_fill(struct credential *, const struct string_list *methods); void credential_reject(struct credential *, const struct string_list *methods); +int git_default_credential_config(const char *var, const char *value); + #endif /* CREDENTIAL_H */ diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch.sh index c78baaf345..407e1cb3c6 100755 --- a/t/t5550-http-fetch.sh +++ b/t/t5550-http-fetch.sh @@ -93,6 +93,19 @@ test_expect_success 'http auth can pull user from config' ' test_cmp askpass-expect-pass askpass-query ' +test_expect_success 'http auth respects credential helpers' ' + cat >credential-helper <<-\EOF && + #!/bin/sh + echo username=user@host + echo password=user@host + EOF + chmod +x credential-helper && + git config --global credential.helper "\"$PWD/credential-helper\"" && + >askpass-query && + git clone "$HTTPD_URL/auth/repo.git" clone-auth-helper && + test_cmp askpass-expect-none askpass-query +' + test_expect_success 'fetch changes via http' ' echo content >>file && git commit -a -m two &&