]> Sergey Matveev's repositories - public-inbox.git/blob - lib/PublicInbox/GitCredential.pm
ds: support greeting protocols
[public-inbox.git] / lib / PublicInbox / GitCredential.pm
1 # Copyright (C) 2020-2021 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3 package PublicInbox::GitCredential;
4 use strict;
5 use PublicInbox::Spawn qw(popen_rd);
6
7 sub run ($$;$) {
8         my ($self, $op, $lei) = @_;
9         my ($in_r, $in_w, $out_r);
10         my $cmd = [ qw(git credential), $op ];
11         pipe($in_r, $in_w) or die "pipe: $!";
12         if ($lei) { # we'll die if disconnected:
13                 pipe($out_r, my $out_w) or die "pipe: $!";
14                 $lei->send_exec_cmd([ $in_r, $out_w ], $cmd, {});
15         } else {
16                 $out_r = popen_rd($cmd, undef, { 0 => $in_r });
17         }
18         close $in_r or die "close in_r: $!";
19
20         my $out = '';
21         for my $k (qw(url protocol host username password)) {
22                 defined(my $v = $self->{$k}) or next;
23                 die "`$k' contains `\\n' or `\\0'\n" if $v =~ /[\n\0]/;
24                 $out .= "$k=$v\n";
25         }
26         $out .= "\n";
27         print $in_w $out or die "print (git credential $op): $!";
28         close $in_w or die "close (git credential $op): $!";
29         return $out_r if $op eq 'fill';
30         <$out_r> and die "unexpected output from `git credential $op'\n";
31         close $out_r or die "`git credential $op' failed: \$!=$! \$?=$?\n";
32 }
33
34 sub check_netrc {
35         my ($self, $lei) = @_;
36
37         # n.b. lei doesn't load ~/.netrc by default, public-inbox-watch does,
38         # which may've been a mistake, but we have to live with it.
39         return if ($lei && !$lei->{opt}->{netrc});
40
41         # part of the standard library, but distributions may split it out
42         eval { require Net::Netrc };
43         if ($@) {
44                 warn "W: Net::Netrc missing: $@\n";
45                 return;
46         }
47         if (my $x = Net::Netrc->lookup($self->{host}, $self->{username})) {
48                 $self->{username} //= $x->login;
49                 $self->{password} = $x->password;
50         }
51 }
52
53 sub fill {
54         my ($self, $lei) = @_;
55         my $out_r = run($self, 'fill', $lei);
56         while (<$out_r>) {
57                 chomp;
58                 return if $_ eq '';
59                 /\A([^=]+)=(.*)\z/ or die "bad line: $_\n";
60                 $self->{$1} = $2;
61         }
62         close $out_r or die "git credential fill failed: \$!=$! \$?=$?\n";
63         $self->{filled} = 1;
64 }
65
66 1;