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>
			
			
				maint
			
			
		
							parent
							
								
									7e0abcec10
								
							
						
					
					
						commit
						bf73fc212a
					
				|  | @ -36,11 +36,9 @@ OPTIONS | ||||||
|  |  | ||||||
| -t <tool>:: | -t <tool>:: | ||||||
| --tool=<tool>:: | --tool=<tool>:: | ||||||
| 	Use the diff tool specified by <tool>. | 	Use the diff tool specified by <tool>.  Valid values include | ||||||
| 	Valid diff tools are: | 	emerge, kompare, meld, and vimdiff. Run `git difftool --tool-help` | ||||||
| 	araxis, bc3, deltawalker, diffuse, emerge, ecmerge, gvimdiff, | 	for the list of valid <tool> settings. | ||||||
| 	kdiff3,	kompare, meld, opendiff, p4merge, tkdiff, vimdiff and |  | ||||||
| 	xxdiff. |  | ||||||
| + | + | ||||||
| If a diff tool is not specified, 'git difftool' | If a diff tool is not specified, 'git difftool' | ||||||
| will use the configuration variable `diff.tool`.  If the | 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 | ||||||
| being compared. `$BASE` is provided for compatibility | being compared. `$BASE` is provided for compatibility | ||||||
| with custom merge tool commands and has the same value as `$MERGED`. | with custom merge tool commands and has the same value as `$MERGED`. | ||||||
|  |  | ||||||
|  | --tool-help:: | ||||||
|  | 	Print a list of diff tools that may be used with `--tool`. | ||||||
|  |  | ||||||
| -x <command>:: | -x <command>:: | ||||||
| --extcmd=<command>:: | --extcmd=<command>:: | ||||||
| 	Specify a custom command for viewing diffs. | 	Specify a custom command for viewing diffs. | ||||||
|  |  | ||||||
|  | @ -15,12 +15,14 @@ use strict; | ||||||
| use warnings; | use warnings; | ||||||
| use File::Basename qw(dirname); | use File::Basename qw(dirname); | ||||||
| use File::Copy; | use File::Copy; | ||||||
|  | use File::Find; | ||||||
| use File::stat; | use File::stat; | ||||||
| use File::Path qw(mkpath); | use File::Path qw(mkpath); | ||||||
| use File::Temp qw(tempdir); | use File::Temp qw(tempdir); | ||||||
| use Getopt::Long qw(:config pass_through); | use Getopt::Long qw(:config pass_through); | ||||||
| use Git; | use Git; | ||||||
|  |  | ||||||
|  | my @tools; | ||||||
| my @working_tree; | my @working_tree; | ||||||
| my $rc; | my $rc; | ||||||
| my $repo = Git->repository(); | my $repo = Git->repository(); | ||||||
|  | @ -30,7 +32,7 @@ sub usage | ||||||
| { | { | ||||||
| 	my $exitcode = shift; | 	my $exitcode = shift; | ||||||
| 	print << 'USAGE'; | 	print << 'USAGE'; | ||||||
| usage: git difftool [-t|--tool=<tool>] | usage: git difftool [-t|--tool=<tool>] [--tool-help] | ||||||
|                     [-x|--extcmd=<cmd>] |                     [-x|--extcmd=<cmd>] | ||||||
|                     [-g|--gui] [--no-gui] |                     [-g|--gui] [--no-gui] | ||||||
|                     [--prompt] [-y|--no-prompt] |                     [--prompt] [-y|--no-prompt] | ||||||
|  | @ -62,6 +64,51 @@ sub find_worktree | ||||||
|  |  | ||||||
| my $workdir = find_worktree(); | my $workdir = find_worktree(); | ||||||
|  |  | ||||||
|  | sub filter_tool_scripts | ||||||
|  | { | ||||||
|  | 	if (-d $_) { | ||||||
|  | 		if ($_ ne ".") { | ||||||
|  | 			# Ignore files in subdirectories | ||||||
|  | 			$File::Find::prune = 1; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		if ((-f $_) && ($_ ne "defaults")) { | ||||||
|  | 			push(@tools, $_); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | sub print_tool_help | ||||||
|  | { | ||||||
|  | 	my ($cmd, @found, @notfound); | ||||||
|  | 	my $gitpath = Git::exec_path(); | ||||||
|  |  | ||||||
|  | 	find(\&filter_tool_scripts, "$gitpath/mergetools"); | ||||||
|  |  | ||||||
|  | 	foreach my $tool (@tools) { | ||||||
|  | 		$cmd  = "TOOL_MODE=diff"; | ||||||
|  | 		$cmd .= ' && . "$(git --exec-path)/git-mergetool--lib"'; | ||||||
|  | 		$cmd .= " && get_merge_tool_path $tool >/dev/null 2>&1"; | ||||||
|  | 		$cmd .= " && can_diff >/dev/null 2>&1"; | ||||||
|  | 		if (system('sh', '-c', $cmd) == 0) { | ||||||
|  | 			push(@found, $tool); | ||||||
|  | 		} else { | ||||||
|  | 			push(@notfound, $tool); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	print "'git difftool --tool=<tool>' may be set to one of the following:\n"; | ||||||
|  | 	print "\t$_\n" for (sort(@found)); | ||||||
|  |  | ||||||
|  | 	print "\nThe following tools are valid, but not currently available:\n"; | ||||||
|  | 	print "\t$_\n" for (sort(@notfound)); | ||||||
|  |  | ||||||
|  | 	print "\nNOTE: Some of the tools listed above only work in a windowed\n"; | ||||||
|  | 	print "environment. If run in a terminal-only session, they will fail.\n"; | ||||||
|  |  | ||||||
|  | 	exit(0); | ||||||
|  | } | ||||||
|  |  | ||||||
| sub setup_dir_diff | sub setup_dir_diff | ||||||
| { | { | ||||||
| 	# Run the diff; exit immediately if no diff found | 	# Run the diff; exit immediately if no diff found | ||||||
|  | @ -230,18 +277,22 @@ sub write_to_file | ||||||
|  |  | ||||||
| # parse command-line options. all unrecognized options and arguments | # parse command-line options. all unrecognized options and arguments | ||||||
| # are passed through to the 'git diff' command. | # are passed through to the 'git diff' command. | ||||||
| my ($difftool_cmd, $dirdiff, $extcmd, $gui, $help, $prompt); | my ($difftool_cmd, $dirdiff, $extcmd, $gui, $help, $prompt, $tool_help); | ||||||
| GetOptions('g|gui!' => \$gui, | GetOptions('g|gui!' => \$gui, | ||||||
| 	'd|dir-diff' => \$dirdiff, | 	'd|dir-diff' => \$dirdiff, | ||||||
| 	'h' => \$help, | 	'h' => \$help, | ||||||
| 	'prompt!' => \$prompt, | 	'prompt!' => \$prompt, | ||||||
| 	'y' => sub { $prompt = 0; }, | 	'y' => sub { $prompt = 0; }, | ||||||
| 	't|tool:s' => \$difftool_cmd, | 	't|tool:s' => \$difftool_cmd, | ||||||
|  | 	'tool-help' => \$tool_help, | ||||||
| 	'x|extcmd:s' => \$extcmd); | 	'x|extcmd:s' => \$extcmd); | ||||||
|  |  | ||||||
| if (defined($help)) { | if (defined($help)) { | ||||||
| 	usage(0); | 	usage(0); | ||||||
| } | } | ||||||
|  | if (defined($tool_help)) { | ||||||
|  | 	print_tool_help(); | ||||||
|  | } | ||||||
| if (defined($difftool_cmd)) { | if (defined($difftool_cmd)) { | ||||||
| 	if (length($difftool_cmd) > 0) { | 	if (length($difftool_cmd) > 0) { | ||||||
| 		$ENV{GIT_DIFF_TOOL} = $difftool_cmd; | 		$ENV{GIT_DIFF_TOOL} = $difftool_cmd; | ||||||
|  |  | ||||||
|  | @ -319,6 +319,11 @@ test_expect_success PERL 'say no to the second file' ' | ||||||
| 	echo "$diff" | stdin_doesnot_contain br2 | 	echo "$diff" | stdin_doesnot_contain br2 | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | test_expect_success PERL 'difftool --tool-help' ' | ||||||
|  | 	tool_help=$(git difftool --tool-help) && | ||||||
|  | 	echo "$tool_help" | stdin_contains tool | ||||||
|  | ' | ||||||
|  |  | ||||||
| test_expect_success PERL 'setup change in subdirectory' ' | test_expect_success PERL 'setup change in subdirectory' ' | ||||||
| 	git checkout master && | 	git checkout master && | ||||||
| 	mkdir sub && | 	mkdir sub && | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Tim Henigan
						Tim Henigan