Skip to content

Commit 02c5631

Browse files
johnkeepinggitster
authored andcommitted
difftool --dir-diff: symlink all files matching the working tree
Some users like to edit files in their diff tool when using "git difftool --dir-diff --symlink" to compare against the working tree but difftool currently only created symlinks when a file contains unstaged changes. Change this behaviour so that symlinks are created whenever the right-hand side of the comparison has the same SHA1 as the file in the working tree. Note that textconv filters are handled in the same way as by git-diff and if a clean filter is not the inverse of its smudge filter we already get a null SHA1 from "diff --raw" and will symlink the file without going through the new hash-object based check. Signed-off-by: John Keeping <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e0976dc commit 02c5631

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

Documentation/git-difftool.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ with custom merge tool commands and has the same value as `$MERGED`.
7272
--symlinks::
7373
--no-symlinks::
7474
'git difftool''s default behavior is create symlinks to the
75-
working tree when run in `--dir-diff` mode.
75+
working tree when run in `--dir-diff` mode and the right-hand
76+
side of the comparison yields the same content as the file in
77+
the working tree.
7678
+
7779
Specifying `--no-symlinks` instructs 'git difftool' to create copies
7880
instead. `--no-symlinks` is the default on Windows.

git-difftool.perl

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,21 @@ sub exit_cleanup
8383
exit($status | ($status >> 8));
8484
}
8585

86+
sub use_wt_file
87+
{
88+
my ($repo, $workdir, $file, $sha1, $symlinks) = @_;
89+
my $null_sha1 = '0' x 40;
90+
91+
if ($sha1 eq $null_sha1) {
92+
return 1;
93+
} elsif (not $symlinks) {
94+
return 0;
95+
}
96+
97+
my $wt_sha1 = $repo->command_oneline('hash-object', "$workdir/$file");
98+
return $sha1 eq $wt_sha1;
99+
}
100+
86101
sub setup_dir_diff
87102
{
88103
my ($repo, $workdir, $symlinks) = @_;
@@ -159,10 +174,10 @@ sub setup_dir_diff
159174
}
160175

161176
if ($rmode ne $null_mode) {
162-
if ($rsha1 ne $null_sha1) {
163-
$rindex .= "$rmode $rsha1\t$dst_path\0";
164-
} else {
177+
if (use_wt_file($repo, $workdir, $dst_path, $rsha1, $symlinks)) {
165178
push(@working_tree, $dst_path);
179+
} else {
180+
$rindex .= "$rmode $rsha1\t$dst_path\0";
166181
}
167182
}
168183
}

t/t7800-difftool.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,28 @@ test_expect_success PERL 'difftool --dir-diff' '
370370
echo "$diff" | stdin_contains file
371371
'
372372

373+
write_script .git/CHECK_SYMLINKS <<\EOF
374+
for f in file file2 sub/sub
375+
do
376+
echo "$f"
377+
readlink "$2/$f"
378+
done >actual
379+
EOF
380+
381+
test_expect_success PERL,SYMLINKS 'difftool --dir-diff --symlink without unstaged changes' '
382+
cat >expect <<-EOF &&
383+
file
384+
$(pwd)/file
385+
file2
386+
$(pwd)/file2
387+
sub/sub
388+
$(pwd)/sub/sub
389+
EOF
390+
git difftool --dir-diff --symlink \
391+
--extcmd "./.git/CHECK_SYMLINKS" branch HEAD &&
392+
test_cmp actual expect
393+
'
394+
373395
test_expect_success PERL 'difftool --dir-diff ignores --prompt' '
374396
diff=$(git difftool --dir-diff --prompt --extcmd ls branch) &&
375397
echo "$diff" | stdin_contains sub &&

0 commit comments

Comments
 (0)