4555cd8b1c5b8cda4527b328b858a015ac75d357
   1#!/usr/bin/env perl
   2# Copyright (c) 2009, 2010 David Aguilar
   3#
   4# This is a wrapper around the GIT_EXTERNAL_DIFF-compatible
   5# git-difftool--helper script.
   6#
   7# This script exports GIT_EXTERNAL_DIFF and GIT_PAGER for use by git.
   8# GIT_DIFFTOOL_NO_PROMPT, GIT_DIFFTOOL_PROMPT, and GIT_DIFF_TOOL
   9# are exported for use by git-difftool--helper.
  10#
  11# Any arguments that are unknown to this script are forwarded to 'git diff'.
  12
  13use 5.008;
  14use strict;
  15use warnings;
  16use Cwd qw(abs_path);
  17use File::Basename qw(dirname);
  18use Getopt::Long qw(:config pass_through);
  19use Git;
  20
  21sub usage
  22{
  23        my $exitcode = shift;
  24        print << 'USAGE';
  25usage: git difftool [-t|--tool=<tool>]
  26                    [-x|--extcmd=<cmd>]
  27                    [-g|--gui] [--no-gui]
  28                    [--prompt] [-y|--no-prompt]
  29                    ['git diff' options]
  30USAGE
  31        exit($exitcode);
  32}
  33
  34sub setup_environment
  35{
  36        my $DIR = abs_path(dirname($0));
  37        $ENV{PATH} = "$DIR:$ENV{PATH}";
  38        $ENV{GIT_PAGER} = '';
  39        $ENV{GIT_EXTERNAL_DIFF} = 'git-difftool--helper';
  40}
  41
  42sub exe
  43{
  44        my $exe = shift;
  45        if ($^O eq 'MSWin32' || $^O eq 'msys') {
  46                return "$exe.exe";
  47        }
  48        return $exe;
  49}
  50
  51# parse command-line options. all unrecognized options and arguments
  52# are passed through to the 'git diff' command.
  53my ($difftool_cmd, $extcmd, $gui, $help, $prompt);
  54GetOptions('g|gui!' => \$gui,
  55        'h' => \$help,
  56        'prompt!' => \$prompt,
  57        'y' => sub { $prompt = 0; },
  58        't|tool:s' => \$difftool_cmd,
  59        'x|extcmd:s' => \$extcmd);
  60
  61if (defined($help)) {
  62        usage(0);
  63}
  64if (defined($difftool_cmd)) {
  65        if (length($difftool_cmd) > 0) {
  66                $ENV{GIT_DIFF_TOOL} = $difftool_cmd;
  67        } else {
  68                print "No <tool> given for --tool=<tool>\n";
  69                usage(1);
  70        }
  71}
  72if (defined($extcmd)) {
  73        if (length($extcmd) > 0) {
  74                $ENV{GIT_DIFFTOOL_EXTCMD} = $extcmd;
  75        } else {
  76                print "No <cmd> given for --extcmd=<cmd>\n";
  77                usage(1);
  78        }
  79}
  80if ($gui) {
  81        my $guitool = "";
  82        $guitool = Git::config('diff.guitool');
  83        if (length($guitool) > 0) {
  84                $ENV{GIT_DIFF_TOOL} = $guitool;
  85        }
  86}
  87if (defined($prompt)) {
  88        if ($prompt) {
  89                $ENV{GIT_DIFFTOOL_PROMPT} = 'true';
  90        } else {
  91                $ENV{GIT_DIFFTOOL_NO_PROMPT} = 'true';
  92        }
  93}
  94
  95setup_environment();
  96my @command = (exe('git'), 'diff', @ARGV);
  97
  98# ActiveState Perl for Win32 does not implement POSIX semantics of
  99# exec* system call. It just spawns the given executable and finishes
 100# the starting program, exiting with code 0.
 101# system will at least catch the errors returned by git diff,
 102# allowing the caller of git difftool better handling of failures.
 103my $rc = system(@command);
 104exit($rc | ($rc >> 8));