--- tests/NOTES | 23 ++ tests/diff3-merge.shrun | 51 ++++ tests/locate-rejects.shrun | 77 +++++++ tests/modes.shrun | 401 ++++++++++++++++++++++++++++++++++++++ tests/prefix-suffix.shrun | 42 +++ tests/rejects.shrun | 133 ++++++++++++ tests/wiggle-base.shrun | 157 ++++++++++++++ tests/wiggle-bugs.shrun | 179 ++++++++++++++++ tests/wiggle-changeafteradd.shrun | 69 ++++++ 9 files changed, 1132 insertions(+) Index: b/tests/diff3-merge.shrun =================================================================== --- /dev/null +++ b/tests/diff3-merge.shrun @@ -0,0 +1,51 @@ +$ tmpdir=$(mktemp -d) +$ trap "cd /; rm -rf $tmpdir" EXIT +$ cd $tmpdir + + $ seq 1 4 > a + $ sed -e 's/2/2b/' a > b + $ sed -e 's/4/4d/' a > c + +Diff3 will merge changes if there is a one-line gap between them. +(Patch would merge this as well.) + + $ diff3 -m b a c + > 1 + > 2b + > 3 + > 4d + +But it will not merge adjacent but nonoverlapping changes. +(Patch would merge this.) + + $ sed -e 's/3/3c/' a > d + $ diff3 -m b a d + > 1 + > <<<<<<< b + > 2b + > 3 + > ||||||| a + > 2 + > 3 + > ======= + > 2 + > 3c + > >>>>>>> d + > 4 + +This is what you get when the first and third files are identical (i.e., +a patch has already been applied). This is confusing because it is not +immediately obvious which section refers to the first file. (It is the +section between === and >>>, while it was the section between <<< and ||| +above.) + + $ cp b e + $ diff3 -m e a b + > 1 + > <<<<<<< a + > 2 + > ======= + > 2b + > >>>>>>> b + > 3 + > 4 Index: b/tests/modes.shrun =================================================================== --- /dev/null +++ b/tests/modes.shrun @@ -0,0 +1,401 @@ +$ PATCH=$(PATH=.:$PATH which patch) +$ patch() { $PATCH "$@"; } + +$ tmpdir=$(mktemp -d) +$ trap "cd /; rm -rf $tmpdir" EXIT +$ cd $tmpdir + +$ cat > clean.diff +< --- a +< +++ b +< @@ -2 +2 @@ +< -2 +< +2clean + +$ seq 1 3 > c ; patch c < clean.diff +> patching file c + +$ cat c +> 1 +> 2clean +> 3 + +$ seq 1 3 > c ; patch -M c < clean.diff +> patching file c + +$ cat c +> 1 +> 2clean +> 3 + +$ cat > fuzz.diff +< --- a +< +++ b +< @@ -1,3 +1,3 @@ +< x +< -2 +< +2fuzz +< x + +$ seq 1 3 > c ; patch c < fuzz.diff +> patching file c +> Hunk #1 succeeded at 1 with fuzz 1. + +$ cat c +> 1 +> 2fuzz +> 3 + +$ patch -f -M c < fuzz.diff +> patching file c +> Hunk #1 merged at 1 with conflicts. + +$ cat c +> <<<<<<< a +> x +> 2 +> x +> ||||||| b +> x +> 2fuzz +> x +> ======= +> >>>>>>> +> 1 +> 2fuzz +> 3 + +$ seq 1 3 > c ; patch -M c < fuzz.diff +> patching file c +> Hunk #1 succeeded at 1 with fuzz 1. + +$ cat c +> 1 +> 2fuzz +> 3 + +$ seq 1 3 > c ; patch --fuzz=0 -M c < fuzz.diff +> patching file c +> Hunk #1 merged at 1 with conflicts. + +$ cat c +> <<<<<<< a +> x +> 2 +> x +> ||||||| b +> x +> 2fuzz +> x +> ======= +> >>>>>>> +> 1 +> 2 +> 3 + +$ cat > reject.diff +< --- a +< +++ b +< @@ -2 +2 @@ +< -2reject +< +2tcejer + +$ seq 1 3 > c ; patch c < reject.diff +> patching file c +> Hunk #1 FAILED at 2. +> 1 out of 1 hunk FAILED -- saving rejects to file c.rej + +$ seq 1 3 > c ; patch -M c < reject.diff +> patching file c +> Hunk #1 merged at 2 with conflicts. + +$ cat c +> 1 +> <<<<<<< a +> 2reject +> ||||||| b +> 2tcejer +> ======= +> >>>>>>> +> 2 +> 3 + +$ cat > insert.diff +< --- a +< +++ b +< @@ -2,4 +2,5 @@ +< 2 +< 3x +< +ins +< 4 +< 5 + +$ seq 1 6 > c ; patch -M c < insert.diff +> patching file c +> Hunk #1 succeeded at 2 with fuzz 2. + +$ cat c +> 1 +> 2 +> 3 +> ins +> 4 +> 5 +> 6 + +$ cat > insert.diff +< --- a +< +++ b +< @@ -2,4 +2,5 @@ +< 2 +< 3 +< +ins +< 4x +< 5 + +$ seq 1 6 > c ; patch --fuzz=1 -M c < insert.diff +> patching file c +> Hunk #1 merged at 2 with conflicts. + +$ cat c +> 1 +> 2 +> 3 +> <<<<<<< a +> 4x +> ||||||| b +> ins +> 4x +> ======= +> 4 +> >>>>>>> +> 5 +> 6 + +$ cat > insert.diff +< --- a +< +++ b +< @@ -2,4 +2,5 @@ +< 2 +< 3x +< +ins +< 4x +< 5 + +$ seq 1 6 > c ; patch --fuzz=1 -M c < insert.diff +> patching file c +> Hunk #1 merged at 2 with conflicts. + +$ cat c +> 1 +> 2 +> <<<<<<< a +> 3x +> 4x +> ||||||| b +> 3x +> ins +> 4x +> ======= +> 3 +> 4 +> >>>>>>> +> 5 +> 6 + +$ seq 1 6 > c ; patch -M c < insert.diff +> patching file c +> Hunk #1 succeeded at 2 with fuzz 2. + +$ cat c +> 1 +> 2 +> 3 +> ins +> 4 +> 5 +> 6 + +$ cat > delete.diff +< --- a +< +++ b +< @@ -2,5 +2,4 @@ +< 2 +< 3x +< -4 +< 5 +< 6 + +$ seq 1 7 > c ; patch --fuzz=1 -M c < delete.diff +> patching file c +> Hunk #1 merged at 2 with conflicts. + +$ cat c +> 1 +> 2 +> <<<<<<< a +> 3x +> 4 +> ||||||| b +> 3x +> ======= +> 3 +> 4 +> >>>>>>> +> 5 +> 6 +> 7 + +$ cat > delete.diff +< --- a +< +++ b +< @@ -2,5 +2,4 @@ +< 2 +< 3 +< -4x +< 5 +< 6 + +$ seq 1 7 > c ; patch --fuzz=1 -M c < delete.diff +> patching file c +> Hunk #1 merged at 2 with conflicts. + +$ cat c +> 1 +> 2 +> 3 +> <<<<<<< a +> 4x +> ||||||| b +> ======= +> 4 +> >>>>>>> +> 5 +> 6 +> 7 + +$ cat > delete.diff +< --- a +< +++ b +< @@ -2,5 +2,4 @@ +< 2 +< 3 +< -4 +< 5x +< 6 + +$ seq 1 7 > c ; patch --fuzz=1 -M c < delete.diff +> patching file c +> Hunk #1 merged at 2 with conflicts. + +$ cat c +> 1 +> 2 +> 3 +> <<<<<<< a +> 4 +> 5x +> ||||||| b +> 5x +> ======= +> 4 +> 5 +> >>>>>>> +> 6 +> 7 + +$ cat > change.diff +< --- a +< +++ b +< @@ -2,5 +2,5 @@ +< 2 +< 3x +< -4 +< +4x +< 5 +< 6 + +$ seq 1 7 > c ; patch --fuzz=1 -M c < change.diff +> patching file c +> Hunk #1 merged at 2 with conflicts. + +$ cat c +> 1 +> 2 +> <<<<<<< a +> 3x +> 4 +> ||||||| b +> 3x +> 4x +> ======= +> 3 +> 4 +> >>>>>>> +> 5 +> 6 +> 7 + +$ cat > delete-gone.diff +< --- a +< +++ b +< @@ -1,7 +1,6 @@ +< 1 +< 2 +< 3 +< -4x +< 5 +< 6 +< 7 + +$ seq 1 7 | sed -e '3,5d' > c; patch --fuzz=2 -M c < delete-gone.diff +> patching file c +> Hunk #1 merged at 1 with conflicts. + +$ cat c +> 1 +> 2 +> <<<<<<< a +> 3 +> 4x +> 5 +> ||||||| b +> 3 +> 5 +> ======= +> >>>>>>> +> 6 +> 7 + + +$ cat > insert-gone.diff +< --- a +< +++ b +< @@ -1,6 +1,7 @@ +< 1 +< 2 +< 3 +< +4x +< 5 +< 6 +< 7 + +$ seq 1 7 | sed -e '3,5d' > c; patch --fuzz=2 -M c < insert-gone.diff +> patching file c +> Hunk #1 merged at 1 with conflicts. + +$ cat c +> 1 +> 2 +> <<<<<<< a +> 3 +> 5 +> ||||||| b +> 3 +> 4x +> 5 +> ======= +> >>>>>>> +> 6 +> 7 + Index: b/tests/prefix-suffix.shrun =================================================================== --- /dev/null +++ b/tests/prefix-suffix.shrun @@ -0,0 +1,42 @@ +$ PATCH=$(PATH=.:$PATH which patch) +$ patch() { $PATCH "$@"; } + +$ tmpdir=$(mktemp -d) +$ trap "cd /; rm -rf $tmpdir" EXIT +$ cd $tmpdir + +$ seq 1 7 > a +$ seq 1 7 | sed -e '4d' > b +$ diff -u -L a -L b a b > ab.diff +$ diff -u -L b -L a b a > ba.diff + +$ seq -f '%gc' 1 7 > c +$ patch -M c < ab.diff +> patching file c +> Hunk #1 merged at 1 with conflicts. + +$ cat c +> <<<<<<< a +> 1 +> 2 +> 3 +> 4 +> 5 +> 6 +> 7 +> ||||||| b +> 1 +> 2 +> 3 +> 5 +> 6 +> 7 +> ======= +> >>>>>>> +> 1c +> 2c +> 3c +> 4c +> 5c +> 6c +> 7c Index: b/tests/locate-rejects.shrun =================================================================== --- /dev/null +++ b/tests/locate-rejects.shrun @@ -0,0 +1,77 @@ +$ PATCH=$(PATH=.:$PATH which patch) +$ patch() { $PATCH "$@"; } + +$ tmpdir=$(mktemp -d) +$ trap "cd /; rm -rf $tmpdir" EXIT +$ cd $tmpdir + +$ seq 1 7 > a +$ seq 1 7 | sed -e 's/4/4b/' > b +$ seq 1 7 | sed -e 's/4/4c/' > c + +$ diff -u a b > ab.diff + +$ patch c < ab.diff +> patching file c +> Hunk #1 FAILED at 1. +> 1 out of 1 hunk FAILED -- saving rejects to file c.rej + +$ patch -M c < ab.diff +> patching file c +> Hunk #1 merged at 1 with conflicts. + +$ cat c +> 1 +> 2 +> 3 +> <<<<<<< a +> 4 +> ||||||| b +> 4b +> ======= +> 4c +> >>>>>>> +> 5 +> 6 +> 7 + +$ (seq 1 3; echo 7) > c +$ patch -M c < ab.diff +> patching file c +> Hunk #1 merged at 1 with conflicts. + +$ cat c +> 1 +> 2 +> 3 +> <<<<<<< a +> 4 +> 5 +> 6 +> ||||||| b +> 4b +> 5 +> 6 +> ======= +> >>>>>>> +> 7 + +$ seq 1 7 | sed -e '4d' > c +$ patch -M c < ab.diff +> patching file c +> Hunk #1 merged at 1 with conflicts. + +$ cat c +> 1 +> 2 +> 3 +> <<<<<<< a +> 4 +> ||||||| b +> 4b +> ======= +> >>>>>>> +> 5 +> 6 +> 7 + Index: b/tests/rejects.shrun =================================================================== --- /dev/null +++ b/tests/rejects.shrun @@ -0,0 +1,133 @@ +$ PATCH=$(PATH=.:$PATH which patch) +$ patch() { $PATCH "$@"; } + +$ tmpdir=$(mktemp -d) +$ trap "cd /; rm -rf $tmpdir" EXIT +$ cd $tmpdir + +$ set +o posix + +$ x() { ++ local max=$1 b ++ shift ++ ++ while [ "$1" != -- ]; do ++ b[${#b[@]}]=$1 ++ shift ++ done ++ shift ++ local c=("$@") ++ ++ seq 1 $max > a ++ seq 1 $max | sed -f <(printf "%s\n" "${b[@]}") > b ++ seq 1 $max | sed -f <(printf "%s\n" "${c[@]}") > c ++ ++ diff -u a b | patch -s -f -M c ++ cat c ++ #diff3 -m c a b ++ } + +$ x 9 -- +> 1 +> 2 +> 3 +> 4 +> 5 +> 6 +> 7 +> 8 +> 9 + +$ x 9 5d -- +> 1 +> 2 +> 3 +> 4 +> 6 +> 7 +> 8 +> 9 + +$ x 9 5d -- 5d +> 1 +> 2 +> 3 +> 4 +> <<<<<<< a +> 5 +> ======= +> >>>>>>> b +> 6 +> 7 +> 8 +> 9 + +$ x 9 5d -- 6d +> 1 +> 2 +> 3 +> 4 +> <<<<<<< a +> 5 +> 6 +> ||||||| b +> 6 +> ======= +> 5 +> >>>>>>> +> 7 +> 8 +> 9 + +$ x 9 5d -- 4d +> 1 +> 2 +> 3 +> <<<<<<< a +> 4 +> 5 +> ||||||| b +> 4 +> ======= +> 5 +> >>>>>>> +> 6 +> 7 +> 8 +> 9 + +$ x 9 5aa -- 5aa +> 1 +> 2 +> 3 +> 4 +> 5 +> <<<<<<< a +> ======= +> a +> >>>>>>> b +> 6 +> 7 +> 8 +> 9 + +$ x 9 s/4/4b/ -- s/3/3c/ s/5/5c/ +> 1 +> 2 +> <<<<<<< a +> 3 +> 4 +> 5 +> ||||||| b +> 3 +> 4b +> 5 +> ======= +> 3c +> 4 +> 5c +> >>>>>>> +> 6 +> 7 +> 8 +> 9 Index: b/tests/wiggle-bugs.shrun =================================================================== --- /dev/null +++ b/tests/wiggle-bugs.shrun @@ -0,0 +1,179 @@ +$ WIGGLE=wiggle + +$ PATCH=$(PATH=.:$PATH which patch) +$ patch() { $PATCH "$@"; } + +$ tmpdir=$(mktemp -d) +$ trap "cd /; rm -rf $tmpdir" EXIT +$ cd $tmpdir + +======================================== + +$ echo a > a +$ echo b > b +$ diff -u a b > ab.diff +$ echo c > c +$ diff3 -m c a b +> <<<<<<< c +> c +> ||||||| a +> a +> ======= +> b +> >>>>>>> b + +In this case, patch has no way to know that c is part of the conflict. +It could make a blind guess, though. + +$ patch -s -M c < ab.diff +$ cat c +> <<<<<<< a +> a +> ||||||| b +> b +> ======= +> >>>>>>> +> c + +======================================== + +$ seq 1 7 | sed -e 's/4/4a/' > a +$ seq 1 7 | sed -e 's/4/4b/' > b +$ diff -u a b > ab.diff +$ seq 1 7 | sed -e 's/4/4c/' > c +$ diff3 -m c a b +> 1 +> 2 +> 3 +> <<<<<<< c +> 4c +> ||||||| a +> 4a +> ======= +> 4b +> >>>>>>> b +> 5 +> 6 +> 7 + +$ patch -s -M c < ab.diff +$ cat c +> 1 +> 2 +> 3 +> <<<<<<< a +> 4a +> ||||||| b +> 4b +> ======= +> 4c +> >>>>>>> +> 5 +> 6 +> 7 + +======================================== + +$ seq 1 7 | sed -e 's/4/4a/' > a +$ seq 1 7 | sed -e 's/4/4b/' > b +$ diff -u a b > ab.diff +$ seq 1 7 | sed -e 's/[345]/&c/' > c +$ diff3 -m c a b +> 1 +> 2 +> <<<<<<< c +> 3c +> 4c +> 5c +> ||||||| a +> 3 +> 4a +> 5 +> ======= +> 3 +> 4b +> 5 +> >>>>>>> b +> 6 +> 7 + +$ patch -s -M c < ab.diff +$ cat c +> 1 +> 2 +> <<<<<<< a +> 3 +> 4a +> 5 +> ||||||| b +> 3 +> 4b +> 5 +> ======= +> 3c +> 4c +> 5c +> >>>>>>> +> 6 +> 7 + +======================================== + +$ seq 1 7 | sed -e 's/4/4a/' > a +$ seq 1 7 | sed -e 's/4/4b/' > b +$ diff -u a b > ab.diff +$ seq 1 7 | sed -e 's/./&c/' > c +$ diff3 -m c a b +> <<<<<<< c +> 1c +> 2c +> 3c +> 4c +> 5c +> 6c +> 7c +> ||||||| a +> 1 +> 2 +> 3 +> 4a +> 5 +> 6 +> 7 +> ======= +> 1 +> 2 +> 3 +> 4b +> 5 +> 6 +> 7 +> >>>>>>> b + +$ patch -s -M c < ab.diff 2>/dev/null +$ cat c +> <<<<<<< a +> 1 +> 2 +> 3 +> 4a +> 5 +> 6 +> 7 +> ||||||| b +> 1 +> 2 +> 3 +> 4b +> 5 +> 6 +> 7 +> ======= +> >>>>>>> +> 1c +> 2c +> 3c +> 4c +> 5c +> 6c +> 7c Index: b/tests/NOTES =================================================================== --- /dev/null +++ b/tests/NOTES @@ -0,0 +1,23 @@ +Same change in b and c: + <<<<<<< a + old lines from patch + ======= + new version == new lines from patch + >>>>>>> b + +Conflicting change (section order differs from diff3, otherwise equivalent): + <<<<<<< a + old lines from patch + ||||||| b + new lines from patch + ======= + new version + >>>>>>> + +Clean change (diff3 doesn't have that, so maybe we don't need it either +except for debugging): + <<<<<<< a + old lines + ======= + new version == new lines of patch + >>>>>>> Index: b/tests/wiggle-changeafteradd.shrun =================================================================== --- /dev/null +++ b/tests/wiggle-changeafteradd.shrun @@ -0,0 +1,69 @@ +$ PATCH=$(PATH=.:$PATH which patch) +$ patch() { $PATCH "$@"; } + +$ tmpdir=$(mktemp -d) +$ trap "cd /; rm -rf $tmpdir" EXIT +$ cd $tmpdir + +$ cat > orig +< here +< is +< the +< original +< file + +$ cat > new +< here +< is +< the +< new version of the +< original +< file + +$ cat > new2 +< here +< is +< the +< new version of the +< inaugural +< file + +$ diff3 -m new new2 orig +> here +> is +> the +> <<<<<<< new +> new version of the +> original +> ||||||| new2 +> new version of the +> inaugural +> ======= +> original +> >>>>>>> orig +> file + +In this case, merging without marking the conflict would be desirable: +it should be possible to detect that this is only a minor change to a +context line, there are context matches before and after, and the +number of changes required is small. + +$ diff -u new new2 > ab.diff +$ patch orig -M < ab.diff +> patching file orig +> Hunk #1 merged at 2 with conflicts. + +$ cat orig +> here +> is +> the +> <<<<<<< new +> new version of the +> original +> ||||||| new2 +> new version of the +> inaugural +> ======= +> original +> >>>>>>> +> file Index: b/tests/wiggle-base.shrun =================================================================== --- /dev/null +++ b/tests/wiggle-base.shrun @@ -0,0 +1,157 @@ +$ PATCH=$(PATH=.:$PATH which patch) +$ patch() { $PATCH "$@"; } + +$ tmpdir=$(mktemp -d) +$ trap "cd /; rm -rf $tmpdir" EXIT +$ cd $tmpdir + +$ cat > orig +< +< This is a base file +< some changes are going to happen to it +< but it has +< several lines +< so that alll +< the changes +< don't h... +< I don't know waht I am saying. +< This lion will have some changes made. +< but this one wont +< stuf stuf stuff +< thing thing +< xxxxx +< that is all +< except +< for +< this +< last +< bit + +$ cat > new +< s is a base file +< some changes are going to happen to it +< but it has +< had +< several lines +< so that alll +< the changes +< don't h... +< I don't know what I am saying. +< This line will have some changes made. +< but this one wont +< stuf stuf stuff +< thing thing +< xxxxx +< that is all +< except +< for +< this +< last +< bit +< x + +$ cat > new2 +< This is a base file +< some changes are going to happen to it +< but it has +< had +< several lines +< so that alll +< the changes +< don't h... +< I don't know what I am saying. +< This line will have some modifications made. +< but this one wont +< stuf stuf stuff +< thing thing +< xxxxx +< that is all +< except +< for +< this +< last +< bit +< x +< + +$ diff -u new new2 > ab.diff +$ patch orig -f -M < ab.diff +> patching file orig +> Hunk #1 merged at 1 with conflicts. +> Hunk #2 merged at 7 with conflicts. +> Hunk #3 merged at 19 with conflicts. + +$ cat orig +> <<<<<<< new +> s is a base file +> some changes are going to happen to it +> but it has +> had +> ||||||| new2 +> This is a base file +> some changes are going to happen to it +> but it has +> had +> ======= +> >>>>>>> +> +> This is a base file +> some changes are going to happen to it +> but it has +> several lines +> so that alll +> the changes +> don't h... +> <<<<<<< new +> I don't know what I am saying. +> This line will have some changes made. +> ||||||| new2 +> I don't know what I am saying. +> This line will have some modifications made. +> ======= +> I don't know waht I am saying. +> This lion will have some changes made. +> >>>>>>> +> but this one wont +> stuf stuf stuff +> thing thing +> xxxxx +> that is all +> except +> for +> <<<<<<< new +> last +> bit +> x +> ||||||| new2 +> last +> bit +> x +> +> ======= +> >>>>>>> +> this +> last +> bit + +#$ cat > merge +#< +#< This is a base file +#< some changes are going to happen to it +#< but it has +#< several lines +#< so that alll +#< the changes +#< don't h... +#< I don't know waht I am saying. +#< This lion will have some modifications made. +#< but this one wont +#< stuf stuf stuff +#< thing thing +#< xxxxx +#< that is all +#< except +#< for +#< this +#< last +#< bit