Skip to content

Commit ffff4ac

Browse files
bk2204gitster
authored andcommitted
credential: add method for querying capabilities
Right now, there's no specific way to determine whether a credential helper or git credential itself supports a given set of capabilities. It would be helpful to have such a way, so let's let credential helpers and git credential take an argument, "capability", which has it list the capabilities and a version number on standard output. Specifically choose a format that is slightly different from regular credential output and assume that no capabilities are supported if a non-zero exit status occurs or the data deviates from the format. It is common for users to write small shell scripts as the argument to credential.helper, which will almost never be designed to emit capabilities. We want callers to gracefully handle this case by assuming that they are not capable of extended support because that is almost certainly the case, and specifying the error behavior up front does this and preserves backwards compatibility in a graceful way. Signed-off-by: brian m. carlson <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 40220f4 commit ffff4ac

File tree

5 files changed

+60
-1
lines changed

5 files changed

+60
-1
lines changed

Documentation/git-credential.txt

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ git-credential - Retrieve and store user credentials
88
SYNOPSIS
99
--------
1010
------------------
11-
'git credential' (fill|approve|reject)
11+
'git credential' (fill|approve|reject|capability)
1212
------------------
1313

1414
DESCRIPTION
@@ -41,6 +41,9 @@ If the action is `reject`, git-credential will send the description to
4141
any configured credential helpers, which may erase any stored
4242
credentials matching the description.
4343

44+
If the action is `capability`, git-credential will announce any capabilities
45+
it supports to standard output.
46+
4447
If the action is `approve` or `reject`, no output should be emitted.
4548

4649
TYPICAL USE OF GIT CREDENTIAL
@@ -263,6 +266,29 @@ is supported, but they should not be provided without the capability.
263266

264267
Unrecognised attributes and capabilities are silently discarded.
265268

269+
[[CAPA-IOFMT]]
270+
CAPABILITY INPUT/OUTPUT FORMAT
271+
------------------------------
272+
273+
For `git credential capability`, the format is slightly different. First, a
274+
`version 0` announcement is made to indicate the current version of the
275+
protocol, and then each capability is announced with a line like `capability
276+
authtype`. Credential helpers may also implement this format, again with the
277+
`capability` argument. Additional lines may be added in the future; callers
278+
should ignore lines which they don't understand.
279+
280+
Because this is a new part of the credential helper protocol, older versions of
281+
Git, as well as some credential helpers, may not support it. If a non-zero
282+
exit status is received, or if the first line doesn't start with the word
283+
`version` and a space, callers should assume that no capabilities are supported.
284+
285+
The intention of this format is to differentiate it from the credential output
286+
in an unambiguous way. It is possible to use very simple credential helpers
287+
(e.g., inline shell scripts) which always produce identical output. Using a
288+
distinct format allows users to continue to use this syntax without having to
289+
worry about correctly implementing capability advertisements or accidentally
290+
confusing callers querying for capabilities.
291+
266292
GIT
267293
---
268294
Part of the linkgit:git[1] suite

builtin/credential-cache.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "builtin.h"
2+
#include "credential.h"
23
#include "gettext.h"
34
#include "parse-options.h"
45
#include "path.h"
@@ -127,6 +128,13 @@ static char *get_socket_path(void)
127128
return socket;
128129
}
129130

131+
static void announce_capabilities(void)
132+
{
133+
struct credential c = CREDENTIAL_INIT;
134+
c.capa_authtype.request_initial = 1;
135+
credential_announce_capabilities(&c, stdout);
136+
}
137+
130138
int cmd_credential_cache(int argc, const char **argv, const char *prefix)
131139
{
132140
char *socket_path = NULL;
@@ -160,6 +168,8 @@ int cmd_credential_cache(int argc, const char **argv, const char *prefix)
160168
do_cache(socket_path, op, timeout, FLAG_RELAY);
161169
else if (!strcmp(op, "store"))
162170
do_cache(socket_path, op, timeout, FLAG_RELAY|FLAG_SPAWN);
171+
else if (!strcmp(op, "capability"))
172+
announce_capabilities();
163173
else
164174
; /* ignore unknown operation */
165175

builtin/credential.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ int cmd_credential(int argc, const char **argv, const char *prefix UNUSED)
1717
usage(usage_msg);
1818
op = argv[1];
1919

20+
if (!strcmp(op, "capability")) {
21+
credential_set_all_capabilities(&c, CREDENTIAL_OP_INITIAL);
22+
credential_announce_capabilities(&c, stdout);
23+
return 0;
24+
}
25+
2026
if (credential_read(&c, stdin, CREDENTIAL_OP_INITIAL) < 0)
2127
die("unable to read credential from stdin");
2228

credential.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,17 @@ void credential_set_all_capabilities(struct credential *c,
7272
credential_set_capability(&c->capa_state, op_type);
7373
}
7474

75+
static void announce_one(struct credential_capability *cc, const char *name, FILE *fp) {
76+
if (cc->request_initial)
77+
fprintf(fp, "capability %s\n", name);
78+
}
79+
80+
void credential_announce_capabilities(struct credential *c, FILE *fp) {
81+
fprintf(fp, "version 0\n");
82+
announce_one(&c->capa_authtype, "authtype", fp);
83+
announce_one(&c->capa_state, "state", fp);
84+
}
85+
7586
int credential_match(const struct credential *want,
7687
const struct credential *have, int match_password)
7788
{

credential.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,12 @@ void credential_set_all_capabilities(struct credential *c,
253253
*/
254254
void credential_clear_secrets(struct credential *c);
255255

256+
/**
257+
* Print a list of supported capabilities and version numbers to standard
258+
* output.
259+
*/
260+
void credential_announce_capabilities(struct credential *c, FILE *fp);
261+
256262
/**
257263
* Prepares the credential for the next iteration of the helper protocol by
258264
* updating the state headers to send with the ones read by the last iteration

0 commit comments

Comments
 (0)