stash-cli 0.8.1

A local store for pipeline output and ad hoc file snapshots
Documentation
#!/usr/bin/env bash
set -euo pipefail

usage() {
  cat <<'EOF'
Usage:
  stash-copy user@host
  stash-copy user@host:/remote/stash

Copies stash data and attribute files from a remote machine into the local
stash repository.

Behavior:
  - local stash root uses STASH_DIR if set, otherwise ~/.stash
  - remote stash root uses the explicit path if provided
  - otherwise remote stash root uses STASH_DIR if set remotely, otherwise ~/.stash
  - only data/ and attr/ are copied
  - tmp/ is created locally and is not copied from the remote machine
EOF
}

if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
  usage
  exit 0
fi

if [[ $# -ne 1 ]]; then
  usage >&2
  exit 1
fi

if ! command -v rsync >/dev/null 2>&1; then
  echo "error: rsync is required" >&2
  exit 1
fi

if ! command -v ssh >/dev/null 2>&1; then
  echo "error: ssh is required" >&2
  exit 1
fi

src="$1"
remote_host="$src"
remote_root=""

if [[ "$src" == *:* ]]; then
  remote_host="${src%%:*}"
  remote_root="${src#*:}"
fi

if [[ -z "$remote_host" ]]; then
  echo "error: invalid remote spec" >&2
  exit 1
fi

local_root="${STASH_DIR:-$HOME/.stash}"
local_data="$local_root/data"
local_attr="$local_root/attr"

mkdir -p "$local_data" "$local_attr" "$local_root/tmp"

if [[ -z "$remote_root" ]]; then
  remote_root="$(
    ssh "$remote_host" '
      set -eu
      if [ -n "${STASH_DIR:-}" ]; then
        printf "%s\n" "$STASH_DIR"
      else
        printf "%s/.stash\n" "$HOME"
      fi
    '
  )"
fi

if [[ -z "$remote_root" ]]; then
  echo "error: could not determine remote stash path" >&2
  exit 1
fi

echo "Copying data from $remote_host:$remote_root/data/ to $local_data/"
rsync -a \
  -e ssh \
  "$remote_host:$remote_root/data/" \
  "$local_data/"

echo "Copying attributes from $remote_host:$remote_root/attr/ to $local_attr/"
rsync -a \
  -e ssh \
  "$remote_host:$remote_root/attr/" \
  "$local_attr/"

echo "Done."