git-credential-netrc: accept gpg option
authorLuis Marsano <luis.marsano@gmail.com>
Sat, 12 May 2018 09:17:28 +0000 (05:17 -0400)
committerJunio C Hamano <gitster@pobox.com>
Sun, 13 May 2018 23:53:08 +0000 (08:53 +0900)
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>
contrib/credential/netrc/git-credential-netrc
contrib/credential/netrc/t-git-credential-netrc.sh
contrib/credential/netrc/test.command-option-gpg [new file with mode: 0755]
contrib/credential/netrc/test.git-config-gpg [new file with mode: 0755]
contrib/credential/netrc/test.netrc.gpg [new file with mode: 0644]
contrib/credential/netrc/test.pl
index 1571a7b2693e50ac93828a76a01366da1e8a6983..0b9a94102ec90be0a51900113092a5177850f3dc 100755 (executable)
@@ -2,11 +2,13 @@
 
 use strict;
 use warnings;
 
 use strict;
 use warnings;
+use autodie;
 
 use Getopt::Long;
 use File::Basename;
 
 use Getopt::Long;
 use File::Basename;
+use Git;
 
 
-my $VERSION = "0.1";
+my $VERSION = "0.2";
 
 my %options = (
               help => 0,
 
 my %options = (
               help => 0,
@@ -54,6 +56,7 @@ GetOptions(\%options,
            "insecure|k",
            "verbose|v",
            "file|f=s@",
            "insecure|k",
            "verbose|v",
            "file|f=s@",
+           'gpg|g:s',
           );
 
 if ($options{help}) {
           );
 
 if ($options{help}) {
@@ -62,27 +65,31 @@ if ($options{help}) {
 
        print <<EOHIPPUS;
 
 
        print <<EOHIPPUS;
 
-$0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] [-v] [-k] get
+$0 [(-f <authfile>)...] [-g <program>] [-d] [-v] [-k] get
 
 Version $VERSION by tzz\@lifelogs.com.  License: BSD.
 
 Options:
 
 
 Version $VERSION by tzz\@lifelogs.com.  License: BSD.
 
 Options:
 
-  -f|--file AUTHFILE : specify netrc-style files.  Files with the .gpg extension
-                       will be decrypted by GPG before parsing.  Multiple -f
-                       arguments are OK.  They are processed in order, and the
-                       first matching entry found is returned via the credential
-                       helper protocol (see below).
+  -f|--file <authfile>: specify netrc-style files.  Files with the .gpg
+                        extension will be decrypted by GPG before parsing.
+                        Multiple -f arguments are OK.  They are processed in
+                        order, and the first matching entry found is returned
+                        via the credential helper protocol (see below).
 
 
-                       When no -f option is given, .authinfo.gpg, .netrc.gpg,
-                      .authinfo, and .netrc files in your home directory are used
-                      in this order.
+                        When no -f option is given, .authinfo.gpg, .netrc.gpg,
+                        .authinfo, and .netrc files in your home directory are
+                        used in this order.
 
 
-  -k|--insecure      : ignore bad file ownership or permissions
+  -g|--gpg <program>  : specify the program for GPG. By default, this is the
+                        value of gpg.program in the git repository or global
+                        option or gpg.
 
 
-  -d|--debug         : turn on debugging (developer info)
+  -k|--insecure       : ignore bad file ownership or permissions
 
 
-  -v|--verbose       : be more verbose (show files and information found)
+  -d|--debug          : turn on debugging (developer info)
+
+  -v|--verbose        : be more verbose (show files and information found)
 
 To enable this credential helper:
 
 
 To enable this credential helper:
 
@@ -99,8 +106,9 @@ in the path.)
 
   git config credential.helper '$shortname -f AUTHFILE -v'
 
 
   git config credential.helper '$shortname -f AUTHFILE -v'
 
-Only "get" mode is supported by this credential helper.  It opens every AUTHFILE
-and looks for the first entry that matches the requested search criteria:
+Only "get" mode is supported by this credential helper.  It opens every
+<authfile> and looks for the first entry that matches the requested search
+criteria:
 
  'port|protocol':
    The protocol that will be used (e.g., https). (protocol=X)
 
  'port|protocol':
    The protocol that will be used (e.g., https). (protocol=X)
@@ -120,7 +128,7 @@ host=github.com
 protocol=https
 username=tzz
 
 protocol=https
 username=tzz
 
-this credential helper will look for the first entry in every AUTHFILE that
+this credential helper will look for the first entry in every <authfile> that
 matches
 
 machine github.com port https login tzz
 matches
 
 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
 back to "protocol".  Any redundant entry tokens (part of the original query) are
 skipped.
 
 back to "protocol".  Any redundant entry tokens (part of the original query) are
 skipped.
 
-Again, note that only the first matching entry from all the AUTHFILEs, processed
-in the sequence given on the command line, is used.
+Again, note that only the first matching entry from all the <authfile>s,
+processed in the sequence given on the command line, is used.
 
 Netrc/authinfo tokens can be quoted as 'STRING' or "STRING".
 
 
 Netrc/authinfo tokens can be quoted as 'STRING' or "STRING".
 
@@ -152,7 +160,7 @@ EOHIPPUS
 my $mode = shift @ARGV;
 
 # Credentials must get a parameter, so die if it's missing.
 my $mode = shift @ARGV;
 
 # Credentials must get a parameter, so die if it's missing.
-die "Syntax: $0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] get" unless defined $mode;
+die "Syntax: $0 [(-f <authfile>)...] [-d] get" unless defined $mode;
 
 # Only support 'get' mode; with any other unsupported ones we just exit.
 exit 0 unless $mode eq 'get';
 
 # Only support 'get' mode; with any other unsupported ones we just exit.
 exit 0 unless $mode eq 'get';
@@ -172,6 +180,8 @@ unless (scalar @$files) {
        $files = $options{file} = [ map { glob $_ } @candidates ];
 }
 
        $files = $options{file} = [ map { glob $_ } @candidates ];
 }
 
+load_config(\%options);
+
 my $query = read_credential_data_from_stdin();
 
 FILE:
 my $query = read_credential_data_from_stdin();
 
 FILE:
@@ -233,7 +243,7 @@ sub load_netrc {
 
        my $io;
        if ($gpgmode) {
 
        my $io;
        if ($gpgmode) {
-               my @cmd = (qw(gpg --decrypt), $file);
+               my @cmd = ($options{'gpg'}, qw(--decrypt), $file);
                log_verbose("Using GPG to open $file: [@cmd]");
                open $io, "-|", @cmd;
        } else {
                log_verbose("Using GPG to open $file: [@cmd]");
                open $io, "-|", @cmd;
        } else {
@@ -410,6 +420,14 @@ sub print_credential_data {
                printf "%s=%s\n", $git_token, $entry->{$git_token};
        }
 }
                printf "%s=%s\n", $git_token, $entry->{$git_token};
        }
 }
+sub load_config {
+       # load settings from git config
+       my $options = shift;
+       # set from command argument, gpg.program option, or default to gpg
+       $options->{'gpg'} //= Git->repository()->config('gpg.program')
+                         // 'gpg';
+       log_verbose("using $options{'gpg'} for GPG operations");
+}
 sub log_verbose {
        return unless $options{verbose};
        printf STDERR @_;
 sub log_verbose {
        return unless $options{verbose};
        printf STDERR @_;
index efb81efedfa4f4a1051a2da1e9ba36c5c289fb52..58191a62f8623642d4bf1f2af50130132d529fb3 100755 (executable)
@@ -18,7 +18,7 @@
 
        test_expect_success \
     'set up test repository' \
 
        test_expect_success \
     'set up test repository' \
-    :
+    'git config --add gpg.program test.git-config-gpg'
 
        # The external test will outputs its own plan
        test_external_has_tap=1
 
        # The external test will outputs its own plan
        test_external_has_tap=1
diff --git a/contrib/credential/netrc/test.command-option-gpg b/contrib/credential/netrc/test.command-option-gpg
new file mode 100755 (executable)
index 0000000..d8f1285
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo machine command-option-gpg login username password password
diff --git a/contrib/credential/netrc/test.git-config-gpg b/contrib/credential/netrc/test.git-config-gpg
new file mode 100755 (executable)
index 0000000..65cf594
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo machine git-config-gpg login username password password
diff --git a/contrib/credential/netrc/test.netrc.gpg b/contrib/credential/netrc/test.netrc.gpg
new file mode 100644 (file)
index 0000000..e69de29
index ea95a2c8ad77d1438c23abb1d1b38e6f9f29b6da..1e1001030e7631dd49cbfeb002b429158019f191 100755 (executable)
@@ -9,15 +9,18 @@
 use IPC::Open2;
 
 BEGIN {
 use IPC::Open2;
 
 BEGIN {
-       # t-git-credential-netrc.sh kicks off our testing, so we have to go from there.
+       # t-git-credential-netrc.sh kicks off our testing, so we have to go
+       # from there.
        Test::More->builder->current_test(1);
        Test::More->builder->no_ending(1);
 }
 
 my @global_credential_args = @ARGV;
 my $scriptDir = dirname rel2abs $0;
        Test::More->builder->current_test(1);
        Test::More->builder->no_ending(1);
 }
 
 my @global_credential_args = @ARGV;
 my $scriptDir = dirname rel2abs $0;
-my $netrc = catfile $scriptDir, 'test.netrc';
-my $gcNetrc = catfile $scriptDir, 'git-credential-netrc';
+my ($netrc, $netrcGpg, $gcNetrc) = map { catfile $scriptDir, $_; }
+                                       qw(test.netrc
+                                          test.netrc.gpg
+                                          git-credential-netrc);
 local $ENV{PATH} = join ':'
                       , $scriptDir
                       , $ENV{PATH}
 local $ENV{PATH} = join ':'
                       , $scriptDir
                       , $ENV{PATH}
@@ -87,6 +90,19 @@ BEGIN
 is($cred->{password}, 'bobwillknow', "Got correct 'host:port kills host' password");
 is($cred->{username}, 'bob', "Got correct 'host:port kills host' username");
 
 is($cred->{password}, 'bobwillknow', "Got correct 'host:port kills host' password");
 is($cred->{username}, 'bob', "Got correct 'host:port kills host' username");
 
+diag 'Testing netrc file decryption by git config gpg.program setting\n';
+$cred = run_credential( ['-f', $netrcGpg, 'get']
+                      , { host => 'git-config-gpg' }
+                      );
+
+ok(scalar keys %$cred == 2, 'Got keys decrypted by git config option');
+
+diag 'Testing netrc file decryption by gpg option\n';
+$cred = run_credential( ['-f', $netrcGpg, '-g', 'test.command-option-gpg', 'get']
+                      , { host => 'command-option-gpg' }
+                      );
+
+ok(scalar keys %$cred == 2, 'Got keys decrypted by command option');
 
 sub run_credential
 {
 
 sub run_credential
 {