git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/3] git-remote-mediawiki: add credential support

From
Matthieu Moy <matthieu.moy@imag.fr>
Date
Jun 24, 2012, 11:40 UTC
Message-ID
<1340538001-18625-3-git-send-email-Matthieu.Moy@imag.fr>
In-Reply-To
<1340538001-18625-1-git-send-email-Matthieu.Moy@imag.fr>

The previous version implemented the possibility to log in a wiki, but the username and password had to be provided as configuration variables. We add the possibility to use the Git credential system to prompt the password.

The support if implemented with generic functions that mimic the C API, designed to be usable from other contexts in the future (i.e. they may migrate to Git.pm if someone is interested).

While we're there, do a bit of refactoring in mw_connect_maybe.
Based on patch by: Javier Roucher Iglesias <Javier.Roucher-Iglesias@ensimag.imag.fr>
---
 contrib/mw-to-git/git-remote-mediawiki | 106 +++++++++++++++++++++++++++++----
 1 file changed, 94 insertions(+), 12 deletions(-)
diff --git a/contrib/mw-to-git/git-remote-mediawiki b/contrib/mw-to-git/git-remote-mediawiki
index c18bfa1..a34f53f 100755
--- a/contrib/mw-to-git/git-remote-mediawiki
+++ b/contrib/mw-to-git/git-remote-mediawiki
@@ -43,6 +43,8 @@ use encoding 'utf8';
 binmode STDERR, ":utf8";
 
 use URI::Escape;
+use IPC::Open2;
+
 use warnings;
 
 # Mediawiki filenames can contain forward slashes. This variable decides by which pattern they should be replaced
@@ -151,28 +153,108 @@ while (<STDIN>) {
 
 ########################## Functions ##############################
 
+## 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;
+	my $op = shift;
+	while (<$reader>) {
+		my ($key, $value) = /([^=]*)=(.*)/;
+		if (not defined $key) {
+			die "ERROR receiving response from git credential $op:\n$_\n";
+		}
+		$credential{$key} = $value;
+	}
+	return %credential;
+}
+
+sub credential_write {
+	my $credential = shift;
+	my $writer = shift;
+	while (my ($key, $value) = each(%$credential) ) {
+		if ($value) {
+			print $writer "$key=$value\n";
+		}
+	}
+}
+
+sub credential_run {
+	my $op = shift;
+	my $credential = shift;
+	my $pid = open2(my $reader, my $writer, "git credential $op");
+	credential_write($credential, $writer);
+	print $writer "\n";
+	close($writer);
+	
+	if ($op eq "fill") {
+		%$credential = credential_read($reader, $op);
+	} else {
+		if (<$reader>) {
+			die "ERROR while running git credential $op:\n$_";
+		}
+	}
+	close($reader);
+	waitpid($pid, 0);
+	my $child_exit_status = $? >> 8;
+	if ($child_exit_status != 0) {
+		die "'git credential $op' failed with code $child_exit_status.";
+	}
+}
+
 # MediaWiki API instance, created lazily.
 my $mediawiki;
 
 sub mw_connect_maybe {
 	if ($mediawiki) {
-	    return;
+		return;
 	}
 	$mediawiki = MediaWiki::API->new;
 	$mediawiki->{config}->{api_url} = "$url/api.php";
 	if ($wiki_login) {
-		if (!$mediawiki->login({
-			lgname => $wiki_login,
-			lgpassword => $wiki_passwd,
-			lgdomain => $wiki_domain,
-		})) {
-			print STDERR "Failed to log in mediawiki user \"$wiki_login\" on $url\n";
-			print STDERR "(error " .
-			    $mediawiki->{error}->{code} . ': ' .
-			    $mediawiki->{error}->{details} . ")\n";
-			exit 1;
+		my %credential = credential_from_url($url);
+		$credential{username} = $wiki_login;
+		$credential{password} = $wiki_passwd;
+		credential_run("fill", \%credential);
+		my $request = {lgname => $credential{username},
+			       lgpassword => $credential{password},
+			       lgdomain => $wiki_domain};
+		if ($mediawiki->login($request)) {
+			credential_run("approve", \%credential);
+			print STDERR "Logged in mediawiki user \"$credential{username}\".\n";
 		} else {
-			print STDERR "Logged in with user \"$wiki_login\".\n";
+			print STDERR "Failed to log in mediawiki user \"$credential{username}\" on $url\n";
+			print STDERR "  (error " .
+				$mediawiki->{error}->{code} . ': ' .
+				$mediawiki->{error}->{details} . ")\n";
+			credential_run("reject", \%credential);
+			exit 1;
 		}
 	}
 }
-- 
1.7.11.5.g0c7e058.dirty
Previous: Matthieu MoyNext: Junio C Hamano
Message 7 of 11 in “git credential plumbing command: implementation and use”
  1. 0/3 git credential plumbing command: implementation and useMatthieu Moy, Jun 22, 2012
  2. 1/3 add 'git credential' plumbing commandMatthieu Moy, Jun 22, 2012
  3. Junio C HamanoJun 22, 2012
  4. Matthieu MoyJun 24, 2012
  5. 1/3 add 'git credential' plumbing commandMatthieu Moy, Jun 24, 2012
  6. 2/3 git credential fill: output the whole 'struct credential'Matthieu Moy, Jun 24, 2012
  7. 3/3 git-remote-mediawiki: add credential supportMatthieu Moy, Jun 24, 2012
  8. Junio C HamanoJun 26, 2012
  9. 2/3 git credential fill: output the whole 'struct credential'Matthieu Moy, Jun 22, 2012
  10. Junio C HamanoJun 22, 2012
  11. 3/3 git-remote-mediawiki: add credential supportMatthieu Moy, Jun 22, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.