Skip to content

Commit

Permalink
diff: don't use pathname-based diff drivers for symlinks
Browse files Browse the repository at this point in the history
When we're diffing symlinks, we consider the contents to be
the pathname that the symlink points to. When a user sets up
a userdiff driver like "*.pdf diff=pdf", their "diff.pdf.*"
config generally tells us what to do with the content of
pdf files.

With the current code, we will actually process a symlink
like "link.pdf" using a configured pdf driver, meaning we
are using contents which consist of a pathname with
configuration that is expecting contents that consist of an
actual pdf file.

The most noticeable example of this would have been
textconv; however, it was already protected in its own
textconv-specific code path. We can still see the breakage
with something like "diff.*.binary", though. You could
also see it with diff.*.funcname, though it is a bit harder
to trigger accidentally there.

This patch adds a check for S_ISREG lower in the callstack
than the textconv-specific check, which should block use of
any userdiff config for non-regular files. We can drop the
check in the textconv code, which is now redundant.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Sep 24, 2010
1 parent e22148f commit d391c0f
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
11 changes: 8 additions & 3 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1764,8 +1764,14 @@ static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two, char *pre

static void diff_filespec_load_driver(struct diff_filespec *one)
{
if (!one->driver)
/* Use already-loaded driver */
if (one->driver)
return;

if (S_ISREG(one->mode))
one->driver = userdiff_find_by_path(one->path);

/* Fallback to default settings */
if (!one->driver)
one->driver = userdiff_find_by_name("default");
}
Expand Down Expand Up @@ -1813,8 +1819,7 @@ struct userdiff_driver *get_textconv(struct diff_filespec *one)
{
if (!DIFF_FILE_VALID(one))
return NULL;
if (!S_ISREG(one->mode))
return NULL;

diff_filespec_load_driver(one);
if (!one->driver->textconv)
return NULL;
Expand Down
26 changes: 26 additions & 0 deletions t/t4011-diff-symlink.sh
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,30 @@ test_expect_success \
test_must_fail git diff --no-index pinky brain > output 2> output.err &&
grep narf output &&
! grep error output.err'

test_expect_success SYMLINKS 'setup symlinks with attributes' '
echo "*.bin diff=bin" >>.gitattributes &&
echo content >file.bin &&
ln -s file.bin link.bin &&
git add -N file.bin link.bin
'

cat >expect <<'EOF'
diff --git a/file.bin b/file.bin
index e69de29..d95f3ad 100644
Binary files a/file.bin and b/file.bin differ
diff --git a/link.bin b/link.bin
index e69de29..dce41ec 120000
--- a/link.bin
+++ b/link.bin
@@ -0,0 +1 @@
+file.bin
\ No newline at end of file
EOF
test_expect_success SYMLINKS 'symlinks do not respect userdiff config by path' '
git config diff.bin.binary true &&
git diff file.bin link.bin >actual &&
test_cmp expect actual
'

test_done

0 comments on commit d391c0f

Please sign in to comment.