tarback/tarback.sh

186 lines
6.3 KiB
Bash
Raw Normal View History

2023-02-17 02:35:13 +01:00
#!/bin/sh
2023-02-17 02:45:35 +01:00
set -eu
2023-02-17 02:35:13 +01:00
2023-06-08 16:47:31 +02:00
_="${XDG_DATA_HOME:=$HOME/.local/share}"
_="${XDG_DATA_DIRS:=/usr/local/share:/usr/share}"
_="${XDG_CONFIG_HOME:=$HOME/.config}"
_="${XDG_CONFIG_DIRS:=/etc}"
2023-02-17 02:35:13 +01:00
2023-02-17 02:45:35 +01:00
TARBACK_REMOTE_DEFAULT=
TARBACK_TRANSFORM_REMOTE_COMMAND_DEFAULT=
2023-06-07 22:24:44 +02:00
TARBACK_TRANSFORM_REMOTE_ARGUMENT_COMMAND_DEFAULT=
2023-02-17 02:35:13 +01:00
# shellcheck disable=SC2016 # disable variable not expanding hint
2023-06-07 13:21:53 +02:00
TARBACK_TAR_CREATE_COMMAND_DEFAULT='tar c -C "$1" .'
2023-02-17 02:35:13 +01:00
# shellcheck disable=SC2016 # disable variable not expanding hint
TARBACK_TAR_CREATE_ALT_COMMAND_DEFAULT='tar c -C "$(dirname "$1")" "$(basename "$1")"'
2023-06-08 00:15:13 +02:00
TARBACK_TAR_CREATE_USE_ALT_COMMAND_DEFAULT='[ ! -d "$1" ]'
2023-06-07 13:21:53 +02:00
# shellcheck disable=SC2016 # disable variable not expanding hint
TARBACK_TAR_EXTRACT_COMMAND_DEFAULT='tar x -C "$1"'
# shellcheck disable=SC2016 # disable variable not expanding hint
TARBACK_TAR_EXTRACT_ALT_COMMAND_DEFAULT='tar x -C "$(dirname "$1")"'
2023-06-08 00:15:13 +02:00
TARBACK_TAR_EXTRACT_USE_ALT_COMMAND_DEFAULT='[ ! -e "$1" ] && [ -d "$(dirname "$1")" ]'
2023-02-17 02:45:35 +01:00
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"
2023-06-08 16:47:31 +02:00
TARBACK_CONFIG_SEARCH_PATH_DEFAULT="$(dirname "$0"):$XDG_CONFIG_HOME:$XDG_CONFIG_DIRS"
2023-02-17 02:45:35 +01:00
2023-06-08 16:47:31 +02:00
_="${TARBACK_PLUGIN_SEARCH_PATH:=$TARBACK_PLUGIN_SEARCH_PATH_DEFAULT}"
_="${TARBACK_CONFIG_SEARCH_PATH:=$TARBACK_CONFIG_SEARCH_PATH_DEFAULT}"
TARBACK_PLUGIN_SEARCH_PATH="$(echo "$TARBACK_PLUGIN_SEARCH_PATH" | tr ':' '\n')"
TARBACK_CONFIG_SEARCH_PATH="$(echo "$TARBACK_CONFIG_SEARCH_PATH" | tr ':' '\n' | tac)"
# load configs
for config_dir in $TARBACK_CONFIG_SEARCH_PATH; do
config_file="$config_dir/tarback/config.sh"
[ ! -f "$config_file" ] && continue
. "$config_file"
done
2023-02-17 02:35:13 +01:00
2023-02-17 02:45:35 +01:00
# 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
2023-06-08 00:32:26 +02:00
_="${TARBACK_TRANSFORM_REMOTE_COMMAND:=$TARBACK_TRANSFORM_REMOTE_COMMAND_DEFAULT}"
_="${TARBACK_TRANSFORM_REMOTE_ARGUMENT_COMMAND:=$TARBACK_TRANSFORM_REMOTE_ARGUMENT_COMMAND_DEFAULT}"
_="${TARBACK_TAR_CREATE_COMMAND:=$TARBACK_TAR_CREATE_COMMAND_DEFAULT}"
_="${TARBACK_TAR_CREATE_ALT_COMMAND:=$TARBACK_TAR_CREATE_ALT_COMMAND_DEFAULT}"
_="${TARBACK_TAR_CREATE_USE_ALT_COMMAND:=$TARBACK_TAR_CREATE_USE_ALT_COMMAND_DEFAULT}"
_="${TARBACK_TAR_EXTRACT_COMMAND:=$TARBACK_TAR_EXTRACT_COMMAND_DEFAULT}"
_="${TARBACK_TAR_EXTRACT_ALT_COMMAND:=$TARBACK_TAR_EXTRACT_ALT_COMMAND_DEFAULT}"
_="${TARBACK_TAR_EXTRACT_USE_ALT_COMMAND:=$TARBACK_TAR_EXTRACT_USE_ALT_COMMAND_DEFAULT}"
_="${TARBACK_COMPRESSION:=$TARBACK_COMPRESSION_DEFAULT}"
_="${TARBACK_SPLIT:=$TARBACK_SPLIT_DEFAULT}"
_="${TARBACK_MERGE:=$TARBACK_MERGE_DEFAULT}"
2023-06-08 17:49:26 +02:00
_="${TARBACK_EXTENSION:=tar.$TARBACK_COMPRESSION}"
2023-02-17 02:35:13 +01:00
_transform_split_name() {
2023-06-08 17:49:26 +02:00
case "$1" in
*"$TARBACK_EXTENSION")
n="$1"
;;
*)
n="$1.$TARBACK_EXTENSION"
;;
esac
2023-02-17 02:35:13 +01:00
command_name="$(echo "$TARBACK_SPLIT" | awk '{print $1}')"
if echo "$command_name" | grep -q 'split'; then
2023-06-08 17:49:26 +02:00
n="$n.part"
2023-02-17 02:35:13 +01:00
fi
2023-06-08 17:49:26 +02:00
echo "$n"
2023-02-17 02:35:13 +01:00
}
_transform_remote() {
r="$1"
2023-06-07 22:24:44 +02:00
if [ -n "$TARBACK_TRANSFORM_REMOTE_COMMAND" ]; then
r="$("$TARBACK_TRANSFORM_REMOTE_COMMAND" "$r")"
fi
2023-06-07 22:24:44 +02:00
echo "$r"
}
_transform_argument() {
a="$1"
2023-06-07 22:24:44 +02:00
if [ -n "$TARBACK_TRANSFORM_REMOTE_ARGUMENT_COMMAND" ]; then
a="$("$TARBACK_TRANSFORM_REMOTE_ARGUMENT_COMMAND" "$a")"
fi
echo "$a"
}
2023-06-07 13:21:53 +02:00
_create() {
2023-02-17 02:35:13 +01:00
# $1 ... src
# $2 ... dst
src="$1"
dst="$(_transform_split_name "$2")"
2023-06-08 00:15:13 +02:00
if ! sh -c "$TARBACK_TAR_CREATE_USE_ALT_COMMAND" - "$src"; then
2023-06-07 13:21:53 +02:00
tarback_tar_create_command="$TARBACK_TAR_CREATE_COMMAND"
else
tarback_tar_create_command="$TARBACK_TAR_CREATE_ALT_COMMAND"
2023-06-07 13:21:53 +02:00
fi
tarback_tar_create_command="$(_transform_remote "$tarback_tar_create_command")"
2023-06-07 22:24:44 +02:00
$TARBACK_REMOTE sh -c "$tarback_tar_create_command" - "$(_transform_argument "$src")" \
2023-02-17 02:35:13 +01:00
| $TARBACK_COMPRESSION \
| $TARBACK_SPLIT "$dst"
}
2023-06-07 13:21:53 +02:00
create() {
_create "$@"
}
_restore() {
2023-02-17 02:35:13 +01:00
src="$(_transform_split_name "$1")"
dst="$2"
2023-06-08 00:15:13 +02:00
if ! sh -c "$TARBACK_TAR_EXTRACT_USE_ALT_COMMAND" - "$dst"; then
2023-06-07 13:21:53 +02:00
tarback_tar_extract_command="$TARBACK_TAR_EXTRACT_COMMAND"
2023-06-08 00:15:13 +02:00
else
tarback_tar_extract_command="$TARBACK_TAR_EXTRACT_ALT_COMMAND"
2023-06-07 13:21:53 +02:00
fi
tarback_tar_extract_command="$(_transform_remote "$tarback_tar_extract_command")"
2023-02-17 02:35:13 +01:00
$TARBACK_MERGE "$src"* \
| $TARBACK_COMPRESSION --decompress --stdout \
2023-06-07 22:24:44 +02:00
| $TARBACK_REMOTE sh -c "$tarback_tar_extract_command" - "$(_transform_argument "$dst")"
2023-02-17 02:35:13 +01:00
}
2023-06-07 13:21:53 +02:00
restore() {
_restore "$@"
}
2023-06-08 17:49:26 +02:00
short_options='P:'
2023-02-17 02:35:13 +01:00
while getopts "$short_options" arg; do
case "$arg" in
2023-06-08 17:49:26 +02:00
P)
2023-06-07 22:24:44 +02:00
for p in $(echo "$OPTARG" | tr ',' ' '); do
# source plugin file(s)
sourced=false
for loc in $TARBACK_PLUGIN_SEARCH_PATH; do
if [ -e "$loc/tarback/$p.sh" ]; then
# shellcheck disable=SC1090 # disable cannot follow source
old_short_options="$short_options"
old_arg="$arg"
old_OPTIND="$OPTIND"
old_OPTARG="$OPTARG"
2023-06-07 22:24:44 +02:00
. "$loc/tarback/$p.sh"
short_options="$old_short_options"
arg="$old_arg"
OPTIND="$old_OPTIND"
OPTARG="$old_OPTARG"
2023-06-07 22:24:44 +02:00
sourced=true
break
fi
done
if ! "$sourced"; then
echo "couldn't find plugin $p" >&2
exit 1
2023-02-17 02:35:13 +01:00
fi
done
;;
*)
echo "unknown option $1" >&2
2023-06-07 22:24:44 +02:00
#exit 1
2023-02-17 02:35:13 +01:00
;;
esac
done
shift $((OPTIND-1))
2023-02-17 02:35:13 +01:00
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