diff --git a/arch-user/bin/backup b/arch-user/bin/backup new file mode 100755 index 0000000..688d7e5 --- /dev/null +++ b/arch-user/bin/backup @@ -0,0 +1,107 @@ +#!/bin/bash +set -e + +source ~/.config/workspace.conf +key_vol_path="/dev/disk/by-uuid/$BACKUP_KEY_VOL_UUID" +data_vol_path="/dev/disk/by-uuid/$BACKUP_DATA_VOL_UUID" + +data_mnt= +remote_open() { + data_mapper_name="$(lsblk "$data_vol_path" -no name --raw | awk 'NR==2')" + key_mnt="$(lsblk "$key_vol_path" -no mountpoint)" + if [ -z "$data_mapper_name" ]; then + echo unlocking data luks vol.. + if [ -z "$key_mnt" ]; then + echo mounting key vol.. + udisksctl mount -b "$key_vol_path" + key_mnt="$(lsblk "$key_vol_path" -no mountpoint)" + fi + echo decrypting key.. + gpg --batch --yes --output /tmp/backup-keyfile --decrypt "$key_mnt/keyfile.gpg" + udisksctl unlock -b "$data_vol_path" --key-file /tmp/backup-keyfile + data_mapper_name="$(lsblk "$data_vol_path" -no name --raw | awk 'NR==2')" + echo unlock ok, doing key cleanup + fi + rm -f /tmp/backup-keyfile + [ -n "$key_mnt" ] && udisksctl unmount -b "$key_vol_path" + data_mnt="$(lsblk "/dev/mapper/$data_mapper_name" -no mountpoint)" + if [ -z "$data_mnt" ]; then + echo mounting data vol.. + udisksctl mount -b "/dev/mapper/$data_mapper_name" + data_mnt="$(lsblk "/dev/mapper/$data_mapper_name" -no mountpoint)" + fi + echo open done +} + +remote_close() { + data_mapper_name="$(lsblk "$data_vol_path" -no name --raw | awk 'NR==2')" + if [ -n "$data_mapper_name" ]; then + echo unmounting data vol.. + udisksctl unmount -b "/dev/mapper/$data_mapper_name" + fi + udisksctl lock -b "$data_vol_path" # must be open here (fail if not) + echo close done +} + +declare -A repos +add_repos_local() { + while IFS= read -r -d $'\0'; do + repo_path="$REPLY" + [ ! -f "$repo_path/HEAD" ] && continue + repo_path="$(realpath "$(dirname "$repo_path")")" + repos["$repo_path"]=1 + done < <(find "$@" -type d -name .git -print0) +} + +add_repos_remote() { + cd "$1" + while IFS= read -r -d $'\0'; do + repo_path="$REPLY" + [ ! -f "$repo_path/HEAD" ] && continue + repo_path="/$(dirname "$repo_path")" + [[ ! " $(groups) " == *" $(echo "$repo_path" | cut -d'/' -f3) "* ]] && continue + repos["$repo_path"]=1 + done < <(find "." -type d -name '*.git' -printf '%P\0' 2>/dev/null) +} + +sync_one() { + local_path="$1" + remote_path="$2$1/$(basename "$1").git" + echo "$local_path <-> $remote_path" + remote_url="file:///$remote_path" + if [ ! -d "$local_path" ]; then + mkdir -p "$(dirname "$local_path")" + git clone "$remote_url" "$local_path" + else + cd "$local_path" + git add . + git diff-index --quiet HEAD || git commit -m autocommit || true + if [ ! -d "$remote_path" ]; then + mkdir -p "$(dirname "$remote_path")" + git clone --bare "file:///$1" "$remote_path" + else + git pull "$remote_url" + git push "$remote_url" + fi + fi +} + +sync_repos() { + for i in "${!repos[@]}"; do + sync_one "$i" "$1" + sync -f "$1" + done +} + +if [[ "$1" = "open" ]]; then + remote_open + exit 0 +fi + +remote_open +add_repos_remote "$data_mnt" +add_repos_local "/home/$(whoami)/dev" -maxdepth 2 +add_repos_local "/home/$(whoami)/know" -maxdepth 2 +sync_repos "$data_mnt" +remote_close +echo ALL OK