git-credential-netrc: accept gpg option

git-credential-netrc was hardcoded to decrypt with 'gpg' regardless of the gpg.program option. This is a problem on distributions like Debian that call modern GnuPG something else, like 'gpg2'. Set the command according to these settings in descending precedence 1. the git-credential-netrc command -g|--gpg option 2. the git gpg.program configuration option 3. the default: 'gpg' For conformance with Documentation/CodingGuidelines - use Git.pm for repository and global option queries - document -g|--gpg command option in command usage - test repository & command options - write documentation placeholders according to main standards Signed-off-by: Luis Marsano <luis.marsano@gmail.com> Acked-by: Ted Zlatanov <tzz@lifelogs.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Luis Marsano committed May 12, 2018 at 05:17 UTC 786ef50a23cbd0e93d1e41982cfaba76801ed885
6 files changed +62 -24
contrib/credential/netrc/git-credential-netrc
+38 -20
@@ -2,11 +2,13 @@
2
3 use strict;
4 use warnings;
5 +use autodie;
6
7 use Getopt::Long;
8 use File::Basename;
9 +use Git;
10
9 -my $VERSION = "0.1";
11 +my $VERSION = "0.2";
12
13 my %options = (
14 help => 0,
@@ -54,6 +56,7 @@ GetOptions(\%options,
56 "insecure|k",
57 "verbose|v",
58 "file|f=s@",
59 + 'gpg|g:s',
60 );
61
62 if ($options{help}) {
@@ -62,27 +65,31 @@ if ($options{help}) {
65
66 print <<EOHIPPUS;
67
65 -$0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] [-v] [-k] get
68 +$0 [(-f <authfile>)...] [-g <program>] [-d] [-v] [-k] get
69
70 Version $VERSION by tzz\@lifelogs.com. License: BSD.
71
72 Options:
73
71 - -f|--file AUTHFILE : specify netrc-style files. Files with the .gpg extension
72 - will be decrypted by GPG before parsing. Multiple -f
73 - arguments are OK. They are processed in order, and the
74 - first matching entry found is returned via the credential
75 - helper protocol (see below).
74 + -f|--file <authfile>: specify netrc-style files. Files with the .gpg
75 + extension will be decrypted by GPG before parsing.
76 + Multiple -f arguments are OK. They are processed in
77 + order, and the first matching entry found is returned
78 + via the credential helper protocol (see below).
79
77 - When no -f option is given, .authinfo.gpg, .netrc.gpg,
78 - .authinfo, and .netrc files in your home directory are used
79 - in this order.
80 + When no -f option is given, .authinfo.gpg, .netrc.gpg,
81 + .authinfo, and .netrc files in your home directory are
82 + used in this order.
83
81 - -k|--insecure : ignore bad file ownership or permissions
84 + -g|--gpg <program> : specify the program for GPG. By default, this is the
85 + value of gpg.program in the git repository or global
86 + option or gpg.
87
83 - -d|--debug : turn on debugging (developer info)
88 + -k|--insecure : ignore bad file ownership or permissions
89
85 - -v|--verbose : be more verbose (show files and information found)
90 + -d|--debug : turn on debugging (developer info)
91 +
92 + -v|--verbose : be more verbose (show files and information found)
93
94 To enable this credential helper:
95
@@ -99,8 +106,9 @@ in the path.)
106
107 git config credential.helper '$shortname -f AUTHFILE -v'
108
102 -Only "get" mode is supported by this credential helper. It opens every AUTHFILE
103 -and looks for the first entry that matches the requested search criteria:
109 +Only "get" mode is supported by this credential helper. It opens every
110 +<authfile> and looks for the first entry that matches the requested search
111 +criteria:
112
113 'port|protocol':
114 The protocol that will be used (e.g., https). (protocol=X)
@@ -120,7 +128,7 @@ host=github.com
128 protocol=https
129 username=tzz
130
123 -this credential helper will look for the first entry in every AUTHFILE that
131 +this credential helper will look for the first entry in every <authfile> that
132 matches
133
134 machine github.com port https login tzz
@@ -137,8 +145,8 @@ Then, the helper will print out whatever tokens it got from the entry, including
145 back to "protocol". Any redundant entry tokens (part of the original query) are
146 skipped.
147
140 -Again, note that only the first matching entry from all the AUTHFILEs, processed
141 -in the sequence given on the command line, is used.
148 +Again, note that only the first matching entry from all the <authfile>s,
149 +processed in the sequence given on the command line, is used.
150
151 Netrc/authinfo tokens can be quoted as 'STRING' or "STRING".
152
@@ -152,7 +160,7 @@ EOHIPPUS
160 my $mode = shift @ARGV;
161
162 # Credentials must get a parameter, so die if it's missing.
155 -die "Syntax: $0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] get" unless defined $mode;
163 +die "Syntax: $0 [(-f <authfile>)...] [-d] get" unless defined $mode;
164
165 # Only support 'get' mode; with any other unsupported ones we just exit.
166 exit 0 unless $mode eq 'get';
@@ -172,6 +180,8 @@ unless (scalar @$files) {
180 $files = $options{file} = [ map { glob $_ } @candidates ];
181 }
182
183 +load_config(\%options);
184 +
185 my $query = read_credential_data_from_stdin();
186
187 FILE:
@@ -233,7 +243,7 @@ sub load_netrc {
243
244 my $io;
245 if ($gpgmode) {
236 - my @cmd = (qw(gpg --decrypt), $file);
246 + my @cmd = ($options{'gpg'}, qw(--decrypt), $file);
247 log_verbose("Using GPG to open $file: [@cmd]");
248 open $io, "-|", @cmd;
249 } else {
@@ -410,6 +420,14 @@ sub print_credential_data {
420 printf "%s=%s\n", $git_token, $entry->{$git_token};
421 }
422 }
423 +sub load_config {
424 + # load settings from git config
425 + my $options = shift;
426 + # set from command argument, gpg.program option, or default to gpg
427 + $options->{'gpg'} //= Git->repository()->config('gpg.program')
428 + // 'gpg';
429 + log_verbose("using $options{'gpg'} for GPG operations");
430 +}
431 sub log_verbose {
432 return unless $options{verbose};
433 printf STDERR @_;
contrib/credential/netrc/t-git-credential-netrc.sh
+1 -1
@@ -18,7 +18,7 @@
18
19 test_expect_success \
20 'set up test repository' \
21 - :
21 + 'git config --add gpg.program test.git-config-gpg'
22
23 # The external test will outputs its own plan
24 test_external_has_tap=1
contrib/credential/netrc/test.command-option-gpg new
+2
@@ -0,0 +1,2 @@
1 +#!/bin/sh
2 +echo machine command-option-gpg login username password password
contrib/credential/netrc/test.git-config-gpg new
+2
@@ -0,0 +1,2 @@
1 +#!/bin/sh
2 +echo machine git-config-gpg login username password password
contrib/credential/netrc/test.netrc.gpg
contrib/credential/netrc/test.pl
+19 -3
@@ -9,15 +9,18 @@ use File::Spec::Functions qw(:DEFAULT rel2abs);
9 use IPC::Open2;
10
11 BEGIN {
12 - # t-git-credential-netrc.sh kicks off our testing, so we have to go from there.
12 + # t-git-credential-netrc.sh kicks off our testing, so we have to go
13 + # from there.
14 Test::More->builder->current_test(1);
15 Test::More->builder->no_ending(1);
16 }
17
18 my @global_credential_args = @ARGV;
19 my $scriptDir = dirname rel2abs $0;
19 -my $netrc = catfile $scriptDir, 'test.netrc';
20 -my $gcNetrc = catfile $scriptDir, 'git-credential-netrc';
20 +my ($netrc, $netrcGpg, $gcNetrc) = map { catfile $scriptDir, $_; }
21 + qw(test.netrc
22 + test.netrc.gpg
23 + git-credential-netrc);
24 local $ENV{PATH} = join ':'
25 , $scriptDir
26 , $ENV{PATH}
@@ -87,6 +90,19 @@ ok(scalar keys %$cred == 2, "Got 2 'host:port kills host' keys");
90 is($cred->{password}, 'bobwillknow', "Got correct 'host:port kills host' password");
91 is($cred->{username}, 'bob', "Got correct 'host:port kills host' username");
92
93 +diag 'Testing netrc file decryption by git config gpg.program setting\n';
94 +$cred = run_credential( ['-f', $netrcGpg, 'get']
95 + , { host => 'git-config-gpg' }
96 + );
97 +
98 +ok(scalar keys %$cred == 2, 'Got keys decrypted by git config option');
99 +
100 +diag 'Testing netrc file decryption by gpg option\n';
101 +$cred = run_credential( ['-f', $netrcGpg, '-g', 'test.command-option-gpg', 'get']
102 + , { host => 'command-option-gpg' }
103 + );
104 +
105 +ok(scalar keys %$cred == 2, 'Got keys decrypted by command option');
106
107 sub run_credential
108 {