homesync 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #!/bin/sh
  2. usage() {
  3. cat <<EOF>&2
  4. Usage: ${0##*/}
  5. Sync home folder.
  6. Data is indexed to \$PERSONAL/index.
  7. The '~/.gnupg' folder can be backup up to a LUKS encrypted device.
  8. Options:
  9. -d PATH: where the data is looked up for indexing.
  10. -g DEVICE: Device where to sync ~/.gnupg.
  11. -p: Push upstream.
  12. EOF
  13. exit
  14. }
  15. OPT_UPDATE=false
  16. OPT_DEVICE=""
  17. OPT_DATAROOT=$(findmnt -n --fstab --output TARGET | grep ^/media/)
  18. [ -z "$OPT_DATAROOT" ] && OPT_DATAROOT=$(findmnt -n --list --output TARGET | grep ^/media/)
  19. while getopts ":hd:g:p" opt; do
  20. case $opt in
  21. h)
  22. usage
  23. exit ;;
  24. d)
  25. OPT_DATAROOT="$OPTARG" ;;
  26. p)
  27. OPT_UPDATE=true ;;
  28. g)
  29. OPT_DEVICE="$OPTARG" ;;
  30. \?)
  31. usage
  32. exit 1 ;;
  33. esac
  34. done
  35. shift $(($OPTIND - 1))
  36. [ -z "$PERSONAL" ] && echo >&2 'Set $PERSONAL to project directory.' && exit 1
  37. [ -z "$XDG_CONFIG_HOME" ] && XDG_CONFIG_HOME="$HOME/.config"
  38. [ -z "$XDG_DATA_HOME" ] && XDG_DATA_HOME="$HOME/.local/share"
  39. RED='\033[0;31m\033[1m'
  40. GREEN='\033[0;32m\033[1m'
  41. YELLOW='\033[0;33m\033[1m'
  42. BOLD='\033[0m\033[1m'
  43. NORMAL='\033[0m'
  44. section() {
  45. echo -e "$GREEN==> $@$NORMAL"
  46. }
  47. message() {
  48. echo -e "$YELLOW:: $@$NORMAL"
  49. }
  50. if [ -n "$OPT_DATAROOT" ]; then
  51. section Data index
  52. for i in "$OPT_DATAROOT"/*; do
  53. mkdir -p "$PERSONAL"/index/
  54. case "$i" in
  55. */locate.db|*/lost+found|*/Sync*)
  56. continue ;;
  57. */public)
  58. for j in "$i"/*; do
  59. case "$j" in
  60. */games|*/videos)
  61. for k in "$j"/*; do
  62. folder=$(basename $(dirname "$k"))
  63. mkdir -p "$PERSONAL"/index/"$folder"
  64. dataindex "$k" > "$PERSONAL"/index/"$folder"/"$(basename "$k")".index
  65. unset folder
  66. done ;;
  67. *)
  68. dataindex "$j" > "$PERSONAL"/index/"$(basename "$j")".index ;;
  69. esac
  70. done
  71. continue ;;
  72. */private)
  73. for j in "$i"/*; do
  74. mkdir -p "$PERSONAL"/index/private
  75. [ -e "$j"/.encfs*.xml ] && continue
  76. dataindex "$j" | gpg --encrypt --recipient mail@ambrevar.xyz \
  77. --output - > "$PERSONAL"/index/private/"$(basename "$j")".index.gpg
  78. done
  79. continue ;;
  80. esac
  81. done
  82. fi
  83. if [ -n "$OPT_DEVICE" ]; then
  84. section "GnuPG"
  85. sudo cryptsetup open "$OPT_DEVICE" gpg_backup
  86. MOUNT_POINT=/mnt
  87. # MOUNT_POINT=/media/ambrevar/gpg_backup
  88. sudo mount -o compress=zstd /dev/mapper/gpg_backup "$MOUNT_POINT"
  89. gpg --import "$MOUNT_POINT"/public/.gnupg/pubring.gpg
  90. sudo btrfs subvolume snapshot -r "$MOUNT_POINT"/public "$MOUNT_POINT"/.snapshots/public.$(date +%F_%R:%S) && \
  91. rm -rfv "$MOUNT_POINT"/public/.gnupg && \
  92. cp -av ~/.gnupg "$MOUNT_POINT"/public/
  93. sudo umount "$MOUNT_POINT"
  94. sudo cryptsetup close gpg_backup
  95. unset MOUNT_POINT
  96. fi
  97. if [ -e ~/.cache/mail/.notmuch ]; then
  98. section "Notmuch tags"
  99. notmuch restore --accumulate --input="$PERSONAL"/mail/notmuch.dump
  100. emacs --quick --batch --load=$HOME/.emacs.d/lisp/init-notmuch-sync.el \
  101. -f notmuch-dump-important-tags
  102. fi
  103. for i in "$PERSONAL"/games/stowed-saves/*; do
  104. section "Stowing '$i'"
  105. stow -t ~ -d "$(dirname "$i")" "$(basename "$i")"
  106. done
  107. project_status() {
  108. local path=$1
  109. local title=$2
  110. local body=$3
  111. [ -z "$body" ] && return
  112. if $CHANGED; then
  113. section "$path"
  114. CHANGED=false
  115. fi
  116. message "$title"
  117. echo "$body"
  118. }
  119. for i in ~/.password-store ~/common-lisp/* ~/projects/* ~/.local/share/emacs/site-lisp/* "$@"; do
  120. [ ! -d "$i/.git" ] && continue
  121. CHANGED=true
  122. push=$(git -C "$i" rev-parse --abbrev-ref --symbolic-full-name @{push} 2>&1)
  123. if [ $? -eq 0 ]; then
  124. unmerged=$(git -C "$i" log --oneline "$push"..)
  125. project_status "$i" "Unpushed commits" "$unmerged"
  126. else
  127. project_status "$i" "Unpushed commits" "No 'push' remote"
  128. fi
  129. project_status "$i" "Unstaged files" "$(git -C "$i" diff --name-only)"
  130. project_status "$i" "Staged files" "$(git -C "$i" diff --name-only --cached)"
  131. if $OPT_UPDATE && [ -n "$unmerged" ]; then
  132. message "Pushing"
  133. git -C "$i" push
  134. fi
  135. done