#!/bin/bash

# Creates two darcs repos such that the common files (and file chunks)
# between them are all in one commit


function fail {
    ret=$1
    shift
    echo -e "$@"
    exit "${ret}"
}

function ask_yn {
    while read -rn1 -p "$* (y/n) "
    do
        echo >&2
        case $REPLY in
            [Yy]) return 0;;
            [Nn]) return 1;;
            *) echo >&2 "Enter y or n";;
        esac
    done
    return 2  # EOF
}

if [[ ${#} != 2 ]]
then
    fail 2 "Usage: ${0##*/} LEFT RIGHT"
fi

set -u

Left=${1%/}
Right=${2%/}
Workdir=$(mktemp -d)
Dest=${Workdir}/$(basename "${Right}")
trap 'rm -rf "${Workdir}"' EXIT

Have_existing_darcs_dirs=

[[ -d ${Left} ]]  ||  fail 2 "${Left} is not a dir"
[[ -d ${Right} ]]  ||  fail 2 "${Right} is not a dir"
Left=$(cd "${Left}" && pwd -P)
Right=$(cd "${Right}" && pwd -P)

if [[ -d ${Left}/_darcs ]]
then
	echo >&2 "${Left} already has a _darcs dir"
	Have_existing_darcs_dirs=1
fi
if [[ -d ${Right}/_darcs ]]
then
	echo >&2 "${Right} already has a _darcs dir"
	Have_existing_darcs_dirs=1
fi
if [[ -n ${Have_existing_darcs_dirs} ]]
then
	ask_yn "Existing _darcs dirs found; delete and start over?"  ||  fail 2 "Exiting."
	rm -rf "${Left}/_darcs" "${Right}/_darcs"  ||  fail 3 "Failed to delete existing _darcs dirs"
fi

cp -a "${Right}" "${Dest}"  ||  fail 3 "Failed to create initial ${Dest}"
cd "${Dest}"  ||  fail 3 "Failed to enter ${Dest}"
darcs init  ||  fail 4 "Failed to make darcs repo"

find "." -name '_*' -prune -o -name '.?*' -prune -o -type f -print0 | while read -d '' -r destfile
do
    leftfile=${Left}/${destfile#./}
    rightfile=${Right}/${destfile#./}
    if [[ ! -f ${leftfile} ]]
    then
        rm -f "${destfile}" && echo -e "-\t${destfile}"
        continue
    fi
    diff -q "${leftfile}" "${rightfile}" &>/dev/null
    ret=$?
    case $ret in
        0)      darcs add -q "${destfile}" && echo -e "A\t${destfile}";;
        1)      diff -U99999 "${leftfile}" "${rightfile}" | grep '^ ' | cut -c 2- > "${destfile}" &&
                darcs add -q "${destfile}" &&
                echo -e "C\t${destfile}"
                ;;
        *)      : ;;
    esac
done
darcs record -qam "Common"  ||  fail 5 "Failed to do initial record"

cp -a "./_darcs" "${Left}/_darcs"  ||  fail 6 "Failed to copy _darcs to ${Left}"
cp -a "./_darcs" "${Right}/_darcs"  ||  fail 6 "Failed to copy _darcs to ${Right}"

# Set the default repos to point to each other
echo "${Right}" > "${Left}/_darcs/prefs/defaultrepo"
echo "${Left}" > "${Right}/_darcs/prefs/defaultrepo"

# The rest of this program is interactive.
if [[ ! (-t 0 && -t 1 && -t 2) ]]
then
    echo Done.
    exit 0
fi


function record_differences {
    local repo first ret
    repo="$1"
    first=1
    pushd "${repo}"  ||  return $?
    echo
    echo
    echo "Checking for differences in ${repo} :"
    echo
    while darcs whatsnew -sl
    do
        if [[ ${first} = 1 ]]
        then
            echo
            echo "Differences found."
        else
            echo
            echo "More differences found."
        fi
        first=0

        if ask_yn "Record differences in ${repo}?"
        then
            darcs record -ql; ret=$?
            if [[ ${ret} != 0 ]]
            then
                echo "Darcs returned ${ret}."
                if ask_yn "Try again?"
                then
                    continue
                else
                    popd || :
                    return ${ret}
                fi
            fi
        else
            popd || :
            return 0
        fi
    done
    echo
    if [[ ${first} = 1 ]]
    then
        echo "No differences found."
    else
        echo "No differences remaining."
    fi
    popd || :
    return 0
}


record_differences "${Left}"
record_differences "${Right}"

echo "Done."
