tarback/tarback.sh

127 lines
4 KiB
Bash
Executable file

#!/bin/sh
set -eu
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
TARBACK_REMOTE_DEFAULT=
TARBACK_TRANSFORM_REMOTE_COMMAND_DEFAULT=
# shellcheck disable=SC2016 # disable variable not expanding hint
TARBACK_TAR_CREATE_COMMAND_DEFAULT='tar c -C "$(dirname "$1")" "$(basename "$1")"'
# shellcheck disable=SC2016 # disable variable not expanding hint
TARBACK_TAR_EXTRACT_COMMAND_DEFAULT='tar x -C "$(dirname "$1")"'
TARBACK_COMPRESSION_DEFAULT='xz'
TARBACK_SPLIT_DEFAULT="split -b $((128*1024*1024)) -"
TARBACK_MERGE_DEFAULT='cat'
TARBACK_PLUGIN_SEARCH_PATH_DEFAULT="$(dirname "$0"):$XDG_DATA_HOME:$XDG_DATA_DIRS"
# example: TARBACK_REMOTE="ssh myuser@myserver" ./tarback ...
TARBACK_REMOTE="${TARBACK_REMOTE:-$TARBACK_REMOTE_DEFAULT}"
# maybe the command needs to be transformed before being passed to the
# remote command, see _transform_ssh_command for an example
TARBACK_TRANSFORM_REMOTE_COMMAND="${TARBACK_TRANSFORM_REMOTE_COMMAND:-$TARBACK_TRANSFORM_REMOTE_COMMAND_DEFAULT}"
TARBACK_TAR_CREATE_COMMAND="${TARBACK_TAR_CREATE_COMMAND:-$TARBACK_TAR_CREATE_COMMAND_DEFAULT}"
TARBACK_TAR_EXTRACT_COMMAND="${TARBACK_TAR_EXTRACT_COMMAND:-$TARBACK_TAR_EXTRACT_COMMAND_DEFAULT}"
TARBACK_COMPRESSION="${TARBACK_COMPRESSION:-$TARBACK_COMPRESSION_DEFAULT}"
TARBACK_SPLIT="${TARBACK_SPLIT:-$TARBACK_SPLIT_DEFAULT}"
TARBACK_MERGE="${TARBACK_MERGE:-$TARBACK_MERGE_DEFAULT}"
TARBACK_PLUGIN_SEARCH_PATH="${TARBACK_PLUGIN_SEARCH_PATH:-$TARBACK_PLUGIN_SEARCH_PATH_DEFAULT}"
TARBACK_PLUGIN_SEARCH_PATH="$(echo "$TARBACK_PLUGIN_SEARCH_PATH" | tr ':' '\n')"
_transform_split_name() {
command_name="$(echo "$TARBACK_SPLIT" | awk '{print $1}')"
if echo "$command_name" | grep -q 'split'; then
echo "$1.part"
else
echo "$1"
fi
}
_transform_ssh_command() {
command_name="$(echo "$TARBACK_REMOTE" | awk '{print $1}')"
if echo "$command_name" | grep -q 'ssh'; then
echo "'$1'"
else
echo "$1"
fi
}
_transform_remote() {
r="$1"
# TODO add more transformers
for t in _transform_ssh_command "$TARBACK_TRANSFORM_REMOTE_COMMAND"; do
[ -z "$t" ] && continue # skip empty transformers
r="$("$t" "$r")"
done
echo "$r"
}
create() {
# $1 ... src
# $2 ... dst
src="$1"
dst="$(_transform_split_name "$2")"
tarback_tar_create_command="$(_transform_remote "$TARBACK_TAR_CREATE_COMMAND")"
$TARBACK_REMOTE sh -c "$tarback_tar_create_command" - "$src" \
| $TARBACK_COMPRESSION \
| $TARBACK_SPLIT "$dst"
}
restore() {
src="$(_transform_split_name "$1")"
dst="$2"
tarback_tar_extract_command="$(_transform_remote "$TARBACK_TAR_EXTRACT_COMMAND")"
$TARBACK_MERGE "$src"* \
| $TARBACK_COMPRESSION --decompress --stdout \
| $TARBACK_REMOTE sh -c "$tarback_tar_extract_command" - "$dst"
}
short_options='p:'
while getopts "$short_options" arg; do
case "$arg" in
p)
# source plugin file
sourced=false
for loc in $TARBACK_PLUGIN_SEARCH_PATH; do
if [ -e "$loc/tarback/$OPTARG.sh" ]; then
# shellcheck disable=SC1090 # disable cannot follow source
. "$loc/tarback/$OPTARG.sh"
sourced=true
break
fi
done
if ! "$sourced"; then
echo "couldn't find plugin $OPTARG" >&2
exit 1
fi
shift 2
;;
*)
echo "unknown option $1" >&2
exit 1
;;
esac
done
case "$1" in
create)
shift
if [ "$#" -eq 2 ]; then
create "$@"
else
echo 'not enough arguments, expected 2: src dest' >&2
exit 1
fi
;;
restore)
shift
if [ "$#" -eq 2 ]; then
restore "$@"
else
echo 'not enough arguments, expected 2: src dest' >&2
exit 1
fi
;;
esac