Skip to content

Commit

Permalink
diff: do not reuse_worktree_file for submodules
Browse files Browse the repository at this point in the history
The GIT_EXTERNAL_DIFF calling code attempts to reuse existing worktree
files for the worktree side of diffs, for performance reasons.
However, that code also tries to do the same with submodules.  This
results in calls to $GIT_EXTERNAL_DIFF where the old-file is a file of
the form "Submodule commit $sha1", but the new-file is a directory in
the worktree.

Fix it by never reusing a worktree "file" in the submodule case.

Reported-by: Grégory Pakosz <gregory.pakosz@gmail.com>
Signed-off-by: Thomas Rast <tr@thomasrast.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Thomas Rast authored and Junio C Hamano committed Feb 18, 2014
1 parent 2f93541 commit aba4727
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
5 changes: 3 additions & 2 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -2842,8 +2842,9 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
remove_tempfile_installed = 1;
}

if (!one->sha1_valid ||
reuse_worktree_file(name, one->sha1, 1)) {
if (!S_ISGITLINK(one->mode) &&
(!one->sha1_valid ||
reuse_worktree_file(name, one->sha1, 1))) {
struct stat st;
if (lstat(name, &st) < 0) {
if (errno == ENOENT)
Expand Down
30 changes: 29 additions & 1 deletion t/t4020-diff-external.sh
Original file line number Diff line number Diff line change
Expand Up @@ -213,17 +213,45 @@ keep_only_cr () {
}

test_expect_success 'external diff with autocrlf = true' '
git config core.autocrlf true &&
test_config core.autocrlf true &&
GIT_EXTERNAL_DIFF=./fake-diff.sh git diff &&
test $(wc -l < crlfed.txt) = $(cat crlfed.txt | keep_only_cr | wc -c)
'

test_expect_success 'diff --cached' '
test_config core.autocrlf true &&
git add file &&
git update-index --assume-unchanged file &&
echo second >file &&
git diff --cached >actual &&
test_cmp "$TEST_DIRECTORY"/t4020/diff.NUL actual
'

test_expect_success 'clean up crlf leftovers' '
git update-index --no-assume-unchanged file &&
rm -f file* &&
git reset --hard
'

test_expect_success 'submodule diff' '
git init sub &&
( cd sub && test_commit sub1 ) &&
git add sub &&
test_tick &&
git commit -m "add submodule" &&
( cd sub && test_commit sub2 ) &&
write_script gather_pre_post.sh <<-\EOF &&
echo "$1 $4" # path, mode
cat "$2" # old file
cat "$5" # new file
EOF
GIT_EXTERNAL_DIFF=./gather_pre_post.sh git diff >actual &&
cat >expected <<-EOF &&
sub 160000
Subproject commit $(git rev-parse HEAD:sub)
Subproject commit $(cd sub && git rev-parse HEAD)
EOF
test_cmp expected actual
'

test_done

0 comments on commit aba4727

Please sign in to comment.