#!/bin/bash

# Copyleft 2005 Konstantin L. Metlov <metlov@fzu.cz>
#
# No warranty of any kind is provided or can be implied. Use at your own risk !
# Study the scipt before usage.
#
# The usage is the following:
#
# 1. Install offmirror so that its executables are on the $PATH. Get it from 
# http://savannah.nongnu.org/projects/offmirror/ 
#
# 2. Copy this script into any directory.
#
# 3. Edit the parameters (framed below) to suit your needs.
#
# 4. Make symbolic links (preferably in the directory on the $PATH, 
# e.g. ~/bin/) named "arrive" and "depart" pointing to this script.
#
# 5. On each departure (even the first one): mount your flash and run "depart".
# This will pack the newly updated files for another end of the sneakernet.
#
# 6. Install the same script on the other end of the sneakernet, interchanging
# the LOCALPCNAME and REMOTEPCNAME parameters below.
#
# 7. On arrival: mount your flash and run "arrive". This will unpack the files
# you brought from the other end of the sneakernet and make your current system
# up to date. Along the way it will allow to see the changes and will ask 
# for your confirmation.
#
# Repeat steps 5 and 7 for each of your arrival and departure to keep your
# files in sync.
#
# It is possible to call "depart" twice to accumulate further changes 
# (for example,# if you prepared for departure, but then changed your mind 
# and introduced some additional modifications to your files.
#
# It is possible (but makes no sense) to call "arrive" twice. If the previous
# "arrive" was successful, the subsequent ones are essentially NOOP.
#
# When you plan to use this script for the first time, it is wise to make
# the initial copy of your files by another means (e.g. "rar", which has a nice 
# feature for making archives in small pieces). On the very first run "depart"
# does not pack any files, but just creates the file lists. The first
# invocation of "arrive" does the same. It means that if you run the first 
# "depart" on computer A, and the first "arrive" on computer B, only the 
# first "depart" on computer B will actually pack any files.
#
#
# --------------------------------------------------------------------------
# Please edit the parameters to suit your needs.
#
# The path, where your flash (or floppy) disk is mounted. It can be also a 
# sub-directory on the flash. The trailing slash is important ! Script does
# not check.
SNEAKERPATH="/mnt/mystick/mirror/"
#
# The name of the local and the remote computers. Each must be a single ASCII
# word, otherwise anything.
LOCALPCNAME="work"
REMOTEPCNAME="home"
#
# On another end of the sneaker net (e.g. home computer) the names need to be
# interchanged in the version of this script, installed there.
#LOCALPCNAME="home"
#REMOTEPCNAME="work"
#
# This is the root of the partially mirrored directory (e.g. home directory,
# as in my case). The trailing slash is important ! Script does not check.
DATAROOT="/home/metlov/"
#
# This is the list of sub-directories of $DATAROOT, which are to be mirrored.
# Each must end with a slash.
DATADIRS="metlov/ Common/personal/ archive/ mail/"
#
# This specifies which directories to exclude from any of the $DATADIRS. 
# e.g. EXCLUDES="-exclude=^Vortex"
# blank is a good default.
EXCLUDES=""
#
# end of parameters
# --------------------------------------------------------------------------

pushd $DATAROOT >/dev/null
case $0 in
    *arrive)
#       First we preview what is to be done
	PREVOPT="-verbose -dry-run"
	
	while true ; do
	
	    for CDIR in $DATADIRS ; do
		if [[ -n $PREVOPT ]] ; then
		    echo -n "Preview of an update for" $CDIR "..."
		else
		    echo -n "Unpacking an update into" $CDIR "..."
		fi
		SLNAME=${SNEAKERPATH}${CDIR//\//_}${LOCALPCNAME}.offlist.gz
		DLNAME=${SNEAKERPATH}${CDIR//\//_}${REMOTEPCNAME}.offlist.gz
		TARNAME=${SNEAKERPATH}to_${CDIR//\//_}${LOCALPCNAME}.tar.gz
		if [ -a $SLNAME -a -a $DLNAME -a -a $TARNAME ] ; then
		    offmirror-untar $PREVOPT $DLNAME $SLNAME $TARNAME
		    if [[ -z $PREVOPT ]] ; then
			rm -f $TARNAME
		    fi
		    echo " done."
		else
		    echo -n "[WARN:"
		    COMMA=""
		    if [[ ! -a $SLNAME ]] ; then 
			echo -n " local list"
			COMMA=","
		    fi
		    if [[ ! -a $DLNAME ]] ; then
			echo -n ${COMMA}" remote list"
			COMMA=","
		    fi
		    if [[ ! -a $TARNAME ]] ; then
			echo -n ${COMMA}" tar"
			COMMA=","
		    fi
		    echo " do not exist]"
		fi
	    done

	    if [[ -n $PREVOPT ]] ; then
		echo -n "Please review the changes and answer 'yes' if you want the merge: "
		read USERINPUT
		if [[ $USERINPUT == "yes" ]] ; then
		    PREVOPT=""
		else
		    echo "OK. aborting..."
		    break;
		fi
	    else
#           here we come if the files were already unpacked	    
		break;
	    fi
	done
	;;
    *depart)
#       First we build lists of files in each datadir
	for CDIR in $DATADIRS ; do
	    echo "Listing files in" $CDIR "..."
	    LNAME=${SNEAKERPATH}${CDIR//\//_}${LOCALPCNAME}.offlist.gz
	    offmirror-list $CDIR ${EXCLUDES} | gzip -1c >$LNAME
	done
#       Now we pack outgoing files if destination list exists
	for CDIR in $DATADIRS ; do
	    echo -n "Tarring updated files for" $CDIR "..."
	    SLNAME=${SNEAKERPATH}${CDIR//\//_}${LOCALPCNAME}.offlist.gz
	    DLNAME=${SNEAKERPATH}${CDIR//\//_}${REMOTEPCNAME}.offlist.gz
	    TARNAME=${SNEAKERPATH}to_${CDIR//\//_}${REMOTEPCNAME}.tar.gz
	    if [ -a $DLNAME ]; then
		offmirror-tar $SLNAME $DLNAME $TARNAME
		echo " done."
	    else
		echo " [WARN: no destination list]"
	    fi
	done
	;;
    *)
	echo "Please invoke this script either by 'arrive' or 'depart' links."
	;;
esac
popd>/dev/null
