git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
To: Sven Strickroth <sven.strickroth@tu-clausthal.de>
Cc: git@vger.kernel.org, Junio C Hamano <gitster@pobox.com>,
	Jakub Narebski <jnareb@gmail.com>, Jeff King <peff@peff.net>
Subject: Re: [PATCH 1/2] git-svn, perl/Git.pm: add central method for prompting passwords honoring GIT_ASKPASS and SSH_ASKPASS
Date: Tue, 3 Jan 2012 11:17:10 +0100	[thread overview]
Message-ID: <CACBZZX7P9PEq0wZp0d3dSwDjF6J6Z3cO4VtWc9_frBengtqPLw@mail.gmail.com> (raw)
In-Reply-To: <4EFA5EB3.4000802@tu-clausthal.de>

On Wed, Dec 28, 2011 at 01:11, Sven Strickroth
<sven.strickroth@tu-clausthal.de> wrote:

Nom nom, some Perl. Thanks for tackling this. Reviewing it as
requested by Junio.

> diff --git a/git-svn.perl b/git-svn.perl
> index eeb83d3..bcee8aa 100755
> --- a/git-svn.perl
> +++ b/git-svn.perl
> @@ -4415,25 +4415,7 @@ sub username {
>
>  sub _read_password {
>        my ($prompt, $realm) = @_;
> -       my $password = '';
> -       if (exists $ENV{GIT_ASKPASS}) {
> -               open(PH, "-|", $ENV{GIT_ASKPASS}, $prompt);
> -               $password = <PH>;
> -               $password =~ s/[\012\015]//; # \n\r
> -               close(PH);
> -       } else {
> -               print STDERR $prompt;
> -               STDERR->flush;
> -               require Term::ReadKey;
> -               Term::ReadKey::ReadMode('noecho');
> -               while (defined(my $key = Term::ReadKey::ReadKey(0))) {
> -                       last if $key =~ /[\012\015]/; # \n\r
> -                       $password .= $key;
> -               }
> -               Term::ReadKey::ReadMode('restore');
> -               print STDERR "\n";
> -               STDERR->flush;
> -       }
> +       my $password = Git->prompt($prompt);
>        $password;
>  }
>
> diff --git a/perl/Git.pm b/perl/Git.pm
> index f7ce511..b1c7c50 100644
> --- a/perl/Git.pm
> +++ b/perl/Git.pm
> @@ -58,7 +58,7 @@ require Exporter;
>                 command_output_pipe command_input_pipe command_close_pipe
>                 command_bidi_pipe command_close_bidi_pipe
>                 version exec_path html_path hash_object git_cmd_try
> -                remote_refs
> +                remote_refs prompt
>                 temp_acquire temp_release temp_reset temp_path);
>
>
> @@ -512,6 +512,55 @@ C<git --html-path>). Useful mostly only internally.
>  sub html_path { command_oneline('--html-path') }
>
>
> +=item prompt ( PROMPT )
> +
> +Query user C<PROMPT> and return answer from user.
> +
> +Check if GIT_ASKPASS or SSH_ASKPASS is set, use first matching for querying
> +user and return answer. If no *_ASKPASS variable is set, the variable is
> +empty or an error occoured, the terminal is tried as a fallback.
> +
> +=cut
> +
> +sub prompt {
> +       my ($self, $prompt) = _maybe_self(@_);
> +       my $ret;
> +       if (exists $ENV{'GIT_ASKPASS'}) {
> +               $ret = _prompt($ENV{'GIT_ASKPASS'}, $prompt);
> +       }
> +       if (!defined $ret && exists $ENV{'SSH_ASKPASS'}) {
> +               $ret = _prompt($ENV{'SSH_ASKPASS'}, $prompt);
> +       }
> +       if (!defined $ret) {
> +               print STDERR $prompt;
> +               STDERR->flush;
> +               require Term::ReadKey;
> +               Term::ReadKey::ReadMode('noecho');
> +               while (defined(my $key = Term::ReadKey::ReadKey(0))) {
> +                       last if $key =~ /[\012\015]/; # \n\r
> +                       $ret .= $key;
> +               }
> +               Term::ReadKey::ReadMode('restore');
> +               print STDERR "\n";
> +               STDERR->flush;
> +       }
> +       return $ret;
> +}

Personally I prefer not to write code I don't have to write. Here
you're doing:

    my ($self, $prompt) = _maybe_self(@_);

And then never using $self, so there's actually no reason for this to
be an object/class function. It could just be called as:

    my $password = Git::prompt($prompt);

Instead of:

    my $password = Git->prompt($prompt);

Which means you could change the first line to just:

    my ($prompt) = @_;

Which wouldn't leave the reader wondering why this needs to maybe
construct an object just to throw it away.

> +sub _prompt {
> +       my ($askpass, $prompt) = @_;
> +       unless ($askpass) {
> +               return undef;
> +       }

The empty list is false in Perl, so explicitly returning undef is
usually the wrong thing. It means that in list context you'll return a
true list (consisting of one undef element), instead of an empty false
one.

    $ perl -MData::Dump=dump -wle 'sub a { return } sub b { return
undef }; my @lists = ([a()], [b()]); for (@lists) { print @$_ ? "true"
: "false" }'
    false
    true

You're not running into that error here since you always use scalar
context. But it's better just to do:

    if (xyz) {
        return;
    }

Unless you want this behavior.

But aside from that I find this code a bit bizarre. The caller is
doing:

    if (exists $ENV{'GIT_ASKPASS'}) {
            $ret = _prompt($ENV{'GIT_ASKPASS'}, $prompt);
    }
    if (!defined $ret && exists $ENV{'SSH_ASKPASS'}) {
            $ret = _prompt($ENV{'SSH_ASKPASS'}, $prompt);
    }

Which means we check whether *_ASKPASS *exists* in the env hash, and
then the function checks whether that value is true or not.

Which means the code implicitly depends on Perl's idea of true/false
values for the names of those commands. E.g. you can't create a
command called "0" and put it in your $PATH.

I suppose the case you actually care about is someone being able to do:

    export GIT_ASKPASS=

Instead of the better:

    unset GIT_ASKPASS

> +       my $ret;
> +       open my $fh, "-|", $askpass, $prompt || return undef;

As pointed out already this is a logic error due to the ||.

But even if that worked I think this behavior is a bit
questionable. Why don't we just throw an error at this point? The way
I'd write this would be something like:

    my $pass = _prompt('GIT_ASKPASS', $prompt);

And then:

    sub _prompt {
        my ($env_var, $prompt) = @_;

        # or exists(), depending on whether we insist on "unset"
        return unless length $ENV{$env_var};

        my $command = $ENV{$env_var};
        open my $fh, "-|", $command or die "We can't get your password
from `$command' given in $env_var: $!";
        chomp(my $password = <$fh>);
        close $fh or die "We can't close() `$command' given in $env_var: $!";

        return $password;
    }

Which would give the user an error if his GIT_ASKPASS command
failed. Check the return value of close() too, and re-structure the
passing around of the env variable so we could give a sensible error
message.

> +       $ret = <$fh>;
> +       $ret =~ s/[\012\015]//g; # strip \n\r, chomp does not work on all systems (i.e. windows) as expected

Urm yes it does. \n in Perl is magical and doesn't mean \012 like it
does in some languages. It means "The Platform's Native
Newline".

Which is \012 on Unix, \015\012 on Windows, and was \015 on Mac OS
until support for it was removed. This is covered in the second
section of "perldoc perlport".

Can you show me a case where it fails, and under what environment
exactly? Maybe it's e.g.s some Cygwin-specific peculiarity, in which
case we could check for that platform specifically.

  parent reply	other threads:[~2012-01-03 10:17 UTC|newest]

Thread overview: 82+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-17 15:15 [PATCH] honour GIT_ASKPASS for querying username in git-svn Sven Strickroth
2011-11-18 11:36 ` Erik Faye-Lund
2011-11-18 13:30   ` Sven Strickroth
2011-11-18 14:19     ` Erik Faye-Lund
2011-11-26 11:33       ` Sven Strickroth
2011-11-30  6:44         ` Jeff King
2011-12-26 23:49           ` Sven Strickroth
2011-12-27 14:33             ` Jakub Narebski
2011-12-27 14:39               ` Sven Strickroth
2011-12-27 16:00                 ` Jakub Narebski
2011-12-27 16:01                 ` [PATCH 0/5] honour *_ASKPASS for querying user " Sven Strickroth
2011-12-27 16:05                   ` [PATCH 1/5] add central method for prompting a user using GIT_ASKPASS or SSH_ASKPASS Sven Strickroth
2011-12-27 20:47                     ` Junio C Hamano
2011-12-27 23:12                       ` Thomas Adam
2011-12-27 23:35                         ` Junio C Hamano
2011-12-27 16:06                   ` [PATCH 2/5] switch to central prompt method Sven Strickroth
2011-12-27 20:47                     ` Junio C Hamano
2011-12-27 16:07                   ` [PATCH 3/5] honour *_ASKPASS for querying username and for querying further actions like unknown certificates Sven Strickroth
2011-12-27 20:56                     ` Junio C Hamano
2011-12-27 16:07                   ` [PATCH 4/5] ignore empty *_ASKPASS variables Sven Strickroth
2011-12-27 21:00                     ` Junio C Hamano
2011-12-27 16:07                   ` [PATCH 5/5] make askpass_prompt a global prompt method for asking users Sven Strickroth
2011-12-27 21:10                     ` Junio C Hamano
2011-12-27 21:41                       ` Junio C Hamano
2011-12-28  0:11                         ` [PATCH 1/2] git-svn, perl/Git.pm: add central method for prompting passwords honoring GIT_ASKPASS and SSH_ASKPASS Sven Strickroth
2011-12-28  2:34                           ` Junio C Hamano
2011-12-28 16:17                             ` Sven Strickroth
2011-12-28 18:56                             ` Jakub Narebski
2012-01-03 10:17                           ` Ævar Arnfjörð Bjarmason [this message]
2012-01-03 10:25                             ` Sven Strickroth
2012-01-03 12:03                               ` Ævar Arnfjörð Bjarmason
2012-01-03 12:06                                 ` Ævar Arnfjörð Bjarmason
2012-01-03 13:18                                 ` Sven Strickroth
2012-01-03 19:42                                 ` Junio C Hamano
2012-01-03 22:51                             ` Junio C Hamano
2012-01-03 23:27                               ` Sven Strickroth
2012-01-04  0:10                                 ` Junio C Hamano
2012-01-04  7:55                                   ` Sven Strickroth
2012-01-04  8:31                                     ` Sven Strickroth
2012-01-04 13:34                                       ` Jeff King
2012-01-04 14:13                                         ` Sven Strickroth
2012-01-04 19:08                                       ` Junio C Hamano
2012-01-07  4:27                                         ` Sven Strickroth
2012-01-04 18:58                                     ` Junio C Hamano
2012-01-04 19:20                                       ` Sven Strickroth
2011-12-28  0:12                         ` [PATCH 2/2] git-svn, perl/Git.pm: extend and use Git->prompt method for querying users Sven Strickroth
2011-12-28  2:41                           ` Junio C Hamano
2011-12-28 10:41                             ` Sven Strickroth
2011-12-28 21:00                               ` Junio C Hamano
2011-12-28 21:38                                 ` Junio C Hamano
2011-12-28 21:47                                   ` Sven Strickroth
2011-12-28 22:29                                     ` Junio C Hamano
2011-12-30  4:40                                       ` Sven Strickroth
2011-12-30 13:54                                         ` Jeff King
2011-12-30 14:53                                           ` Sven Strickroth
2012-01-01  9:11                                             ` Junio C Hamano
2012-01-01 19:57                                               ` Sven Strickroth
2012-01-01 20:55                                                 ` Sven Strickroth
2012-01-01 19:45                                   ` Sven Strickroth
2012-01-03 18:19                                     ` Junio C Hamano
2012-01-03 18:40                                       ` Jeff King
2012-02-12 16:02                                         ` Sven Strickroth
2012-02-12 16:11                                           ` Jakub Narebski
2012-02-12 16:26                                             ` Sven Strickroth
2012-02-14 22:20                                               ` Jeff King
2012-02-14 22:35                                                 ` Junio C Hamano
2012-02-14 22:47                                                   ` Jeff King
2012-01-03 23:24                                       ` Sven Strickroth
2012-01-04  0:12                                         ` Junio C Hamano
2012-10-06 15:18                                           ` Sven Strickroth
2012-10-06 18:28                                             ` Junio C Hamano
2012-11-11 16:40                                               ` [PATCH 0/2] second try Sven Strickroth
2012-11-24 19:07                                                 ` Sven Strickroth
2012-11-26  4:50                                                   ` Junio C Hamano
2012-12-17 15:54                                                     ` Sven Strickroth
2012-12-17 20:08                                                       ` Junio C Hamano
2012-12-18  0:28                                                         ` [PATCH 1/3] git-svn, perl/Git.pm: add central method for prompting passwords Sven Strickroth
2012-12-18  0:28                                                         ` [PATCH 2/3] perl/Git.pm: Honor SSH_ASKPASS as fallback if GIT_ASKPASS is not set Sven Strickroth
2012-12-18  0:57                                                           ` Jeff King
2012-12-18  0:28                                                         ` [PATCH 3/3] git-svn, perl/Git.pm: extend and use Git->prompt method for querying users Sven Strickroth
2012-11-11 16:40                                               ` [PATCH 1/2] git-svn, perl/Git.pm: add central method for prompting passwords honoring GIT_ASKPASS and SSH_ASKPASS Sven Strickroth
2012-11-11 16:41                                               ` [PATCH 2/2] git-svn, perl/Git.pm: extend and use Git->prompt method for querying users Sven Strickroth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CACBZZX7P9PEq0wZp0d3dSwDjF6J6Z3cO4VtWc9_frBengtqPLw@mail.gmail.com \
    --to=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jnareb@gmail.com \
    --cc=peff@peff.net \
    --cc=sven.strickroth@tu-clausthal.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).