difftool: print list of valid tools with '--tool-help'
Since bc7a96a (mergetool--lib: Refactor tools into separate files, 2011-08-18), it is possible to add a new diff tool by creating a simple script in the '$(git --exec-path)/mergetools' directory. Updating the difftool help text is still a manual process, and the documentation can easily go out of sync. This commit teaches difftool the '--tool-help' option, which: - Reads the list of valid tools from 'mergetools/*' - Determines which of them are actually installed - Determines which are capable of diffing (i.e. not just a merge tool) - Prints the resulting list for the user Signed-off-by: Tim Henigan <tim.henigan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Tim Henigan committed
Mar 29, 2012 at 09:39 UTC
bf73fc212a159210398b6d46ed5e9101c650e7db
3 files changed
+64
-7
Documentation/git-difftool.txt
+6
-5
@@ -36,11 +36,9 @@ OPTIONS
36
37
-t <tool>::
38
--tool=<tool>::
39
- Use the diff tool specified by <tool>.
40
- Valid diff tools are:
41
- araxis, bc3, deltawalker, diffuse, emerge, ecmerge, gvimdiff,
42
- kdiff3, kompare, meld, opendiff, p4merge, tkdiff, vimdiff and
43
- xxdiff.
39
+ Use the diff tool specified by <tool>. Valid values include
40
+ emerge, kompare, meld, and vimdiff. Run `git difftool --tool-help`
41
+ for the list of valid <tool> settings.
42
+
43
If a diff tool is not specified, 'git difftool'
44
will use the configuration variable `diff.tool`. If the
@@ -68,6 +66,9 @@ of the diff post-image. `$MERGED` is the name of the file which is
66
being compared. `$BASE` is provided for compatibility
67
with custom merge tool commands and has the same value as `$MERGED`.
68
69
+--tool-help::
70
+ Print a list of diff tools that may be used with `--tool`.
71
+
72
-x <command>::
73
--extcmd=<command>::
74
Specify a custom command for viewing diffs.
git-difftool.perl
+53
-2
@@ -15,12 +15,14 @@ use strict;
15
use warnings;
16
use File::Basename qw(dirname);
17
use File::Copy;
18
+use File::Find;
19
use File::stat;
20
use File::Path qw(mkpath);
21
use File::Temp qw(tempdir);
22
use Getopt::Long qw(:config pass_through);
23
use Git;
24
25
+my @tools;
26
my @working_tree;
27
my $rc;
28
my $repo = Git->repository();
@@ -30,7 +32,7 @@ sub usage
32
{
33
my $exitcode = shift;
34
print << 'USAGE';
33
-usage: git difftool [-t|--tool=<tool>]
35
+usage: git difftool [-t|--tool=<tool>] [--tool-help]
36
[-x|--extcmd=<cmd>]
37
[-g|--gui] [--no-gui]
38
[--prompt] [-y|--no-prompt]
@@ -62,6 +64,51 @@ sub find_worktree
64
65
my $workdir = find_worktree();
66
67
+sub filter_tool_scripts
68
+{
69
+ if (-d $_) {
70
+ if ($_ ne ".") {
71
+ # Ignore files in subdirectories
72
+ $File::Find::prune = 1;
73
+ }
74
+ } else {
75
+ if ((-f $_) && ($_ ne "defaults")) {
76
+ push(@tools, $_);
77
+ }
78
+ }
79
+}
80
+
81
+sub print_tool_help
82
+{
83
+ my ($cmd, @found, @notfound);
84
+ my $gitpath = Git::exec_path();
85
+
86
+ find(\&filter_tool_scripts, "$gitpath/mergetools");
87
+
88
+ foreach my $tool (@tools) {
89
+ $cmd = "TOOL_MODE=diff";
90
+ $cmd .= ' && . "$(git --exec-path)/git-mergetool--lib"';
91
+ $cmd .= " && get_merge_tool_path $tool >/dev/null 2>&1";
92
+ $cmd .= " && can_diff >/dev/null 2>&1";
93
+ if (system('sh', '-c', $cmd) == 0) {
94
+ push(@found, $tool);
95
+ } else {
96
+ push(@notfound, $tool);
97
+ }
98
+ }
99
+
100
+ print "'git difftool --tool=<tool>' may be set to one of the following:\n";
101
+ print "\t$_\n" for (sort(@found));
102
+
103
+ print "\nThe following tools are valid, but not currently available:\n";
104
+ print "\t$_\n" for (sort(@notfound));
105
+
106
+ print "\nNOTE: Some of the tools listed above only work in a windowed\n";
107
+ print "environment. If run in a terminal-only session, they will fail.\n";
108
+
109
+ exit(0);
110
+}
111
+
112
sub setup_dir_diff
113
{
114
# Run the diff; exit immediately if no diff found
@@ -230,18 +277,22 @@ sub write_to_file
277
278
# parse command-line options. all unrecognized options and arguments
279
# are passed through to the 'git diff' command.
233
-my ($difftool_cmd, $dirdiff, $extcmd, $gui, $help, $prompt);
280
+my ($difftool_cmd, $dirdiff, $extcmd, $gui, $help, $prompt, $tool_help);
281
GetOptions('g|gui!' => \$gui,
282
'd|dir-diff' => \$dirdiff,
283
'h' => \$help,
284
'prompt!' => \$prompt,
285
'y' => sub { $prompt = 0; },
286
't|tool:s' => \$difftool_cmd,
287
+ 'tool-help' => \$tool_help,
288
'x|extcmd:s' => \$extcmd);
289
290
if (defined($help)) {
291
usage(0);
292
}
293
+if (defined($tool_help)) {
294
+ print_tool_help();
295
+}
296
if (defined($difftool_cmd)) {
297
if (length($difftool_cmd) > 0) {
298
$ENV{GIT_DIFF_TOOL} = $difftool_cmd;
t/t7800-difftool.sh
+5
@@ -319,6 +319,11 @@ test_expect_success PERL 'say no to the second file' '
319
echo "$diff" | stdin_doesnot_contain br2
320
'
321
322
+test_expect_success PERL 'difftool --tool-help' '
323
+ tool_help=$(git difftool --tool-help) &&
324
+ echo "$tool_help" | stdin_contains tool
325
+'
326
+
327
test_expect_success PERL 'setup change in subdirectory' '
328
git checkout master &&
329
mkdir sub &&