#!/bin/sh
# cpv file dest
# could extend with -r or copying multiple files

#define ln_or_cp function - try to hardlink and if that fails copy source to dest
ln_or_cp () {
  ln_or_cp_src="$1"
  ln_or_cp_dest="$2"
  ln "$ln_or_cp_src" "$ln_or_cp_dest" >/dev/null 2>&1
  if [ $? -eq 0 ]
  then
    return 0
  else
    cp -p "$ln_or_cp_src" "$ln_or_cp_dest"
    return $?
  fi
}
# end of funtion definitions


file="$1"
dest="$2"

if [ ! -f "$file" ]; then
    echo "Error: no such file "$file". Exiting."
    exit 1
fi

# if dest is a directory, add the source file name
if [ -d "$dest" ]; then
    dest=$dest/`basename $file`
fi

# if (the new) $dest is a directory, then just bail
if [ -d "$dest" ]; then
    echo "Error: destination file ($dest) is a directory. Exiting."
    exit 1
fi

# if no such file $dest or dest.~[0-9]*~ then just link or copy
# without adding version info
# THEN EXIT
if [ ! -f "$dest" ] && ! ls "$dest".~[0-9]*~ >/dev/null 2>&1
then
  ln_or_cp $file $dest
  res=$?
  if [ $res -eq 0 ]
  then
    msg_start="Added"
  else
    msg_start="Error: failed to add"
  fi
  echo "$msg_start $(basename $dest) to $(dirname $dest)"
  exit $res
fi


# find maximum version of dest
max=0
for vf in "$dest".~[1-9]*~
do vn=`echo $vf | sed -e 's/^.*\.~\([1-9][0-9]*\)~$/\1/'`
   if [ -f $dest.~$vn~ ]; then
       if [ $max -lt $vn ]; then
	   max=$vn
       fi
   fi
done

if [ $max -eq 0 ]; then		# no current versions
    mv $dest $dest.~1~		# change version to version 1
    new=2
else
    if cmp -q $dest $dest.~$max~ >/dev/null 2>&1
    then			# they're different
	max=`expr $max + 1`	# make newer version
	mv $dest $dest.~$max~
	new=`expr $max + 1`
    else			# dest and dest.~nn~ are equal so
	rm $dest		# delete dest leave old version behind
	new=`expr $max + 1`
    fi
fi

# make new version and link or copy it.
# If link or copy fails, then exit with error code
ln_or_cp $file $dest.~$new~
res=$?
if [ $res -eq 0 ]
then
  echo "Added $(basename $dest.~$new~) to $(dirname $dest.~$new~)"
else
  echo "Error: failed to add $(basename $dest.~$new~) to $(dirname $dest.~$new~)."
  exit $res
fi

# hardlink latest version to unversioned filename
rm -f $dest
ln $dest.~$new~ $dest
if [ $? -eq 0 ]
then
  msg_start="Linked"
else
  msg_start="Warning: failed to link"
fi
echo "$msg_start $(basename $dest) to $(basename $dest.~$new~) in $(dirname $dest)"

exit 0
