#!/bin/sh
# $Id: archive,v 1.8 2003/07/30 10:53:02 tom Exp $
# archive, unarchive -- tar and compress source for archival storage
CDPATH=
command=`basename $0`

#-- parse command line options
set -- `getopt 'bBdhlrtuvzZ' $*`
if [ $? != 0 ]
then
	eval $0 -h
	exit 1
fi

debug="eval"
extract="-xp"
listonly=""
remove="n"
touch="n"
unarchive="n"
verbose=""
suffix="tgz"
compress="gzip"

while [ $# != 0 ]
do
	opt=$1
	shift
	case $opt in
	-b)	compress="bzip2";suffix="tar.bz2";;
	-B)	compress="bzip2";suffix="tbz";;
	-d)	debug="echo";;
	-l)	extract="-tv"; listonly="#";;
	-r)	remove="y";;
	-t)	touch="y";;
	-u)	unarchive="y";;
	-v)	verbose="v";;
	-z)	compress="gzip";suffix="tar.gz";;
	-Z)	compress="compress";suffix="tar.Z";;
	-h)	cat <<eof
Usage: $command [options] [archive_name]

Options:
  -b     use bzip2 and suffix .tar.bz2
  -B     use bzip2 and suffix .tbz
  -d     debug
  -l     list-only (don't extract files)
  -r     remove directory (leave tar in parent)
  -t     touch archive (latest file)
  -u     un archive
  -v     verbose (lists filenames)
  -z     use gzip and .tar.gz
  -Z     use compress and suffix .tar.Z

Parameters:
    archive_name   name for archive (default is current directory name)

By default, archive uses gzip to produce a gzip'd tar archive with suffix .tgz
eof
		exit;;
	--)	break;;
	-*)	eval $0 -h; exit 1;;
	esac
done

#-- if script is invoked as 'unarchive' do same as -u option
if [ $command = unarchive ]
then	unarchive="y"
fi

#-- figure out where we are
paths=`/bin/pwd`

#-- Provide default archive-name
if [ $# = 1 ]
then	dir="$1"
	arg="$1"
else	dir=$paths
	arg=.
fi

myfile=
SUF=".tar.gz .tgz .tar.bz2 .tbz .tar.Z"

# Try to decide what the parameter is, and deduce the archive-file and its
# directory:
if [ -f "$dir" ]
then
	myfile="$dir"
	dir=`echo "$dir" |sed -e 's@/[^/]*$@@'`
	if [ "$dir" = "$myfile" ]
	then
		dir=.
	fi
	cmp=`basename $myfile`
	for suf in $SUF none
	do
		tst=`basename $myfile $suf`
		if [ "$cmp" != "$tst" ]
		then
			break
		fi
	done
elif [ -d "$dir" ]
then
	for suf in $SUF none
	do
		tst=$dir/`basename $dir`$suf
		if [ -f "$tst" ]
		then
			myfile="$tst"
			break
		fi
	done
else
	echo "Neither a directory nor a file: $dir"
	exit 1
fi

if [ $unarchive = "y" ]
then
	if [ -z "$myfile" ]
	then
		echo "Cannot determine archive-file for $dir"
		exit 1
	fi

	case $suf in #(vi
	.tar.gz|.tgz) #(vi
		decomp="gzip -d"
		;;
	.tar.bz2|.tbz) #(vi
		decomp="bzip2 -d"
		;;
	.tar.Z) #(vi
		decomp="uncompress"
		;;
	*) #(vi
		echo "No archive found in ${dir}."
		exit 1
	esac

	if [ ! -w . -a ".$listonly" = "." ]
	then
		$debug "chmod u+w ."
		if [ $? != 0 ]
		then
			echo "archive: chmod error"
			exit 1
		fi
	fi

	if [ "$dir" != "$paths" ]
	then
		$debug cd "$dir"
		if [ "$debug" = echo ]
		then
			cd "$dir"
		fi
	fi
	myfile=`basename "$myfile"`

	#-- uncompress and untar
	if [ ".$listonly" = "." ]
	then
		if [ ! -w . ]
		then
			$debug chmod u+w .
		fi
		if [ -w .. ]
		then
			$debug	"mv $myfile .."
			if [ $? != 0 ]
			then
				echo "archive: mv error"
				exit 1
			fi
			myfile="../$myfile"
		fi
	fi

	$debug	"umask 0;$decomp -c $myfile | tar ${extract}${verbose}f - 2>&1"
	if [ $? != 0 ]
	then
		echo "archive: $decomp/tar error"
		exit 1
	fi

	#-- remove archive
	if [ ".$listonly" = "." ]
	then
		$debug	"rm -f $myfile"
	fi

elif [ ".$listonly" != "." ]
then
	echo "archive: -l option applies only to dearchiving"
	exit 1
else
	test -z "$myfile" && myfile="${dir}.$suffix"
	if [ -f "$myfile" ]
	then
		echo "Archive $myfile already present."
		exit 1
	fi
	myfile=`basename "$myfile"`

	if [ $arg = . ]
	then	all='`ls -A`'
	else	all='`ls -Ad '$arg'`'
	fi
	$debug	"tar -c${verbose}f - $all | $compress -c >../$myfile"
	if [ $? != 0 ]
	then
		echo "archive: tar error"
		exit 1
	fi

	#-- obtain date for "-t" option
	if [ $touch = "y" ]
	then
		last=`find $arg -type f -print`
		if [ ".$last" != "." ]
		then
			last=`ls -1t $last | head -1`
			$debug cpd $last ../$myfile
			if [ ".$verbose" = ".v" ]
			then
				echo last=$last
			fi
		fi
	fi

	#-- remove current sources
	$debug	"chmod u+w ."
	$debug	"find $arg -type d -exec chmod u+w {} \\;"
	$debug	"rm -rf $all"

	if [ $remove = "y" ]
	then	#-- move archive to parent, removing leaf
		leaf=`basename $paths`
		$debug	"cd ..;rmdir $leaf"
	else	#-- move archive back in
		$debug	"mv ../$myfile ."
		if [ $arg = . ]
		then
			$debug	"chmod -w ."
		fi
		if [ $touch = "y" ]
		then
			$debug cpd $myfile .
		fi
	fi
fi
