93e84e8d3da8a88d6517a5174e650cf102343542
   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        print << 'USAGE';
  24usage: git difftool [-t|--tool=<tool>]
  25                    [-x|--extcmd=<cmd>]
  26                    [-g|--gui] [--no-gui]
  27                    [--prompt] [-y|--no-prompt]
  28                    ['git diff' options]
  29USAGE
  30        exit 1;
  31}
  32
  33sub setup_environment
  34{
  35        my $DIR = abs_path(dirname($0));
  36        $ENV{PATH} = "$DIR:$ENV{PATH}";
  37        $ENV{GIT_PAGER} = '';
  38        $ENV{GIT_EXTERNAL_DIFF} = 'git-difftool--helper';
  39}
  40
  41sub exe
  42{
  43        my $exe = shift;
  44        if ($^O eq 'MSWin32' || $^O eq 'msys') {
  45                return "$exe.exe";
  46        }
  47        return $exe;
  48}
  49
  50# parse command-line options. all unrecognized options and arguments
  51# are passed through to the 'git diff' command.
  52my ($difftool_cmd, $extcmd, $gui, $help, $prompt);
  53GetOptions('g|gui!' => \$gui,
  54        'h' => \$help,
  55        'prompt!' => \$prompt,
  56        'y' => sub { $prompt = 0; },
  57        't|tool:s' => \$difftool_cmd,
  58        'x|extcmd:s' => \$extcmd);
  59
  60if (defined($help)) {
  61        usage();
  62}
  63if (defined($difftool_cmd)) {
  64        if (length($difftool_cmd) > 0) {
  65                $ENV{GIT_DIFF_TOOL} = $difftool_cmd;
  66        } else {
  67                print "No <tool> given for --tool=<tool>\n";
  68                usage();
  69        }
  70}
  71if (defined($extcmd)) {
  72        if (length($extcmd) > 0) {
  73                $ENV{GIT_DIFFTOOL_EXTCMD} = $extcmd;
  74        } else {
  75                print "No <cmd> given for --extcmd=<cmd>\n";
  76                usage();
  77        }
  78}
  79if ($gui) {
  80        my $guitool = "";
  81        $guitool = Git::config('diff.guitool');
  82        if (length($guitool) > 0) {
  83                $ENV{GIT_DIFF_TOOL} = $guitool;
  84        }
  85}
  86if (defined($prompt)) {
  87        if ($prompt) {
  88                $ENV{GIT_DIFFTOOL_PROMPT} = 'true';
  89        } else {
  90                $ENV{GIT_DIFFTOOL_NO_PROMPT} = 'true';
  91        }
  92}
  93
  94setup_environment();
  95my @command = (exe('git'), 'diff', @ARGV);
  96
  97# ActiveState Perl for Win32 does not implement POSIX semantics of
  98# exec* system call. It just spawns the given executable and finishes
  99# the starting program, exiting with code 0.
 100# system will at least catch the errors returned by git diff,
 101# allowing the caller of git difftool better handling of failures.
 102my $rc = system(@command);
 103exit($rc | ($rc >> 8));