|  | #!/bin/sh | 
|  |  | 
|  | test_description='diff --relative tests' | 
|  |  | 
|  | . ./test-lib.sh | 
|  |  | 
|  | test_expect_success 'setup' ' | 
|  | git commit --allow-empty -m empty && | 
|  | echo content >file1 && | 
|  | mkdir subdir && | 
|  | echo other content >subdir/file2 && | 
|  | blob_file1=$(git hash-object file1) && | 
|  | blob_file2=$(git hash-object subdir/file2) && | 
|  | git add . && | 
|  | git commit -m one | 
|  | ' | 
|  |  | 
|  | check_diff () { | 
|  | dir=$1 | 
|  | shift | 
|  | expect=$1 | 
|  | shift | 
|  | short_blob=$(git rev-parse --short $blob_file2) | 
|  | cat >expected <<-EOF | 
|  | diff --git a/$expect b/$expect | 
|  | new file mode 100644 | 
|  | index 0000000..$short_blob | 
|  | --- /dev/null | 
|  | +++ b/$expect | 
|  | @@ -0,0 +1 @@ | 
|  | +other content | 
|  | EOF | 
|  | test_expect_success "-p $*" " | 
|  | git -C '$dir' diff -p $* HEAD^ >actual && | 
|  | test_cmp expected actual | 
|  | " | 
|  | } | 
|  |  | 
|  | check_numstat () { | 
|  | dir=$1 | 
|  | shift | 
|  | expect=$1 | 
|  | shift | 
|  | cat >expected <<-EOF | 
|  | 1	0	$expect | 
|  | EOF | 
|  | test_expect_success "--numstat $*" " | 
|  | echo '1	0	$expect' >expected && | 
|  | git -C '$dir' diff --numstat $* HEAD^ >actual && | 
|  | test_cmp expected actual | 
|  | " | 
|  | } | 
|  |  | 
|  | check_stat () { | 
|  | dir=$1 | 
|  | shift | 
|  | expect=$1 | 
|  | shift | 
|  | cat >expected <<-EOF | 
|  | $expect | 1 + | 
|  | 1 file changed, 1 insertion(+) | 
|  | EOF | 
|  | test_expect_success "--stat $*" " | 
|  | git -C '$dir' diff --stat $* HEAD^ >actual && | 
|  | test_cmp expected actual | 
|  | " | 
|  | } | 
|  |  | 
|  | check_raw () { | 
|  | dir=$1 | 
|  | shift | 
|  | expect=$1 | 
|  | shift | 
|  | cat >expected <<-EOF | 
|  | :000000 100644 $ZERO_OID $blob_file2 A	$expect | 
|  | EOF | 
|  | test_expect_success "--raw $*" " | 
|  | git -C '$dir' diff --no-abbrev --raw $* HEAD^ >actual && | 
|  | test_cmp expected actual | 
|  | " | 
|  | } | 
|  |  | 
|  | for type in diff numstat stat raw | 
|  | do | 
|  | check_$type . file2 --relative=subdir/ | 
|  | check_$type . file2 --relative=subdir | 
|  | check_$type subdir file2 --relative | 
|  | check_$type . dir/file2 --relative=sub | 
|  | done | 
|  |  | 
|  | check_diff_relative_option () { | 
|  | dir=$1 | 
|  | shift | 
|  | expect=$1 | 
|  | shift | 
|  | relative_opt=$1 | 
|  | shift | 
|  | test_expect_success "config diff.relative $relative_opt -p $*" " | 
|  | short_blob=\$(git rev-parse --short $blob_file2) && | 
|  | cat >expected <<-EOF && | 
|  | diff --git a/$expect b/$expect | 
|  | new file mode 100644 | 
|  | index 0000000..\$short_blob | 
|  | --- /dev/null | 
|  | +++ b/$expect | 
|  | @@ -0,0 +1 @@ | 
|  | +other content | 
|  | EOF | 
|  | test_config -C $dir diff.relative $relative_opt && | 
|  | git -C '$dir' diff -p $* HEAD^ >actual && | 
|  | test_cmp expected actual | 
|  | " | 
|  | } | 
|  |  | 
|  | check_diff_no_relative_option () { | 
|  | dir=$1 | 
|  | shift | 
|  | expect=$1 | 
|  | shift | 
|  | relative_opt=$1 | 
|  | shift | 
|  | test_expect_success "config diff.relative $relative_opt -p $*" " | 
|  | short_blob_file1=\$(git rev-parse --short $blob_file1) && | 
|  | short_blob_file2=\$(git rev-parse --short $blob_file2) && | 
|  | cat >expected <<-EOF && | 
|  | diff --git a/file1 b/file1 | 
|  | new file mode 100644 | 
|  | index 0000000..\$short_blob_file1 | 
|  | --- /dev/null | 
|  | +++ b/file1 | 
|  | @@ -0,0 +1 @@ | 
|  | +content | 
|  | diff --git a/$expect b/$expect | 
|  | new file mode 100644 | 
|  | index 0000000..\$short_blob_file2 | 
|  | --- /dev/null | 
|  | +++ b/$expect | 
|  | @@ -0,0 +1 @@ | 
|  | +other content | 
|  | EOF | 
|  | test_config -C $dir diff.relative $relative_opt && | 
|  | git -C '$dir' diff -p $* HEAD^ >actual && | 
|  | test_cmp expected actual | 
|  | " | 
|  | } | 
|  |  | 
|  | check_diff_no_relative_option . subdir/file2 false | 
|  | check_diff_no_relative_option . subdir/file2 true --no-relative | 
|  | check_diff_no_relative_option . subdir/file2 false --no-relative | 
|  | check_diff_no_relative_option subdir subdir/file2 false | 
|  | check_diff_no_relative_option subdir subdir/file2 true --no-relative | 
|  | check_diff_no_relative_option subdir subdir/file2 false --no-relative | 
|  |  | 
|  | check_diff_relative_option . file2 false --relative=subdir/ | 
|  | check_diff_relative_option . file2 false --relative=subdir | 
|  | check_diff_relative_option . file2 true --relative=subdir/ | 
|  | check_diff_relative_option . file2 true --relative=subdir | 
|  | check_diff_relative_option subdir file2 false --relative | 
|  | check_diff_relative_option subdir file2 true --relative | 
|  | check_diff_relative_option subdir file2 true | 
|  | check_diff_relative_option subdir file2 false --no-relative --relative | 
|  | check_diff_relative_option subdir file2 true --no-relative --relative | 
|  | check_diff_relative_option . file2 false --no-relative --relative=subdir | 
|  | check_diff_relative_option . file2 true --no-relative --relative=subdir | 
|  |  | 
|  | test_expect_success 'external diff with --relative' ' | 
|  | test_when_finished "git reset --hard" && | 
|  | echo changed >file1 && | 
|  | echo changed >subdir/file2 && | 
|  |  | 
|  | write_script mydiff <<-\EOF && | 
|  | # hacky pretend diff; the goal here is just to make sure we got | 
|  | # passed sensible input that we _could_ diff, without relying on | 
|  | # the specific output of a system diff tool. | 
|  | echo "diff a/$1 b/$1" && | 
|  | echo "--- a/$1" && | 
|  | echo "+++ b/$1" && | 
|  | echo "@@ -1 +0,0 @@" && | 
|  | sed "s/^/-/" "$2" && | 
|  | sed "s/^/+/" "$5" | 
|  | EOF | 
|  |  | 
|  | cat >expect <<-\EOF && | 
|  | diff a/file2 b/file2 | 
|  | --- a/file2 | 
|  | +++ b/file2 | 
|  | @@ -1 +0,0 @@ | 
|  | -other content | 
|  | +changed | 
|  | EOF | 
|  | GIT_EXTERNAL_DIFF=./mydiff git diff --relative=subdir >actual && | 
|  | test_cmp expect actual | 
|  | ' | 
|  |  | 
|  | test_expect_success 'setup diff --relative unmerged' ' | 
|  | test_commit zero file0 && | 
|  | test_commit base subdir/file0 && | 
|  | git switch -c br1 && | 
|  | test_commit one file0 && | 
|  | test_commit sub1 subdir/file0 && | 
|  | git switch -c br2 base && | 
|  | test_commit two file0 && | 
|  | git switch -c br3 && | 
|  | test_commit sub3 subdir/file0 | 
|  | ' | 
|  |  | 
|  | test_expect_success 'diff --relative without change in subdir' ' | 
|  | git switch br2 && | 
|  | test_when_finished "git merge --abort" && | 
|  | test_must_fail git merge one && | 
|  | git -C subdir diff --relative >out && | 
|  | test_must_be_empty out && | 
|  | git -C subdir diff --relative --name-only >out && | 
|  | test_must_be_empty out | 
|  | ' | 
|  |  | 
|  | test_expect_success 'diff --relative --name-only with change in subdir' ' | 
|  | git switch br3 && | 
|  | test_when_finished "git merge --abort" && | 
|  | test_must_fail git merge sub1 && | 
|  | test_write_lines file0 file0 >expected && | 
|  | git -C subdir diff --relative --name-only >out && | 
|  | test_cmp expected out | 
|  | ' | 
|  |  | 
|  | test_expect_failure 'diff --relative with change in subdir' ' | 
|  | git switch br3 && | 
|  | br1_blob=$(git rev-parse --short --verify br1:subdir/file0) && | 
|  | br3_blob=$(git rev-parse --short --verify br3:subdir/file0) && | 
|  | test_when_finished "git merge --abort" && | 
|  | test_must_fail git merge br1 && | 
|  | cat >expected <<-EOF && | 
|  | diff --cc file0 | 
|  | index $br3_blob,$br1_blob..0000000 | 
|  | --- a/file0 | 
|  | +++ b/file0 | 
|  | @@@ -1,1 -1,1 +1,5 @@@ | 
|  | ++<<<<<<< HEAD | 
|  | +sub3 | 
|  | ++======= | 
|  | + sub1 | 
|  | ++>>>>>>> br1 | 
|  | EOF | 
|  | git -C subdir diff --relative >out && | 
|  | test_cmp expected out | 
|  | ' | 
|  |  | 
|  | test_done |