#!/bin/bash

# This test tries to simulate a master/local URL relationship, 
# ie. that there is a "master" URL (to be updated from) and a "local" URL 
# which tracks local modifications.
# 
# The "master" URL is set with a higher priority, so that it takes 
# precedence (binaries, and basic system); the local URL is just for 
# tracking the (machine-specific) local changes.
# 
# We use the working copies as follows:
#  1 for the master data (/trunk in the repository)
WC_MASTER=${WCBASE}1
REP_MASTER=$REPURL
#  2 for the local#1 data (/machineA)
WC_LOCAL1=${WCBASE}2
#  3 for the local#2 data (/machineB)
WC_LOCAL2=${WCBASE}3
#  4 as working copy for machine1
WC_MACHINE1=${WCBASE}4
#  5 as working copy for machine2
WC_MACHINE2=${WCBASE}5
#  6 as the base directory for the machine-specific repositories
REPD_1=${WCBASE}6/m1
REPD_2=${WCBASE}6/m2
REP_1=file://$REPD_1/trunk
REP_2=file://$REPD_2/trunk
# 
# So we need 5 working copies.
NUM_WC=6
#
# We take care to commit to a directory that doesn't yet exist in the 
# "local" repository.

# PS: is there an easier way for variable indirection?

logfile=$LOGDIR/038.multi-url

set -e
$PREPARE_CLEAN WC_COUNT=$NUM_WC > /dev/null
$INCLUDE_FUNCS

file1=conf1
file2=etc/conf2

####################################################
##### Prepare Master-data
####################################################
cd $WC_MASTER
mkdir bin
echo got ya > bin/ls
echo something > root-file
echo is_base > is_base
mkdir both
echo master_of_desaster > both/master
$BINq urls $REP_MASTER
$BINq ci -m "master"

####################################################
##### Prepare machine-local data.
####################################################
function makeLocal
{
  which=$1
	_rep="REP_$which"
	_rep=${!_rep}
	_repd="REPD_$which"
	_repd=${!_repd}

# Create repository for machine
	svnadmin create $_repd
	svn mkdir "$_rep" -m "mkdir loc-$which"

# Local data wc
	_loc="WC_LOCAL$which"
  cd "${!_loc}"
# We have to load, as the (wrong) /trunk was already set by prepare
	echo "$_rep" | $BINq urls load
# An empty revision 2 is needed. (1 is the mkdir above)
	$BINq ci -m empty	-d > $logfile #> /dev/null
	echo "Set URL $_rep for ${!_loc}"
	echo "$which here" > is_$which
	$BINq ci -m here	> /dev/null
	echo "is $which" > is_$which
	$BINq ci -m is	> /dev/null
# Make some empty revisions, so that the revision numbers surely disagree
  for a in a `seq 1 $(($RANDOM % 14))`
	do
	  $BINq ci -m $a > /dev/null
	done

	mkdir both
	echo $which > both/m-$which
	$BINq ci -m b

# Goto machine-WC
	_mac="WC_MACHINE$which"
  cd "${!_mac}"
# Set URLs with priorities
	echo "N:base,P:10,$REP_MASTER" | $BINq urls load
	$BINq urls "N:local,P:20,$_rep"
	echo "set N:base,P:10,$REP_MASTER and N:local,P:20,$_rep for ${!_mac}"
# Set commit-URL in config
	conf=`$BINdflt info | grep Conf-Path | cut -f2`
	if [[ "$conf" == "" ]] 
	then
	  $ERROR "Can't get Conf-Path for $which"
	fi

	echo "Got $conf as config path"
	echo commit-to=local > $conf/config
}
makeLocal 1
makeLocal 2

####################################################
##### Set data
####################################################
function Set
{
	which=$1
	num=$2
	where=$3
	delay=$4
  _p=$where$which
  cd "${!_p}"

# make and commit data.
  echo $which$num > $file1
	test -d etc || mkdir etc
	echo $which$num > $file2
# We generate a unix-mode here; maybe we should just take a random number?
	perl -e '($fn, $data, $nr)=@ARGV; chmod( 0600+unpack("C*",$data)-97+$nr, $fn ) || die $!' $file2 $num $which
	ls -la $file2
	$BINq ci -m "change local $which - $num" $delay
	echo ":: Set $which to $num"
}
Set 1 a WC_LOCAL
Set 2 a WC_LOCAL -odelay=yes

####################################################
##### Verify 1
####################################################
function Verify
{
	which=$1
	num=$2
	where=$3
  _p=$where$which
  update_parm=$4
  cd "${!_p}"

# get data
	$BINq up $update_parm

# verify data
	if [[ x`cat $file1`x`cat $file2`x == x${which}${num}x${which}${num}x ]]
	then
		$SUCCESS "Working copy local-$which correctly updated ($num)"
	else
		$ERROR_NB "Wrong data in $file2|$file2 ($num)"
		$ERROR "In "`pwd`", expected '$which$num'."
	fi

# verify mode
	ls -la $file2
  if ! $BINdflt info $file2 | egrep "Status:.*0x0 .unmodified"
	then
	  $ERROR "Wrong mode for ${!_p}$file2"
	fi
}
Verify 1 a WC_MACHINE
Verify 2 a WC_MACHINE

####################################################
##### Set/verify again
####################################################
Set 1 b WC_LOCAL
Set 2 b WC_LOCAL -odelay=yes
Verify 1 b WC_MACHINE
Verify 2 b WC_MACHINE

####################################################
##### Do changes on the machines
####################################################
$INFO "Committing locals from machines"
Set 1 t WC_MACHINE
Set 2 t WC_MACHINE -odelay=yes

####################################################
##### Verify the data in the repository
####################################################
Verify 1 t WC_LOCAL
Verify 2 t WC_LOCAL


$INFO "Doing partial update"
# Now do a single-URL-update
Set 1 g WC_LOCAL
# Has still to be at the old data.
Verify 1 t WC_MACHINE -ubase
Verify 1 g WC_MACHINE -ulocal
$SUCCESS "Partial update works"


$WARN "disabled, doesn't work with current subversion"
exit 0

# TODO: Get both ways of repository numbers - local higher than base, and 
# vice-versa.

# TODO: Master overlays one of the config files -> has to get to the 
# machines (even if changed locally??); if changed doesn't get committed to 
# master unless specified via commit-to.

# Checking correct creation of new directories.
cd $WC_MACHINE1
NEW1=etc/date.txt
NEW2=bin/date
date > $NEW1
date > $NEW2
$BINq ci -m "both dirs"
if [[ `svn ls $REP_1/$NEW1 | wc -l` == 1 &&
	`svn ls $REP_1/$NEW2 | wc -l` == 1 ]]
then
	$SUCCESS "New directory successfully created"
else
	$ERROR "New dirs not found!"
fi


# Try to specify a single URL; go to the empty revision.
$BINq up -u local@2
# When updating to a revision where a directory disappears, but it still 
# needed by other entries within, we don't know the mtime of the new 
# highest-priority URL (yet?).
# So we have to ignore the dir-mtime here.
$COMPARE -d $WC_MACHINE1/ $WC_MASTER/

# Now the is_1 file should appear.
$BINdflt up -u local@3 > $logfile
# The "." modified is allowed, and there's the "Updated ..." line.
if [[ `wc -l < $logfile` == [23] ]] &&
	grep -E "^N\.\.\. .* 7 .* is_1$" $logfile 
then
  $SUCCESS "Single-URL update ok"
else
	cat $logfile
  $ERROR "Single-URL update wrong?"
fi
# There's at least an empty revision afterwards.
if [[ `$BINdflt diff -u local@3 -r4` != "" ]]
then
  $ERROR "Empty single-URL diff wrong?"
fi
$BINdflt diff -u local -r4 > $logfile
if [[ `wc -l < $logfile` == 6 &&
	`grep -c is_1 $logfile` == 3 ]]
then
	$SUCCESS "Single-URL diff ok"
else
	cat $logfile
	$ERROR "Single-URL diff wrong"
fi

$SUCCESS "Master/Local-URL usage works."


# Now use the multi-URL setup to test "fsvs cat".
$BINq up

cd $WC_MACHINE1
for file in is_1 is_base bin/date
do
	md5l=`md5sum - < $file`
	md5r=`$BINdflt cat $file | md5sum -`
	if [[ "$md5l" != "$md5r" ]]
	then
		$ERROR_NB "Checksums on unmodified file $file wrong:"
		$ERROR_NB "local $md5l"
		$ERROR "versus repository $md5r"
	fi

	echo doesnt matter never mind > $file
	md5r=`$BINdflt cat $file | md5sum -`
	if [[ "$md5l" != "$md5r" ]]
	then
		$ERROR_NB "Checksums on modified file $file wrong:"
		$ERROR_NB "local was $md5l"
		$ERROR "versus repository $md5r"
	fi
done
$SUCCESS "fsvs cat works."


# Test -rX
export FSVS_COMMIT_TO=local
file=is_1

echo 1 > $file
md5_1=`md5sum < $file`
$BINq ci -m1 $file > $logfile
rev1=`grep "revision	" $logfile | tail -1 | cut -f2 -d"	" | cut -f1 -d" "` 

# Change size, to be sure that the change is seen
echo 22 > $file
md5_2=`md5sum < $file`
$BINq ci -m1 $file

if [[ `$BINdflt cat $file -r$rev1 | md5sum -` != $md5_1 ]]
then
	$ERROR "'cat -r$rev1 $file' wrong"
fi

if [[ `$BINdflt cat $file -rHEAD | md5sum -` != $md5_2 ]]
then
	$ERROR "'cat -rHEAD $file' wrong"
else
	$SUCCESS "cat -rX works, too."
fi


# Test data of special entries
ln -s link link
$BINq ci -m1 link

data=`$BINdflt cat link`
if [[ "$data" == "link link" ]]
then
	$SUCCESS "cat for symlinks ok."
else
	$ERROR "cat for symlinks wrong? '$data'"
fi
