{"thread":{"id":"30095","subject":"[PATCH 9/9 v9] difftool: print list of valid tools with '--tool-help'","startedAt":"2012-03-29T13:39:18Z","lastAt":"2012-03-29T13:39:18Z","messageCount":1,"participants":["Tim Henigan"],"isPatch":true,"patchVersion":9,"patchTotal":9},"messages":[{"id":"188057","messageId":"1333028358-12917-1-git-send-email-tim.henigan@gmail.com","threadId":"30095","inReplyTo":null,"subject":"[PATCH 9/9 v9] difftool: print list of valid tools with '--tool-help'","fromName":"Tim Henigan","fromEmail":"tim.henigan@gmail.com","sentAt":"2012-03-29T13:39:18Z","receivedAt":"2012-03-29T13:39:18Z","isPatch":true,"sender":{"key":"tim.henigan@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42022?v=4"},"body":"Since bc7a96a (mergetool--lib: Refactor tools into separate files,\n2011-08-18), it is possible to add a new diff tool by creating a simple\nscript in the '$(git --exec-path)/mergetools' directory.  Updating the\ndifftool help text is still a manual process, and the documentation can\neasily go out of sync.\n\nThis commit teaches difftool the '--tool-help' option, which:\n  - Reads the list of valid tools from 'mergetools/*'\n  - Determines which of them are actually installed\n  - Determines which are capable of diffing (i.e. not just a merge tool)\n  - Prints the resulting list for the user\n\nSigned-off-by: Tim Henigan <tim.henigan@gmail.com>\n---\n\nThis replaces 9/9 in the previous version of the series.\n\nChanges in v9:\n  - File::Find now ignores sub-directories of '$(git --exec-path)/mergetools'.\n  - Moved all tool script filter logic into a separate function.\n  - Filter now rejects anything other than simple files found in 'mergetools'.\n\nPlease note that the tool script files are not 'chmod +x', so we cannot test\nfor it.\n\nThese changes were suggested during review of the previous version by\nJunio Hamano on the Git developers list [1].\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/194158/focus=194181\n\n\n Documentation/git-difftool.txt |   11 ++++----\n git-difftool.perl              |   55 ++++++++++++++++++++++++++++++++++++++--\n t/t7800-difftool.sh            |    5 ++++\n 3 files changed, 64 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt\nindex aba5e76..31fc2e3 100644\n--- a/Documentation/git-difftool.txt\n+++ b/Documentation/git-difftool.txt\n@@ -36,11 +36,9 @@ OPTIONS\n \n -t <tool>::\n --tool=<tool>::\n-\tUse the diff tool specified by <tool>.\n-\tValid diff tools are:\n-\taraxis, bc3, deltawalker, diffuse, emerge, ecmerge, gvimdiff,\n-\tkdiff3,\tkompare, meld, opendiff, p4merge, tkdiff, vimdiff and\n-\txxdiff.\n+\tUse the diff tool specified by <tool>.  Valid values include\n+\temerge, kompare, meld, and vimdiff. Run `git difftool --tool-help`\n+\tfor the list of valid <tool> settings.\n +\n If a diff tool is not specified, 'git difftool'\n will use the configuration variable `diff.tool`.  If the\n@@ -68,6 +66,9 @@ of the diff post-image.  `$MERGED` is the name of the file which is\n being compared. `$BASE` is provided for compatibility\n with custom merge tool commands and has the same value as `$MERGED`.\n \n+--tool-help::\n+\tPrint a list of diff tools that may be used with `--tool`.\n+\n -x <command>::\n --extcmd=<command>::\n \tSpecify a custom command for viewing diffs.\ndiff --git a/git-difftool.perl b/git-difftool.perl\nindex 0fa131c..f83e226 100755\n--- a/git-difftool.perl\n+++ b/git-difftool.perl\n@@ -16,19 +16,21 @@ use strict;\n use warnings;\n use File::Basename qw(dirname);\n use File::Copy;\n+use File::Find;\n use File::stat;\n use File::Path qw(mkpath);\n use File::Temp qw(tempdir);\n use Getopt::Long qw(:config pass_through);\n use Git;\n \n+my @tools;\n my @working_tree;\n \n sub usage\n {\n \tmy $exitcode = shift;\n \tprint << 'USAGE';\n-usage: git difftool [-t|--tool=<tool>]\n+usage: git difftool [-t|--tool=<tool>] [--tool-help]\n                     [-x|--extcmd=<cmd>]\n                     [-g|--gui] [--no-gui]\n                     [--prompt] [-y|--no-prompt]\n@@ -38,6 +40,51 @@ USAGE\n \texit($exitcode);\n }\n \n+sub filter_tool_scripts\n+{\n+\tif (-d $_) {\n+\t\tif ($_ ne \".\") {\n+\t\t\t# Ignore files in subdirectories\n+\t\t\t$File::Find::prune = 1;\n+\t\t}\n+\t} else {\n+\t\tif ((-f $_) && ($_ ne \"defaults\")) {\n+\t\t\tpush(@tools, $_);\n+\t\t}\n+\t}\n+}\n+\n+sub print_tool_help\n+{\n+\tmy ($cmd, @found, @notfound);\n+\tmy $gitpath = Git::exec_path();\n+\n+\tfind(\\&filter_tool_scripts, \"$gitpath/mergetools\");\n+\n+\tforeach my $tool (@tools) {\n+\t\t$cmd  = \"TOOL_MODE=diff\";\n+\t\t$cmd .= ' && . \"$(git --exec-path)/git-mergetool--lib\"';\n+\t\t$cmd .= \" && get_merge_tool_path $tool >/dev/null 2>&1\";\n+\t\t$cmd .= \" && can_diff >/dev/null 2>&1\";\n+\t\tif (system('sh', '-c', $cmd) == 0) {\n+\t\t\tpush(@found, $tool);\n+\t\t} else {\n+\t\t\tpush(@notfound, $tool);\n+\t\t}\n+\t}\n+\n+\tprint \"'git difftool --tool=<tool>' may be set to one of the following:\\n\";\n+\tprint \"\\t$_\\n\" for (sort(@found));\n+\n+\tprint \"\\nThe following tools are valid, but not currently available:\\n\";\n+\tprint \"\\t$_\\n\" for (sort(@notfound));\n+\n+\tprint \"\\nNOTE: Some of the tools listed above only work in a windowed\\n\";\n+\tprint \"environment. If run in a terminal-only session, they will fail.\\n\";\n+\n+\texit(0);\n+}\n+\n sub setup_dir_diff\n {\n \t# Run the diff; exit immediately if no diff found\n@@ -132,18 +179,22 @@ sub setup_dir_diff\n \n # parse command-line options. all unrecognized options and arguments\n # are passed through to the 'git diff' command.\n-my ($difftool_cmd, $dirdiff, $extcmd, $gui, $help, $prompt);\n+my ($difftool_cmd, $dirdiff, $extcmd, $gui, $help, $prompt, $tool_help);\n GetOptions('g|gui!' => \\$gui,\n \t'd|dir-diff' => \\$dirdiff,\n \t'h' => \\$help,\n \t'prompt!' => \\$prompt,\n \t'y' => sub { $prompt = 0; },\n \t't|tool:s' => \\$difftool_cmd,\n+\t'tool-help' => \\$tool_help,\n \t'x|extcmd:s' => \\$extcmd);\n \n if (defined($help)) {\n \tusage(0);\n } \n+if (defined($tool_help)) {\n+\tprint_tool_help();\n+}\n if (defined($difftool_cmd)) {\n \tif (length($difftool_cmd) > 0) {\n \t\t$ENV{GIT_DIFF_TOOL} = $difftool_cmd;\ndiff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh\nindex 478c1be..bbe71e5 100755\n--- a/t/t7800-difftool.sh\n+++ b/t/t7800-difftool.sh\n@@ -319,6 +319,11 @@ test_expect_success PERL 'say no to the second file' '\n \techo \"$diff\" | stdin_doesnot_contain br2\n '\n \n+test_expect_success PERL 'difftool --tool-help' '\n+\ttool_help=$(git difftool --tool-help) &&\n+\techo \"$tool_help\" | stdin_contains tool\n+'\n+\n test_expect_success PERL 'setup change in subdirectory' '\n \tgit checkout master &&\n \tmkdir sub &&\n-- \n1.7.10.rc2.21.g42bdb\n"}]}