#!/bin/bash

set -e 
$PREPARE_CLEAN > /dev/null
$INCLUDE_FUNCS

cd $WC

# A file gets copied; but before it gets marked as copied, it is changed:
# - The MD5 of the copy must be the original MD5.
# - If the copy gets changed, it must have the correct MD5 after commit.

file1=src-f
file2=cpy-f

logfile=$LOGDIR/045.log

orig=text-$RANDOM-$RANDOM-$RANDOM-text
new=NEW


function CheckStoredMD5
{
  file=$1
  expect=$2
	msg=$3


	$BINdflt info $file > $logfile
	have=`perl -ne 'print $1 if m#^\s+Repos-MD5:\s+(\S+)#' < $logfile`
	if [[ "$expect" == "$have" ]]
	then
	  $SUCCESS "MD5($file): $msg"
	else
	  $ERROR_NB "MD5($file): $msg:"
	  $ERROR_NB "  expected $expect"
	  $ERROR    "  have     $have"
	fi
}



function Test
{
# Generate source file
	echo "$orig" > $file1
	$BINq ci -m "$file1" "$file1"
	orig_md5=`md5sum < $file1 | cut -f1 -d" "`

# Copy, change, and record as copied
	CheckStoredMD5 "$file1" $orig_md5 "$file1 after commit"
	cat $file1 > $file2
	echo "$new" > $file1
	new_md5=`md5sum < $file1 | cut -f1 -d" "`
# The stored value must not change until commit.
	CheckStoredMD5 "$file1" $orig_md5 "changed $file1"
	$BINq cp $file1 $file2
	CheckStoredMD5 "$file1" $orig_md5 "copy recorded - $file1"
	CheckStoredMD5 "$file2" $orig_md5 "copy recorded - $file2"

# Change other file
	echo "$RANDOM-$file2" > $file2
	CheckStoredMD5 "$file2" $orig_md5 "changed"

# Commit other file
	$BINq ci -m "$file2" "$file2"
	new2_md5=`md5sum < $file2 | cut -f1 -d" "`
	CheckStoredMD5 "$file2" $new2_md5 "$file2 after commit"

	CheckStoredMD5 "$file1" $orig_md5 "$file1 after committing $file2"
	$BINq ci -m "$file1" "$file1"
	CheckStoredMD5 "$file1" $new_md5 "committed $file1"
}


$INFO "Run 1"
Test

ls -i | sort -n

# There might be differences in the behaviour, depending on whether file1 
# or file2 is first in the inode order. So we try both ways.
$INFO "Run 2 with exchanged inodes"
mv "$file1" xx
mv "$file2" "$file1"
mv xx "$file2"
# Put the second file out of the filelist, so that it can be added again
$BINq unversion "$file2"
$BINq ci -m "inodes"
Test

ls -i | sort -n


# Test uncopy.
mkdir d1
date > d1/date
$BINq ci -m "T" -o delay=yes
targ=target-$$

echo $targ $$ > "$targ"
mkdir d2
echo $$ > d2/date
echo $$ > d2/new

$BINdflt cp "$file1" "$targ"
$BINdflt cp d1 d2

if [[ `$BINdflt st "$targ"` != ".mC+ "*" $targ" ]]
then
	$BINdflt st "$targ"
	$ERROR "Unexpected status output after cp."
fi
$BINdflt st d2 > $logfile
if [[ `sort < $logfile` != ".mC+ "*" d2/date"*".mC+ "*" dir  d2"*"N... "*" d2/new" ]]
then
	cat $logfile
	$ERROR "Unexpected status output after cp."
fi

$BINdflt uncopy "$targ"
if [[ `$BINdflt st "$targ"` == "N... "*" $targ" ]]
then
	$SUCCESS "'uncopy file' works"
else
	$BINdflt st "$targ"
	$ERROR "Unexpected status output after 'uncopy file'."
fi
$BINdflt uncopy d2
$BINdflt st > $logfile
if [[ `grep "^N\.\.\." < $logfile | wc -l` -eq 4 ]]
then
	$SUCCESS "'uncopy dir' works"
else
	$BINdflt st
	$ERROR "Unexpected status output after 'uncopy dir'."
fi


# Now test uncopy of added and property-set entries
$BINq cp d1 d2
echo 12345 > d2/added
echo 54321 > d2/prop
$BINq ps a b d2/prop
$BINq add d2/added


$BINdflt uncopy d2


function C
{
	$BINdflt st "$1" -N -N > $logfile
	if [[ `cat $logfile` != $2* ]]
	then
		cat $logfile
		$ERROR "Wrong status for $1, exp. $2"
	fi
}
$BINdflt st d2 > $logfile
C d2 'n...'
C d2/added 'n...'
C d2/prop 'nP..'

$SUCCESS "uncopy sets ADDED".



# Now we build a big file (so that manber hashes are done), commit it, and 
# define a copy.
# - for the simple copy with the same mtime *no* MD5 should be calculated
# - for a change (different mtime) the MD5 has to be done.
# - On commit the manber hashes should be done (but locally only, the file 
#   must not be sent to the repository)

# We need the debug output to see whether that works as wanted.
if [[ "$opt_DEBUG" != "1" ]]
then
	$WARN "Can't test manber hashing without debug log."
	# Or can we, simply looking whether the md5s file exist?
	exit
fi

file1=tt-$RANDOM
file2=$file1.cp
function CountManber
{
	exp="$1"
	shift
	if $BINdflt st -v "$@" | fgrep "^$exp"
	then
		$BINdflt st -v "$@"
		$ERROR "Expected output '$exp'"
	fi

	$BINdflt st -D cs___end_of_block -d "$@" | grep "manber found a border" | wc -l
}


$INFO "Preparing big file ..."
# We need a file with some minimum number of manber blocks.
# I had "seq 10000000 10111111" but that gave only 3.
exp_manber=15
perl -e '$zero="\0" x 65536; for(0 .. 15) { print $_, $zero; }' > $file1
$BINdflt delay
touch .

$BINq ci -m1


$INFO "Doing copy."
cp -a $file1 $file2
$BINq cp $file1 $file2
if [[ `CountManber "....." $file2` == 0 ]]
then
	$SUCCESS "No hashing on unchanged copy."
else
	$ERROR "Manber-hashing on unchanged copy?"
fi

# change data at beginning, give another mtime
dd conv=notrunc of=$file2 if=$logfile bs=1 count=16 seek=123
touch -d yesterday $file2
if [[ `CountManber ".t.C." $file2` -gt $exp_manber ]]
then
	$SUCCESS "Hashing on changed copy."
else
	$ERROR "Changed copy not hashed?"
fi

# Revert to original, so commit doesn't have to send data.
cat $file1 > $file2
touch -d yesterday $file2

# Now commit, and look whether the manber hashes are done *locally*.
$BINdflt ci -m1 -d > $logfile
if grep 'ci__nondir.* doing local MD5.' $logfile
then
	$SUCCESS "OK, local MD5 done."
else
	$ERROR "no local MD5?"
fi

# Now test whether we really find changes soon.
dd conv=notrunc of=$file2 if=$logfile bs=1 count=16 seek=1
if [[ `CountManber ".t.C." $file2` -gt 1 ]]
then
	$ERROR "Committed copy hashed full, no manber hashes available."
else
	$SUCCESS "Manber hashes exist for unchanged copy."
fi

