From ab58bcb9909967503bc4ed810f2053b8ed6efb2e Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 27 Jun 2020 10:03:57 +0000 Subject: watch: use our own "git credential" wrapper Git.pm may not be installed on some systems; or some users have multiple Perl installations and Git.pm is not available to the Perl running -watch. Accomodate both those types of users by providing our own "git credential" wrapper. --- lib/PublicInbox/GitCredential.pm | 40 ++++++++++++++++++++++++++++++++++++++++ lib/PublicInbox/WatchMaildir.pm | 22 ++++++++++------------ 2 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 lib/PublicInbox/GitCredential.pm (limited to 'lib') diff --git a/lib/PublicInbox/GitCredential.pm b/lib/PublicInbox/GitCredential.pm new file mode 100644 index 00000000..826e7a55 --- /dev/null +++ b/lib/PublicInbox/GitCredential.pm @@ -0,0 +1,40 @@ +# Copyright (C) 2020 all contributors +# License: AGPL-3.0+ +package PublicInbox::GitCredential; +use strict; +use PublicInbox::Spawn qw(popen_rd); + +sub run ($$) { + my ($self, $op) = @_; + my ($in_r, $in_w); + pipe($in_r, $in_w) or die "pipe: $!"; + my $out_r = popen_rd([qw(git credential), $op], undef, { 0 => $in_r }); + close $in_r or die "close in_r: $!"; + + my $out = ''; + for my $k (qw(url protocol host username password)) { + defined(my $v = $self->{$k}) or next; + die "`$k' contains `\\n' or `\\0'\n" if $v =~ /[\n\0]/; + $out .= "$k=$v\n"; + } + $out .= "\n"; + print $in_w $out or die "print (git credential $op): $!"; + close $in_w or die "close (git credential $op): $!"; + return $out_r if $op eq 'fill'; + <$out_r> and die "unexpected output from `git credential $op'\n"; + close $out_r or die "`git credential $op' failed: \$!=$! \$?=$?\n"; +} + +sub fill { + my ($self) = @_; + my $out_r = run($self, 'fill'); + while (<$out_r>) { + chomp; + return if $_ eq ''; + /\A([^=]+)=(.*)\z/ or die "bad line: $_\n"; + $self->{$1} = $2; + } + close $out_r or die "git credential fill failed: \$!=$! \$?=$?\n"; +} + +1; diff --git a/lib/PublicInbox/WatchMaildir.pm b/lib/PublicInbox/WatchMaildir.pm index d2f410d0..b89462de 100644 --- a/lib/PublicInbox/WatchMaildir.pm +++ b/lib/PublicInbox/WatchMaildir.pm @@ -308,13 +308,14 @@ sub auth_anon_cb { '' }; # for Mail::IMAPClient::Authcallback sub mic_for ($$$) { # mic = Mail::IMAPClient my ($self, $url, $mic_args) = @_; my $uri = PublicInbox::URIimap->new($url); - my $cred = { + require PublicInbox::GitCredential; + my $cred = bless { url => $url, protocol => $uri->scheme, host => $uri->host, username => $uri->user, password => $uri->password, - }; + }, 'PublicInbox::GitCredential'; my $common = $mic_args->{uri_section($uri)} // {}; my $host = $cred->{host}; my $mic_arg = { @@ -342,7 +343,7 @@ sub mic_for ($$$) { # mic = Mail::IMAPClient $cred = undef; } if ($cred) { - Git::credential($cred, 'fill'); # may prompt user here + $cred->fill; # may prompt user here $mic->User($mic_arg->{User} = $cred->{username}); $mic->Password($mic_arg->{Password} = $cred->{password}); } else { # AUTH=ANONYMOUS @@ -356,7 +357,7 @@ sub mic_for ($$$) { # mic = Mail::IMAPClient warn "E: <$url> LOGIN: $@\n"; $mic = undef; } - Git::credential($cred, $mic ? 'approve' : 'reject') if $cred; + $cred->run($mic ? 'approve' : 'reject') if $cred; $mic; } @@ -653,8 +654,6 @@ sub watch_imap_init ($) { my ($self) = @_; eval { require PublicInbox::IMAPClient } or die "Mail::IMAPClient is required for IMAP:\n$@\n"; - eval { require Git } or - die "Git (Perl module) is required for IMAP:\n$@\n"; eval { require PublicInbox::IMAPTracker } or die "DBD::SQLite is required for IMAP\n:$@\n"; @@ -772,11 +771,12 @@ sub nn_for ($$$) { # nn = Net::NNTP my $cred; my ($u, $p); if (defined(my $ui = $uri->userinfo)) { - $cred = { + require PublicInbox::GitCredential; + $cred = bless { url => $sec, protocol => uri_scheme($uri), host => $uri->host, - }; + }, 'PublicInbox::GitCredential'; ($u, $p) = split(/:/, $ui, 2); ($cred->{username}, $cred->{password}) = ($u, $p); } @@ -791,7 +791,7 @@ sub nn_for ($$$) { # nn = Net::NNTP my $nn = nn_new($nn_arg, $nntp_opt, $url); if ($cred) { - Git::credential($cred, 'fill'); # may prompt user here + $cred->fill; # may prompt user here if ($nn->authinfo($u, $p)) { push @{$nntp_opt->{-postconn}}, [ 'authinfo', $u, $p ]; } else { @@ -818,7 +818,7 @@ W: see https://rt.cpan.org/Ticket/Display.html?id=129967 for updates } $self->{nn_arg}->{$sec} = $nn_arg; - Git::credential($cred, $nn ? 'approve' : 'reject') if $cred; + $cred->run($nn ? 'approve' : 'reject') if $cred; $nn; } @@ -896,8 +896,6 @@ sub watch_nntp_init ($) { my ($self) = @_; eval { require Net::NNTP } or die "Net::NNTP is required for NNTP:\n$@\n"; - eval { require Git } or - die "Git (Perl module) is required for NNTP:\n$@\n"; eval { require PublicInbox::IMAPTracker } or die "DBD::SQLite is required for NNTP\n:$@\n"; -- cgit v1.2.3-24-ge0c7