#!/bin/sh interactive="ja" bdiff3cmd="/usr/obj/usr/home/tj/code/freebsd/worktrees/diff3/amd64.amd64/usr.bin/diff3/diff3" operations="File operations performed:\n" # diff3 compares three files as arguments in the order, mine original yours # the file 'mine' represents changes you have made to original. 'yours' # represents changes someone else has made to original. # # diff3 attempts to distinguish and merge the differences made in 'yours' into # 'mine' and can be used to highlight conflicting changes between the two # update files. original="o.txt" mine="m.txt" yours="y.txt" # diff3 uses diff to determine the changes made by 'mine' and 'yours', it diffs # mine and original and yours and original like so: # # diff mine original # diff mine yours # # the differences in each pair of files are collected up and merged together # where possible. There are three types of difference possible between either # pair of files: # # - an addition # A new line or a range of lines is added in the second file. # - a change # A range of lines is changed between the two files, changes can increase # or decrease the length of the range in the original file. i.e # we can can lines 4 -> 10 to be 4 -> 8, replacing existing lines # in the processs. # - a deletion # A line or range of lines is removed from the original file and is # missing in the new file. # # diff3 attempts to merge the two sets of differences to create a single # unified file. # # - Deletions overlap or collide they can always be safely merged. # - If additions or changes are made and they are the same in both files they # can be merged. # - If additions or changes are made and they differ between the two new files # they generate a conflict. In the case of a conflict diff3 doesn't know what # to do and can be configured to mark the conflict in its output. # # To test diff3 we need to generate all types of changes in both conflicting # and non-conflicting positions. Fortunately (and very very sadly), diff3 has # an ed output mode leading to the me learning ed, learning ed wouldn't have # been possible without mwl's book Ed Mastery. We can use ed to easily (lol) # generate changes for our files. # # diff gets a little odd on short file and long files, to full test diff3 we # need to test changes of differing sizes on files of differing sizes. We need # to catch simple cases like small changes in big files, and complex cases such # as changes that take up a large portion or most of the files. # # delete lines in file starting from start and covering lines lines. delete () { file=$1 start=$2 lines=$3 echo "${start},$((${start}+${lines}))d wq"| ed $file >/dev/null operations="$operations\ndelete $file $start $lines" } change() { file=$1 start=$2 lines=$3 prefix=$4 echo "${start} c $(seq -f "${prefix} %g" ${lines}) . wq" | ed $file >/dev/null operations="$operations\nchange $file $start $lines $prefix" } add() { file=$1 start=$2 lines=$3 prefix=$4 echo "${start} a $(seq -f "${prefix} %g" ${lines}) . wq" | ed $file >/dev/null operations="$operations\nadd $file $start $lines $prefix" } sizes="10" for size in $sizes do # Generate an original file seq -f "o %g" $size > $original operations="$operations\ncreate $size $original" # both mine and yours have original as a common ancestor cp $original $mine cp $original $yours # we need to test the following cases: # - add in just mine # - add in just yours # - add in both non-conflicting # - add in both conflicting # - change in just mine # - change in just yours # - change in both files that don't overlap # - change in both files that do overlap # - change matching in both (m==y) # - delete mergable # - delete non-mergable # - mine removed # - yours removed # - mine completely rewritten # - yours completely rewritten # - both rewritten delete $mine 7 2 delete $yours 7 2 # add $mine 7 10 m # add $yours 7 10 y # change $mine 7 10 m # change $yours 7 10 y d3flags="-e -E -A -m -Em -x -X" for flags in $d3flags do # diff $original $mine # diff $original $yours # set -e gdiff3 $flags $mine $original $yours > gdiff3.out $bdiff3cmd $flags $mine $original $yours > bdiff3.out # set +e cmp bdiff3.out gdiff3.out >/dev/null if [ $? -ne 0 ] then if [ ! -z $interactive ] then clear echo "diff3 failed with flags: $flags" echo -e $operations "\n" printf "fbsddiff3\t\t\t\t\t\t\tgdiff3\n\n" sdiff bdiff3.out gdiff3.out echo "waiting for input to continue" read tmp else echo "diff3 failed with flags: $flags" fi # exit 1 fi done done