Skip to content

Commit

Permalink
difftool --dir-diff: symlink all files matching the working tree
Browse files Browse the repository at this point in the history
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 <john@keeping.me.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
John Keeping authored and Junio C Hamano committed Mar 14, 2013
1 parent e0976dc commit 02c5631
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 4 deletions.
4 changes: 3 additions & 1 deletion Documentation/git-difftool.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ with custom merge tool commands and has the same value as `$MERGED`.
--symlinks::
--no-symlinks::
'git difftool''s default behavior is create symlinks to the
working tree when run in `--dir-diff` mode.
working tree when run in `--dir-diff` mode and the right-hand
side of the comparison yields the same content as the file in
the working tree.
+
Specifying `--no-symlinks` instructs 'git difftool' to create copies
instead. `--no-symlinks` is the default on Windows.
Expand Down
21 changes: 18 additions & 3 deletions git-difftool.perl
Original file line number Diff line number Diff line change
Expand Up @@ -83,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) = @_;
Expand Down Expand Up @@ -159,10 +174,10 @@ sub setup_dir_diff
}

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";
}
}
}
Expand Down
22 changes: 22 additions & 0 deletions t/t7800-difftool.sh
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,28 @@ test_expect_success PERL 'difftool --dir-diff' '
echo "$diff" | stdin_contains file
'

write_script .git/CHECK_SYMLINKS <<\EOF
for f in file file2 sub/sub
do
echo "$f"
readlink "$2/$f"
done >actual
EOF

test_expect_success PERL,SYMLINKS 'difftool --dir-diff --symlink without unstaged changes' '
cat >expect <<-EOF &&
file
$(pwd)/file
file2
$(pwd)/file2
sub/sub
$(pwd)/sub/sub
EOF
git difftool --dir-diff --symlink \
--extcmd "./.git/CHECK_SYMLINKS" branch HEAD &&
test_cmp actual expect
'

test_expect_success PERL 'difftool --dir-diff ignores --prompt' '
diff=$(git difftool --dir-diff --prompt --extcmd ls branch) &&
echo "$diff" | stdin_contains sub &&
Expand Down

0 comments on commit 02c5631

Please sign in to comment.