#!/bin/sh set -eu _="${XDG_DATA_HOME:=$HOME/.local/share}" _="${XDG_DATA_DIRS:=/usr/local/share:/usr/share}" _="${XDG_CONFIG_HOME:=$HOME/.config}" _="${XDG_CONFIG_DIRS:=/etc}" TARBACK_REMOTE_DEFAULT= TARBACK_TRANSFORM_REMOTE_COMMAND_DEFAULT= TARBACK_TRANSFORM_REMOTE_ARGUMENT_COMMAND_DEFAULT= # shellcheck disable=SC2016 # disable variable not expanding hint TARBACK_TAR_CREATE_COMMAND_DEFAULT='tar c -C "$1" .' # shellcheck disable=SC2016 # disable variable not expanding hint TARBACK_TAR_CREATE_ALT_COMMAND_DEFAULT='tar c -C "$(dirname "$1")" "$(basename "$1")"' TARBACK_TAR_CREATE_USE_ALT_COMMAND_DEFAULT='[ ! -d "$1" ]' # 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")"' TARBACK_TAR_EXTRACT_USE_ALT_COMMAND_DEFAULT='[ ! -e "$1" ] && [ -d "$(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" TARBACK_CONFIG_SEARCH_PATH_DEFAULT="$(dirname "$0"):$XDG_CONFIG_HOME:$XDG_CONFIG_DIRS" _="${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 # 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_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}" _="${TARBACK_EXTENSION:=tar.$TARBACK_COMPRESSION}" _transform_split_name() { case "$1" in *"$TARBACK_EXTENSION") n="$1" ;; *) n="$1.$TARBACK_EXTENSION" ;; esac command_name="$(echo "$TARBACK_SPLIT" | awk '{print $1}')" if echo "$command_name" | grep -q 'split'; then n="$n.part" fi echo "$n" } _transform_remote() { r="$1" if [ -n "$TARBACK_TRANSFORM_REMOTE_COMMAND" ]; then r="$("$TARBACK_TRANSFORM_REMOTE_COMMAND" "$r")" fi echo "$r" } _transform_argument() { a="$1" if [ -n "$TARBACK_TRANSFORM_REMOTE_ARGUMENT_COMMAND" ]; then a="$("$TARBACK_TRANSFORM_REMOTE_ARGUMENT_COMMAND" "$a")" fi echo "$a" } _create() { # $1 ... src # $2 ... dst src="$1" dst="$(_transform_split_name "$2")" if ! sh -c "$TARBACK_TAR_CREATE_USE_ALT_COMMAND" - "$src"; then tarback_tar_create_command="$TARBACK_TAR_CREATE_COMMAND" else tarback_tar_create_command="$TARBACK_TAR_CREATE_ALT_COMMAND" fi tarback_tar_create_command="$(_transform_remote "$tarback_tar_create_command")" $TARBACK_REMOTE sh -c "$tarback_tar_create_command" - "$(_transform_argument "$src")" \ | $TARBACK_COMPRESSION \ | $TARBACK_SPLIT "$dst" } create() { _create "$@" } _restore() { src="$(_transform_split_name "$1")" dst="$2" if ! sh -c "$TARBACK_TAR_EXTRACT_USE_ALT_COMMAND" - "$dst"; then tarback_tar_extract_command="$TARBACK_TAR_EXTRACT_COMMAND" else tarback_tar_extract_command="$TARBACK_TAR_EXTRACT_ALT_COMMAND" fi 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" - "$(_transform_argument "$dst")" } restore() { _restore "$@" } short_options='P:' while getopts "$short_options" arg; do case "$arg" in P) 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" . "$loc/tarback/$p.sh" short_options="$old_short_options" arg="$old_arg" OPTIND="$old_OPTIND" OPTARG="$old_OPTARG" sourced=true break fi done if ! "$sourced"; then echo "couldn't find plugin $p" >&2 exit 1 fi done ;; *) echo "unknown option $1" >&2 #exit 1 ;; esac done shift $((OPTIND-1)) 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