http: avoid disconnecting on 404s for loose objects
[gitweb.git] / git-difftool.perl
index 18ca61e8d0493bde9c21ed337043bc72fa5c73a7..ebd13baa6e06cf7007fdd5c48713f06cf511721d 100755 (executable)
@@ -47,13 +47,9 @@ sub find_worktree
 
 sub print_tool_help
 {
-       my $cmd = 'TOOL_MODE=diff';
-       $cmd .= ' && . "$(git --exec-path)/git-mergetool--lib"';
-       $cmd .= ' && show_tool_help';
-
        # 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);
+       my $rc = system(qw(git mergetool --tool-help=diff));
        exit($rc | ($rc >> 8));
 }
 
@@ -74,9 +70,7 @@ sub use_wt_file
        my ($repo, $workdir, $file, $sha1) = @_;
        my $null_sha1 = '0' x 40;
 
-       if (! -e "$workdir/$file") {
-               # If the file doesn't exist in the working tree, we cannot
-               # use it.
+       if (-l "$workdir/$file" || ! -e _) {
                return (0, $null_sha1);
        }
 
@@ -144,6 +138,7 @@ sub setup_dir_diff
        my %submodule;
        my %symlink;
        my @working_tree = ();
+       my %working_tree_dups = ();
        my @rawdiff = split('\0', $diffrtn);
 
        my $i = 0;
@@ -194,6 +189,10 @@ sub setup_dir_diff
                }
 
                if ($rmode ne $null_mode) {
+                       # Avoid duplicate working_tree entries
+                       if ($working_tree_dups{$dst_path}++) {
+                               next;
+                       }
                        my ($use, $wt_sha1) = use_wt_file($repo, $workdir,
                                                          $dst_path, $rsha1);
                        if ($use) {
@@ -279,7 +278,7 @@ sub setup_dir_diff
        # temporary file to both the left and right directories to show the
        # change in the recorded SHA1 for the submodule.
        for my $path (keys %submodule) {
-               my $ok;
+               my $ok = 0;
                if (defined($submodule{$path}{left})) {
                        $ok = write_to_file("$ldir/$path",
                                "Subproject commit $submodule{$path}{left}");
@@ -295,7 +294,7 @@ sub setup_dir_diff
        # shows only the link itself, not the contents of the link target.
        # This loop replicates that behavior.
        for my $path (keys %symlink) {
-               my $ok;
+               my $ok = 0;
                if (defined($symlink{$path}{left})) {
                        $ok = write_to_file("$ldir/$path",
                                        $symlink{$path}{left});
@@ -346,6 +345,7 @@ sub main
                symlinks => $^O ne 'cygwin' &&
                                $^O ne 'MSWin32' && $^O ne 'msys',
                tool_help => undef,
+               trust_exit_code => undef,
        );
        GetOptions('g|gui!' => \$opts{gui},
                'd|dir-diff' => \$opts{dirdiff},
@@ -356,6 +356,8 @@ sub main
                'no-symlinks' => sub { $opts{symlinks} = 0; },
                't|tool:s' => \$opts{difftool_cmd},
                'tool-help' => \$opts{tool_help},
+               'trust-exit-code' => \$opts{trust_exit_code},
+               'no-trust-exit-code' => sub { $opts{trust_exit_code} = 0; },
                'x|extcmd:s' => \$opts{extcmd});
 
        if (defined($opts{help})) {
@@ -387,6 +389,15 @@ sub main
                }
        }
 
+       if (!defined $opts{trust_exit_code}) {
+               $opts{trust_exit_code} = Git::config_bool('difftool.trustExitCode');
+       }
+       if ($opts{trust_exit_code}) {
+               $ENV{GIT_DIFFTOOL_TRUST_EXIT_CODE} = 'true';
+       } else {
+               $ENV{GIT_DIFFTOOL_TRUST_EXIT_CODE} = 'false';
+       }
+
        # In directory diff mode, 'git-difftool--helper' is called once
        # to compare the a/b directories.  In file diff mode, 'git diff'
        # will invoke a separate instance of 'git-difftool--helper' for