From 3e5f29e8963a9a6f1774add194ec19583c19fbb6 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 18 Jul 2012 08:04:02 -0400 Subject: [PATCH 1/4] docs/credential: minor clarity fixups The text in git-credential(1) was copied from technical/api-credentials, so it still talks about the input/output format as coming from git to the helper. Since the surrounding text already indicates that this format is used for reading and writing with git credential, we can just remove the extraneous confusing bits. Signed-off-by: Jeff King Acked-by: Matthieu Moy Signed-off-by: Junio C Hamano --- Documentation/git-credential.txt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Documentation/git-credential.txt b/Documentation/git-credential.txt index a81684e15f..afd5365255 100644 --- a/Documentation/git-credential.txt +++ b/Documentation/git-credential.txt @@ -102,22 +102,20 @@ INPUT/OUTPUT FORMAT ------------------- `git credential` reads and/or writes (depending on the action used) -credential information in its standard input/output. These information +credential information in its standard input/output. This information can correspond either to keys for which `git credential` will obtain the login/password information (e.g. host, protocol, path), or to the actual credential data to be obtained (login/password). -The credential is split into a set of named attributes. -Attributes are provided to the helper, one per line. Each attribute is +The credential is split into a set of named attributes, with one +attribute per line. Each attribute is specified by a key-value pair, separated by an `=` (equals) sign, followed by a newline. The key may contain any bytes except `=`, newline, or NUL. The value may contain any bytes except newline or NUL. In both cases, all bytes are treated as-is (i.e., there is no quoting, and one cannot transmit a value with newline or NUL in it). The list of attributes is terminated by a blank line or end-of-file. -Git will send the following attributes (but may not send all of -them for a given credential; for example, a `host` attribute makes no -sense when dealing with a non-network protocol): +Git understands the following attributes: `protocol`:: From 6319a2a148adaa78f11414e914f8c9f3f1c52b5e Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 18 Jul 2012 08:04:30 -0400 Subject: [PATCH 2/4] mw-to-git: check blank credential attributes via length When writing a credential to git-credential, we omit fields that do not have a true value. This will skip empty or undefined fields (which we want), but will also accidentally skip usernames or passwords which happen to have a non-true value (e.g., "0"). Be more careful by checking for non-zero length. Signed-off-by: Jeff King Acked-by: Matthieu Moy Signed-off-by: Junio C Hamano --- contrib/mw-to-git/git-remote-mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/mw-to-git/git-remote-mediawiki b/contrib/mw-to-git/git-remote-mediawiki index accd70a94c..b06f27b921 100755 --- a/contrib/mw-to-git/git-remote-mediawiki +++ b/contrib/mw-to-git/git-remote-mediawiki @@ -207,7 +207,7 @@ sub credential_write { my $credential = shift; my $writer = shift; while (my ($key, $value) = each(%$credential) ) { - if ($value) { + if (length $value) { print $writer "$key=$value\n"; } } From 9c183a70722804114ac1dc54d17fe791ac1a452c Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 18 Jul 2012 08:06:26 -0400 Subject: [PATCH 3/4] credential: convert "url" attribute into its parsed subparts The git-credential command requires that you feed it a broken-down credential, which means that the client needs to parse a URL itself. Since we have our own URL-parsing routines, we can easily allow the caller to just give us the URL as-is, saving them some code. Signed-off-by: Jeff King Acked-by: Matthieu Moy Signed-off-by: Junio C Hamano --- Documentation/git-credential.txt | 12 ++++++++++++ credential.c | 2 ++ 2 files changed, 14 insertions(+) diff --git a/Documentation/git-credential.txt b/Documentation/git-credential.txt index afd5365255..53adee3203 100644 --- a/Documentation/git-credential.txt +++ b/Documentation/git-credential.txt @@ -140,3 +140,15 @@ Git understands the following attributes: `password`:: The credential's password, if we are asking it to be stored. + +`url`:: + + When this special attribute is read by `git credential`, the + value is parsed as a URL and treated as if its constituent parts + were read (e.g., `url=https://example.com` would behave as if + `protocol=https` and `host=example.com` had been provided). This + can help callers avoid parsing URLs themselves. Note that any + components which are missing from the URL (e.g., there is no + username in the example above) will be set to empty; if you want + to provide a URL and override some attributes, provide the URL + attribute first, followed by any overrides. diff --git a/credential.c b/credential.c index 2c400073fa..e54753c75d 100644 --- a/credential.c +++ b/credential.c @@ -172,6 +172,8 @@ int credential_read(struct credential *c, FILE *fp) } else if (!strcmp(key, "path")) { free(c->path); c->path = xstrdup(value); + } else if (!strcmp(key, "url")) { + credential_from_url(c, value); } /* * Ignore other lines; we don't know what they mean, but From 77eab053a48a2062665c42f63348ae12290de03f Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 18 Jul 2012 09:03:08 -0400 Subject: [PATCH 4/4] mw-to-git: use git-credential's URL parser We can just feed our URL straight to git-credential and it will parse it for us, saving us some code. Signed-off-by: Jeff King Acked-by: Matthieu Moy Signed-off-by: Junio C Hamano --- contrib/mw-to-git/git-remote-mediawiki | 32 ++++---------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/contrib/mw-to-git/git-remote-mediawiki b/contrib/mw-to-git/git-remote-mediawiki index b06f27b921..38afa76606 100755 --- a/contrib/mw-to-git/git-remote-mediawiki +++ b/contrib/mw-to-git/git-remote-mediawiki @@ -163,32 +163,6 @@ while () { ## credential API management (generic functions) -sub credential_from_url { - my $url = shift; - my $parsed = URI->new($url); - my %credential; - - if ($parsed->scheme) { - $credential{protocol} = $parsed->scheme; - } - if ($parsed->host) { - $credential{host} = $parsed->host; - } - if ($parsed->path) { - $credential{path} = $parsed->path; - } - if ($parsed->userinfo) { - if ($parsed->userinfo =~ /([^:]*):(.*)/) { - $credential{username} = $1; - $credential{password} = $2; - } else { - $credential{username} = $parsed->userinfo; - } - } - - return %credential; -} - sub credential_read { my %credential; my $reader = shift; @@ -206,8 +180,10 @@ sub credential_read { sub credential_write { my $credential = shift; my $writer = shift; + # url overwrites other fields, so it must come first + print $writer "url=$credential->{url}\n" if exists $credential->{url}; while (my ($key, $value) = each(%$credential) ) { - if (length $value) { + if (length $value && $key ne 'url') { print $writer "$key=$value\n"; } } @@ -246,7 +222,7 @@ sub mw_connect_maybe { $mediawiki = MediaWiki::API->new; $mediawiki->{config}->{api_url} = "$url/api.php"; if ($wiki_login) { - my %credential = credential_from_url($url); + my %credential = (url => $url); $credential{username} = $wiki_login; $credential{password} = $wiki_passwd; credential_run("fill", \%credential);