diff options
Diffstat (limited to 'git-difftool.perl')
| -rwxr-xr-x | git-difftool.perl | 82 |
1 files changed, 29 insertions, 53 deletions
diff --git a/git-difftool.perl b/git-difftool.perl index edd0493a08..663640d33c 100755 --- a/git-difftool.perl +++ b/git-difftool.perl @@ -59,57 +59,16 @@ sub find_worktree return $worktree; } -sub filter_tool_scripts -{ - my ($tools) = @_; - 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, @tools); - my $gitpath = Git::exec_path(); - - find(sub { filter_tool_scripts(\@tools) }, "$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 << 'EOF'; -'git difftool --tool=<tool>' may be set to one of the following: -EOF - print "\t$_\n" for (sort(@found)); - - print << 'EOF'; - -The following tools are valid, but not currently available: -EOF - print "\t$_\n" for (sort(@notfound)); + my $cmd = 'TOOL_MODE=diff'; + $cmd .= ' && . "$(git --exec-path)/git-mergetool--lib"'; + $cmd .= ' && show_tool_help'; - print << 'EOF'; - -NOTE: Some of the tools listed above only work in a windowed -environment. If run in a terminal-only session, they will fail. -EOF - exit(0); + # See the comment at the bottom of file_diff() for the reason behind + # using system() followed by exit() instead of exec(). + my $rc = system('sh', '-c', $cmd); + exit($rc | ($rc >> 8)); } sub exit_cleanup @@ -124,6 +83,21 @@ sub exit_cleanup exit($status | ($status >> 8)); } +sub use_wt_file +{ + my ($repo, $workdir, $file, $sha1, $symlinks) = @_; + my $null_sha1 = '0' x 40; + + if ($sha1 eq $null_sha1) { + return 1; + } elsif (not $symlinks) { + return 0; + } + + my $wt_sha1 = $repo->command_oneline('hash-object', "$workdir/$file"); + return $sha1 eq $wt_sha1; +} + sub setup_dir_diff { my ($repo, $workdir, $symlinks) = @_; @@ -200,10 +174,10 @@ EOF } if ($rmode ne $null_mode) { - if ($rsha1 ne $null_sha1) { - $rindex .= "$rmode $rsha1\t$dst_path\0"; - } else { + if (use_wt_file($repo, $workdir, $dst_path, $rsha1, $symlinks)) { push(@working_tree, $dst_path); + } else { + $rindex .= "$rmode $rsha1\t$dst_path\0"; } } } @@ -250,7 +224,9 @@ EOF delete($ENV{GIT_INDEX_FILE}); # Changes in the working tree need special treatment since they are - # not part of the index + # not part of the index. Remove any trailing slash from $workdir + # before starting to avoid double slashes in symlink targets. + $workdir =~ s|/$||; for my $file (@working_tree) { my $dir = dirname($file); unless (-d "$rdir/$dir") { @@ -377,7 +353,7 @@ sub main } if ($opts{gui}) { my $guitool = Git::config('diff.guitool'); - if (length($guitool) > 0) { + if (defined($guitool) && length($guitool) > 0) { $ENV{GIT_DIFF_TOOL} = $guitool; } } |
