From 8aa10d4a5bb2eceb78b689f0c13b334725a1019f Mon Sep 17 00:00:00 2001 From: John Keeping Date: Thu, 14 Mar 2013 20:19:39 +0000 Subject: git-difftool(1): fix formatting of --symlink description Signed-off-by: John Keeping Signed-off-by: Junio C Hamano --- Documentation/git-difftool.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt index e0e12e9470..e575fea1ad 100644 --- a/Documentation/git-difftool.txt +++ b/Documentation/git-difftool.txt @@ -74,8 +74,8 @@ with custom merge tool commands and has the same value as `$MERGED`. 'git difftool''s default behavior is create symlinks to the working tree when run in `--dir-diff` mode. + - Specifying `--no-symlinks` instructs 'git difftool' to create - copies instead. `--no-symlinks` is the default on Windows. +Specifying `--no-symlinks` instructs 'git difftool' to create copies +instead. `--no-symlinks` is the default on Windows. -x :: --extcmd=:: -- cgit v1.2.1 From e0976dcf83884fd0b48e90f0c62f50852e6971f6 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Thu, 14 Mar 2013 20:19:40 +0000 Subject: difftool: avoid double slashes in symlink targets When we add tests for symlinks in "git difftool --dir-diff" it's easier to check the target path if we don't have to worry about double slashes separating directories. Remove the trailing slash (if present) from $workdir before creating the symlinks in order to avoid this. Signed-off-by: John Keeping Signed-off-by: Junio C Hamano --- git-difftool.perl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/git-difftool.perl b/git-difftool.perl index 0a90de4146..3cab257595 100755 --- a/git-difftool.perl +++ b/git-difftool.perl @@ -209,7 +209,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") { -- cgit v1.2.1 From 02c56314aab9474827cd7831518a970f0341e4fd Mon Sep 17 00:00:00 2001 From: John Keeping Date: Thu, 14 Mar 2013 20:19:41 +0000 Subject: 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 Signed-off-by: Junio C Hamano --- Documentation/git-difftool.txt | 4 +++- git-difftool.perl | 21 ++++++++++++++++++--- t/t7800-difftool.sh | 22 ++++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt index e575fea1ad..8361e6e4e3 100644 --- a/Documentation/git-difftool.txt +++ b/Documentation/git-difftool.txt @@ -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. diff --git a/git-difftool.perl b/git-difftool.perl index 3cab257595..c433e86f09 100755 --- a/git-difftool.perl +++ b/git-difftool.perl @@ -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) = @_; @@ -159,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"; } } } diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index eb1d3f85b5..db3d3d6bd1 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -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 && -- cgit v1.2.1