#!/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 "$1" .' # shellcheck disable=SC2016 # disable variable not expanding hint TARBACK_TAR_CREATE_COMMAND_FILE_DEFAULT='tar c -C "$(dirname "$1")" "$(basename "$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_COMMAND_FILE_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_CREATE_COMMAND_FILE="${TARBACK_TAR_CREATE_COMMAND_FILE:-$TARBACK_TAR_CREATE_COMMAND_FILE_DEFAULT}" TARBACK_TAR_EXTRACT_COMMAND="${TARBACK_TAR_EXTRACT_COMMAND:-$TARBACK_TAR_EXTRACT_COMMAND_DEFAULT}" TARBACK_TAR_EXTRACT_COMMAND_FILE="${TARBACK_TAR_EXTRACT_COMMAND_FILE:-$TARBACK_TAR_EXTRACT_COMMAND_FILE_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")" if [ -d "$src" ]; then tarback_tar_create_command="$TARBACK_TAR_CREATE_COMMAND" else tarback_tar_create_command="$TARBACK_TAR_CREATE_COMMAND_FILE" fi tarback_tar_create_command="$(_transform_remote "$tarback_tar_create_command")" $TARBACK_REMOTE sh -c "$tarback_tar_create_command" - "$src" \ | $TARBACK_COMPRESSION \ | $TARBACK_SPLIT "$dst" } create() { _create "$@" } _restore() { src="$(_transform_split_name "$1")" dst="$2" if [ ! -e "$dst" ] && [ -d "$(dirname "$dst")" ]; then tarback_tar_extract_command="$TARBACK_TAR_EXTRACT_COMMAND_FILE" else tarback_tar_extract_command="$TARBACK_TAR_EXTRACT_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" - "$dst" } restore() { _restore "$@" } 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