Merge branch 'jk/diff-convfilter-test-fix'

* jk/diff-convfilter-test-fix:
  Avoid using non-portable `echo -n` in tests.
  add userdiff textconv tests
  document the diff driver textconv feature
  diff: add missing static declaration

Conflicts:
	Documentation/gitattributes.txt
This commit is contained in:
Junio C Hamano 2008-11-12 21:50:41 -08:00
commit 459d60084f
7 changed files with 178 additions and 20 deletions

View file

@ -216,10 +216,12 @@ Generating diff text
`diff` `diff`
^^^^^^ ^^^^^^
The attribute `diff` affects if 'git-diff' generates textual The attribute `diff` affects how 'git' generates diffs for particular
patch for the path or just says `Binary files differ`. It also files. It can tell git whether to generate a textual patch for the path
can affect what line is shown on the hunk header `@@ -k,l +n,m @@` or to treat the path as a binary file. It can also affect what line is
line. shown on the hunk header `@@ -k,l +n,m @@` line, tell git to use an
external command to generate the diff, or ask git to convert binary
files to a text format before generating the diff.
Set:: Set::
@ -230,7 +232,8 @@ Set::
Unset:: Unset::
A path to which the `diff` attribute is unset will A path to which the `diff` attribute is unset will
generate `Binary files differ`. generate `Binary files differ` (or a binary patch, if
binary patches are enabled).
Unspecified:: Unspecified::
@ -241,21 +244,21 @@ Unspecified::
String:: String::
Diff is shown using the specified custom diff driver. Diff is shown using the specified diff driver. Each driver may
The driver program is given its input using the same specify one or more options, as described in the following
calling convention as used for GIT_EXTERNAL_DIFF section. The options for the diff driver "foo" are defined
program. This name is also used for custom hunk header by the configuration variables in the "diff.foo" section of the
selection. git config file.
Defining a custom diff driver Defining an external diff driver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The definition of a diff driver is done in `gitconfig`, not The definition of a diff driver is done in `gitconfig`, not
`gitattributes` file, so strictly speaking this manual page is a `gitattributes` file, so strictly speaking this manual page is a
wrong place to talk about it. However... wrong place to talk about it. However...
To define a custom diff driver `jcdiff`, add a section to your To define an external diff driver `jcdiff`, add a section to your
`$GIT_DIR/config` file (or `$HOME/.gitconfig` file) like this: `$GIT_DIR/config` file (or `$HOME/.gitconfig` file) like this:
---------------------------------------------------------------- ----------------------------------------------------------------
@ -331,6 +334,43 @@ patterns are available:
- `tex` suitable for source code for LaTeX documents. - `tex` suitable for source code for LaTeX documents.
Performing text diffs of binary files
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sometimes it is desirable to see the diff of a text-converted
version of some binary files. For example, a word processor
document can be converted to an ASCII text representation, and
the diff of the text shown. Even though this conversion loses
some information, the resulting diff is useful for human
viewing (but cannot be applied directly).
The `textconv` config option is used to define a program for
performing such a conversion. The program should take a single
argument, the name of a file to convert, and produce the
resulting text on stdout.
For example, to show the diff of the exif information of a
file instead of the binary information (assuming you have the
exif tool installed):
------------------------
[diff "jpg"]
textconv = exif
------------------------
NOTE: The text conversion is generally a one-way conversion;
in this example, we lose the actual image contents and focus
just on the text data. This means that diffs generated by
textconv are _not_ suitable for applying. For this reason,
only `git diff` and the `git log` family of commands (i.e.,
log, whatchanged, show) will perform text conversion. `git
format-patch` will never generate this output. If you want to
send somebody a text-converted diff of a binary file (e.g.,
because it quickly conveys the changes you have made), you
should generate it separately and send it as a comment _in
addition to_ the usual binary diff that you might send.
Performing a three-way merge Performing a three-way merge
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

2
diff.c
View file

@ -1283,7 +1283,7 @@ static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two)
emit_binary_diff_body(file, two, one); emit_binary_diff_body(file, two, one);
} }
void diff_filespec_load_driver(struct diff_filespec *one) static void diff_filespec_load_driver(struct diff_filespec *one)
{ {
if (!one->driver) if (!one->driver)
one->driver = userdiff_find_by_path(one->path); one->driver = userdiff_find_by_path(one->path);

View file

@ -13,7 +13,7 @@ file if core.symlinks is false.'
test_expect_success \ test_expect_success \
'preparation' ' 'preparation' '
git config core.symlinks false && git config core.symlinks false &&
l=$(echo -n file | git hash-object -t blob -w --stdin) && l=$(printf file | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info' echo "120000 $l symlink" | git update-index --index-info'
test_expect_success \ test_expect_success \

View file

@ -13,12 +13,12 @@ even if a plain file is in the working tree if core.symlinks is false.'
test_expect_success \ test_expect_success \
'preparation' ' 'preparation' '
git config core.symlinks false && git config core.symlinks false &&
l=$(echo -n file | git hash-object -t blob -w --stdin) && l=$(printf file | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info' echo "120000 $l symlink" | git update-index --index-info'
test_expect_success \ test_expect_success \
'modify the symbolic link' ' 'modify the symbolic link' '
echo -n new-file > symlink && printf new-file > symlink &&
git update-index symlink' git update-index symlink'
test_expect_success \ test_expect_success \

118
t/t4030-diff-textconv.sh Executable file
View file

@ -0,0 +1,118 @@
#!/bin/sh
test_description='diff.*.textconv tests'
. ./test-lib.sh
find_diff() {
sed '1,/^index /d' | sed '/^-- $/,$d'
}
cat >expect.binary <<'EOF'
Binary files a/file and b/file differ
EOF
cat >expect.text <<'EOF'
--- a/file
+++ b/file
@@ -1 +1,2 @@
0
+1
EOF
cat >hexdump <<'EOF'
#!/bin/sh
perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' "$1"
EOF
chmod +x hexdump
test_expect_success 'setup binary file with history' '
printf "\\0\\n" >file &&
git add file &&
git commit -m one &&
printf "\\1\\n" >>file &&
git add file &&
git commit -m two
'
test_expect_success 'file is considered binary by porcelain' '
git diff HEAD^ HEAD >diff &&
find_diff <diff >actual &&
test_cmp expect.binary actual
'
test_expect_success 'file is considered binary by plumbing' '
git diff-tree -p HEAD^ HEAD >diff &&
find_diff <diff >actual &&
test_cmp expect.binary actual
'
test_expect_success 'setup textconv filters' '
echo file diff=foo >.gitattributes &&
git config diff.foo.textconv "$PWD"/hexdump &&
git config diff.fail.textconv false
'
test_expect_failure 'diff produces text' '
git diff HEAD^ HEAD >diff &&
find_diff <diff >actual &&
test_cmp expect.text actual
'
test_expect_success 'diff-tree produces binary' '
git diff-tree -p HEAD^ HEAD >diff &&
find_diff <diff >actual &&
test_cmp expect.binary actual
'
test_expect_failure 'log produces text' '
git log -1 -p >log &&
find_diff <log >actual &&
test_cmp expect.text actual
'
test_expect_failure 'format-patch produces binary' '
git format-patch --no-binary --stdout HEAD^ >patch &&
find_diff <patch >actual &&
test_cmp expect.binary actual
'
cat >expect.stat <<'EOF'
file | Bin 2 -> 4 bytes
1 files changed, 0 insertions(+), 0 deletions(-)
EOF
test_expect_failure 'diffstat does not run textconv' '
echo file diff=fail >.gitattributes &&
git diff --stat HEAD^ HEAD >actual &&
test_cmp expect.stat actual
'
# restore working setup
echo file diff=foo >.gitattributes
cat >expect.typechange <<'EOF'
--- a/file
+++ /dev/null
@@ -1,2 +0,0 @@
-0
-1
diff --git a/file b/file
new file mode 120000
index ad8b3d2..67be421
--- /dev/null
+++ b/file
@@ -0,0 +1 @@
+frotz
\ No newline at end of file
EOF
# make a symlink the hard way that works on symlink-challenged file systems
test_expect_failure 'textconv does not act on symlinks' '
printf frotz > file &&
git add file &&
git ls-files -s | sed -e s/100644/120000/ |
git update-index --index-info &&
git commit -m typechange &&
git show >diff &&
find_diff <diff >actual &&
test_cmp expect.typechange actual
'
test_done

View file

@ -18,11 +18,11 @@ git add file &&
git commit -m initial && git commit -m initial &&
git branch b-symlink && git branch b-symlink &&
git branch b-file && git branch b-file &&
l=$(echo -n file | git hash-object -t blob -w --stdin) && l=$(printf file | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info && echo "120000 $l symlink" | git update-index --index-info &&
git commit -m master && git commit -m master &&
git checkout b-symlink && git checkout b-symlink &&
l=$(echo -n file-different | git hash-object -t blob -w --stdin) && l=$(printf file-different | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info && echo "120000 $l symlink" | git update-index --index-info &&
git commit -m b-symlink && git commit -m b-symlink &&
git checkout b-file && git checkout b-file &&

View file

@ -424,7 +424,7 @@ cd "$WORKDIR"
test_expect_success 'cvs update (-p)' ' test_expect_success 'cvs update (-p)' '
touch really-empty && touch really-empty &&
echo Line 1 > no-lf && echo Line 1 > no-lf &&
echo -n Line 2 >> no-lf && printf "Line 2" >> no-lf &&
git add really-empty no-lf && git add really-empty no-lf &&
git commit -q -m "Update -p test" && git commit -q -m "Update -p test" &&
git push gitcvs.git >/dev/null && git push gitcvs.git >/dev/null &&