credential: let helpers tell us to quit
authorJeff King <peff@peff.net>
Thu, 4 Dec 2014 03:46:48 +0000 (22:46 -0500)
committerJunio C Hamano <gitster@pobox.com>
Thu, 4 Dec 2014 18:11:12 +0000 (10:11 -0800)
When we are trying to fill a credential, we loop over the
set of defined credential-helpers, then fall back to running
askpass, and then finally prompt on the terminal. Helpers
which cannot find a credential are free to tell us nothing,
but they cannot currently ask us to stop prompting.

This patch lets them provide a "quit" attribute, which asks
us to stop the process entirely (avoiding running more
helpers, as well as the askpass/terminal prompt).

This has a few possible uses:

1. A helper which prompts the user itself (e.g., in a
dialog) can provide a "cancel" button to the user to
stop further prompts.

2. Some helpers may know that prompting cannot possibly
work. For example, if their role is to broker a ticket
from an external auth system and that auth system
cannot be contacted, there is no point in continuing
(we need a ticket to authenticate, and the user cannot
provide one by typing it in).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/technical/api-credentials.txt
credential.c
credential.h
t/t0300-credentials.sh
index c1b42a40d3c0c297994cd2966b60cd48629e57fa..e44426dd041516b8d9220ce9f1b2413be0319703 100644 (file)
@@ -248,7 +248,10 @@ FORMAT` in linkgit:git-credential[7] for a detailed specification).
 For a `get` operation, the helper should produce a list of attributes
 on stdout in the same format. A helper is free to produce a subset, or
 even no values at all if it has nothing useful to provide. Any provided
-attributes will overwrite those already known about by Git.
+attributes will overwrite those already known about by Git.  If a helper
+outputs a `quit` attribute with a value of `true` or `1`, no further
+helpers will be consulted, nor will the user be prompted (if no
+credential has been provided, the operation will then fail).
 
 For a `store` or `erase` operation, the helper's output is ignored.
 If it fails to perform the requested operation, it may complain to
index 4d79d320f89e956aa9233a170120f05b2473ca59..0f974f1987b78fb506e044fd8180c2f24fb86703 100644 (file)
@@ -173,6 +173,8 @@ int credential_read(struct credential *c, FILE *fp)
                        c->path = xstrdup(value);
                } else if (!strcmp(key, "url")) {
                        credential_from_url(c, value);
+               } else if (!strcmp(key, "quit")) {
+                       c->quit = !!git_config_bool("quit", value);
                }
                /*
                 * Ignore other lines; we don't know what they mean, but
@@ -275,6 +277,9 @@ void credential_fill(struct credential *c)
                credential_do(c, c->helpers.items[i].string, "get");
                if (c->username && c->password)
                        return;
+               if (c->quit)
+                       die("credential helper '%s' told us to quit",
+                           c->helpers.items[i].string);
        }
 
        credential_getpass(c);
index 0c3e85e8e4232ad9298372efebf7696a77dc94b1..6b0cd16be2b96b23ae5ce14a07a8ad130af8d5bb 100644 (file)
@@ -7,6 +7,7 @@ struct credential {
        struct string_list helpers;
        unsigned approved:1,
                 configured:1,
+                quit:1,
                 use_http_path:1;
 
        char *username;
index 57ea5a10c5c716f52a8c8c7335ac7f68fe9dd92d..d7ef44b4a261a588874df3b8359d809655286a43 100755 (executable)
@@ -289,4 +289,13 @@ test_expect_success 'http paths can be part of context' '
        EOF
 '
 
+test_expect_success 'helpers can abort the process' '
+       test_must_fail git \
+               -c credential.helper="!f() { echo quit=1; }; f" \
+               -c credential.helper="verbatim foo bar" \
+               credential fill >stdout &&
+       >expect &&
+       test_cmp expect stdout
+'
+
 test_done