git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Aguilar <davvid@gmail.com>
To: Tim Henigan <tim.henigan@gmail.com>
Cc: gitster@pobox.com, git@vger.kernel.org
Subject: Re: [PATCH 1/9] difftool: parse options using Getopt::Long
Date: Fri, 16 Mar 2012 20:21:31 -0700	[thread overview]
Message-ID: <CAJDDKr7BTz-2THw1JaJEDcK1G4Uxwc88=gFsHCSONHAtqtypRw@mail.gmail.com> (raw)
In-Reply-To: <1331949442-15039-2-git-send-email-tim.henigan@gmail.com>

On Fri, Mar 16, 2012 at 6:57 PM, Tim Henigan <tim.henigan@gmail.com> wrote:
> Replace custom option/argument parser with standard Getopt::Long
> module.  This shortens the code and makes it easier to understand.

I've also wanted to do the same in the past.  The one thing holding me
back was this note from the perldocs:

"If pass_through is also enabled, options processing will terminate at
the first unrecognized option, or non-option, whichever comes first."

http://search.cpan.org/~jv/Getopt-Long-2.38/lib/Getopt/Long.pm

That leads me to believe that using Getopt::Long would break this use case:

    $ git difftool --cached --tool xxdiff ...

According to the docs, it will stop at --cached and leave it (and the
rest) in @ARGV.  When git-diff runs it will see the --tool argument
and bail out.

Is this indeed the case?  I am a little ashamed that the difftool
tests do not cover this area.  That would be a valuable first step
towards exploring this approach, IMO.


BTW, I hate @ARGV parsing loops just as much as anyone!  I was not
ignorant of Getopt::Long, and no, I was not re-inventing the wheel for
no reason.  The reason it was done that way was so that we can forward
everything we don't know about to git-diff.

I haven't tried this patch, but my reading of the documentation leads
me to believe that this is a regression.



> Signed-off-by: Tim Henigan <tim.henigan@gmail.com>
> ---
>  git-difftool.perl |  109 +++++++++++++++++++++--------------------------------
>  1 file changed, 44 insertions(+), 65 deletions(-)
>
> diff --git a/git-difftool.perl b/git-difftool.perl
> index 09b65f1..e365727 100755
> --- a/git-difftool.perl
> +++ b/git-difftool.perl
> @@ -15,11 +15,8 @@ use strict;
>  use warnings;
>  use Cwd qw(abs_path);
>  use File::Basename qw(dirname);
> -
> -require Git;
> -
> -my $DIR = abs_path(dirname($0));
> -
> +use Getopt::Long qw(:config pass_through);
> +use Git;
>
>  sub usage
>  {
> @@ -33,6 +30,7 @@ USAGE
>
>  sub setup_environment
>  {
> +       my $DIR = abs_path(dirname($0));
>        $ENV{PATH} = "$DIR:$ENV{PATH}";
>        $ENV{GIT_PAGER} = '';
>        $ENV{GIT_EXTERNAL_DIFF} = 'git-difftool--helper';
> @@ -47,75 +45,56 @@ sub exe
>        return $exe;
>  }
>
> -sub generate_command
> -{
> -       my @command = (exe('git'), 'diff');
> -       my $skip_next = 0;
> -       my $idx = -1;
> -       my $prompt = '';
> -       for my $arg (@ARGV) {
> -               $idx++;
> -               if ($skip_next) {
> -                       $skip_next = 0;
> -                       next;
> -               }
> -               if ($arg eq '-t' || $arg eq '--tool') {
> -                       usage() if $#ARGV <= $idx;
> -                       $ENV{GIT_DIFF_TOOL} = $ARGV[$idx + 1];
> -                       $skip_next = 1;
> -                       next;
> -               }
> -               if ($arg =~ /^--tool=/) {
> -                       $ENV{GIT_DIFF_TOOL} = substr($arg, 7);
> -                       next;
> -               }
> -               if ($arg eq '-x' || $arg eq '--extcmd') {
> -                       usage() if $#ARGV <= $idx;
> -                       $ENV{GIT_DIFFTOOL_EXTCMD} = $ARGV[$idx + 1];
> -                       $skip_next = 1;
> -                       next;
> -               }
> -               if ($arg =~ /^--extcmd=/) {
> -                       $ENV{GIT_DIFFTOOL_EXTCMD} = substr($arg, 9);
> -                       next;
> -               }
> -               if ($arg eq '-g' || $arg eq '--gui') {
> -                       eval {
> -                               my $tool = Git::command_oneline('config',
> -                                                               'diff.guitool');
> -                               if (length($tool)) {
> -                                       $ENV{GIT_DIFF_TOOL} = $tool;
> -                               }
> -                       };
> -                       next;
> -               }
> -               if ($arg eq '-y' || $arg eq '--no-prompt') {
> -                       $prompt = 'no';
> -                       next;
> -               }
> -               if ($arg eq '--prompt') {
> -                       $prompt = 'yes';
> -                       next;
> -               }
> -               if ($arg eq '-h') {
> -                       usage();
> -               }
> -               push @command, $arg;
> +# parse command-line options. all unrecognized options and arguments
> +# are passed through to the 'git diff' command.
> +my ($difftool_cmd, $extcmd, $gui, $help, $no_prompt, $prompt);
> +GetOptions('g|gui' => \$gui,
> +       'h' => \$help,
> +       'prompt' => \$prompt,
> +       't|tool:s' => \$difftool_cmd,
> +       'x|extcmd:s' => \$extcmd,
> +       'y|no-prompt' => \$no_prompt);
> +
> +if (defined($help)) {
> +       usage();
> +}
> +if (defined($difftool_cmd)) {
> +       if (length($difftool_cmd) > 0) {
> +               $ENV{GIT_DIFF_TOOL} = $difftool_cmd;
> +       } else {
> +               print "No <tool> given for --tool=<tool>\n";
> +               usage();
>        }
> -       if ($prompt eq 'yes') {
> -               $ENV{GIT_DIFFTOOL_PROMPT} = 'true';
> -       } elsif ($prompt eq 'no') {
> -               $ENV{GIT_DIFFTOOL_NO_PROMPT} = 'true';
> +}
> +if (defined($extcmd)) {
> +       if (length($extcmd) > 0) {
> +               $ENV{GIT_DIFFTOOL_EXTCMD} = $extcmd;
> +       } else {
> +               print "No <cmd> given for --extcmd=<cmd>\n";
> +               usage();
> +       }
> +}
> +if (defined($gui)) {
> +       my $guitool = "";
> +       $guitool = Git::config('diff.guitool');
> +       if (length($guitool) > 0) {
> +               $ENV{GIT_DIFF_TOOL} = $guitool;
>        }
> -       return @command
> +}
> +if (defined($prompt)) {
> +       $ENV{GIT_DIFFTOOL_PROMPT} = 'true';
> +}
> +elsif (defined($no_prompt)) {
> +       $ENV{GIT_DIFFTOOL_NO_PROMPT} = 'true';
>  }
>
>  setup_environment();
> +my @command = (exe('git'), 'diff', @ARGV);
>
>  # ActiveState Perl for Win32 does not implement POSIX semantics of
>  # exec* system call. It just spawns the given executable and finishes
>  # the starting program, exiting with code 0.
>  # system will at least catch the errors returned by git diff,
>  # allowing the caller of git difftool better handling of failures.
> -my $rc = system(generate_command());
> +my $rc = system(@command);
>  exit($rc | ($rc >> 8));
> --
> 1.7.9.1.290.gbd444
>



-- 
David

  reply	other threads:[~2012-03-17  3:22 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-17  1:57 [PATCH 0/9] difftool: teach command to perform directory diffs Tim Henigan
2012-03-17  1:57 ` [PATCH 1/9] difftool: parse options using Getopt::Long Tim Henigan
2012-03-17  3:21   ` David Aguilar [this message]
2012-03-17 13:54     ` Tim Henigan
2012-03-18  3:29       ` David Aguilar
2012-03-17  1:57 ` [PATCH 2/9] difftool: exit(0) when usage is printed Tim Henigan
2012-03-17  1:57 ` [PATCH 3/9] difftool: remove explicit change of PATH Tim Henigan
2012-03-17  1:57 ` [PATCH 4/9] difftool: stop appending '.exe' to git Tim Henigan
2012-03-17  2:06 ` [PATCH 0/9] difftool: teach command to perform directory diffs Junio C Hamano
2012-03-17  2:26   ` Tim Henigan
2012-03-17  4:24     ` Junio C Hamano
2012-03-18  1:55 ` [PATCH 0/9 v2] " Tim Henigan
2012-03-18  1:55   ` [PATCH 1/9 v2] difftool: parse options using Getopt::Long Tim Henigan
2012-03-18  1:55   ` [PATCH 2/9 v2] difftool: exit(0) when usage is printed Tim Henigan
2012-03-18  1:55   ` [PATCH 3/9 v2] difftool: remove explicit change of PATH Tim Henigan
2012-03-18  1:55   ` [PATCH 4/9 v2] difftool: stop appending '.exe' to git Tim Henigan
2012-03-18  1:55   ` [PATCH 5/9 v2] difftool: eliminate setup_environment function Tim Henigan
2012-03-18  1:55   ` [PATCH 6/9 v2] difftool: replace system call with Git::command_noisy Tim Henigan
2012-03-18  1:55   ` [PATCH 7/9 v2] difftool: teach difftool to handle directory diffs Tim Henigan
2012-03-18  1:55   ` [PATCH 8/9 v2] difftool: teach dir-diff to copy modified files back to working tree Tim Henigan
2012-03-18  1:55   ` [PATCH 9/9 v2] difftool: print list of valid tools with '--tool-help' Tim Henigan
2012-03-19 21:00   ` [PATCH 0/9 v2] difftool: teach command to perform directory diffs Junio C Hamano
2012-03-20  2:52     ` David Aguilar
2012-03-20  5:52       ` Junio C Hamano
2012-03-20 13:07     ` Tim Henigan
2012-03-20 16:36       ` Junio C Hamano

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

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

  git send-email \
    --in-reply-to='CAJDDKr7BTz-2THw1JaJEDcK1G4Uxwc88=gFsHCSONHAtqtypRw@mail.gmail.com' \
    --to=davvid@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=tim.henigan@gmail.com \
    /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.
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 NNTP newsgroup(s).