From 622450574a75e7b6765733d64186640ef968b759 Mon Sep 17 00:00:00 2001
From: "Hahn Axel (hahn)" <axel.hahn@iml.unibe.ch>
Date: Tue, 25 May 2021 17:21:37 +0200
Subject: [PATCH] save current restore as legacy script

---
 restore_legacy.sh | 506 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 506 insertions(+)
 create mode 100755 restore_legacy.sh

diff --git a/restore_legacy.sh b/restore_legacy.sh
new file mode 100755
index 0000000..4fc0993
--- /dev/null
+++ b/restore_legacy.sh
@@ -0,0 +1,506 @@
+#!/bin/bash
+# ================================================================================
+#
+# RESTORE - interactive restore
+#
+# Restore duplicity backup data to a local directory.
+# Please notice: duplicity does not overwrite any dir or file. So the restore
+# path is different to the path of the backed up data.
+#
+# SYNTAX:
+# restore.sh [path-to-restore]
+#
+#   path-to-restore - optional
+#   default: none ... you get an interactive selection of backup sets
+#
+# --------------------------------------------------------------------------------
+# ah - Axel Hahn <axel.hahn@iml.unibe.ch>
+# ds - Daniel Schueler <daniel.schueler@iml.unibe.ch>
+#
+# 2016-11-17  ah,ds  v1.0
+# 2017-10-11  ah,ds  v1.1  added support for duplicity param --ssh-backend
+# 2018-08-27  ah,ds  v1.2  fix restore target with a given selection; handle '*' placeholder
+# 2019-06-05  ah,ds  v1.3  add custom cache dir
+# ================================================================================
+
+
+# --------------------------------------------------------------------------------
+# CONFIG
+# --------------------------------------------------------------------------------
+
+  # . `dirname $0`/inc_config.sh
+
+  . `dirname $0`/jobhelper.sh
+  . `dirname $0`/inc_bash.sh
+
+  STORAGE_BASEDIR=`_j_getvar ${STORAGEFILE} "storage"`
+
+  # check
+  if [ -z $STORAGE_BASEDIR ]; then
+    echo ERROR: missing config for backup target.
+    echo There must be an entry storage in ${STORAGEFILE}
+    exit 1
+  fi
+
+  # ----- read something from config files
+  RESTORE_BASEDIR=`_j_getvar ${STORAGEFILE} "restore-path"`
+  PASSPHRASE=`_j_getvar ${STORAGEFILE} "gnupg-passphrase"`
+  export PASSPHRASE
+
+  sFileSshPrivkey=`_j_getvar ${STORAGEFILE} "ssh-privatekey"`
+
+  sParams=
+
+  # task#1623 - fallback ssh backend for Debian 8
+  sSshBackend=`_j_getvar ${STORAGEFILE} "ssh-backend"`
+  if [ ! -z $sSshBackend ]; then
+    sParams="${sParams} --ssh-backend $sSshBackend"
+  fi
+
+  sFileSshPrivkey=`_j_getvar ${STORAGEFILE} "ssh-privatekey"`
+  if [ ! -z $sFileSshPrivkey ]; then
+    sParams="${sParams} --ssh-options="""-oIdentityFile=${sFileSshPrivkey}""" "
+  fi
+
+  # task#3046 - add custom cache dir
+  sCacheDir=`_j_getvar ${STORAGEFILE} "cachedir"`
+  if [ ! -z $sCacheDir ]; then
+    sParams="${sParams} --archive-dir=$sCacheDir"
+  fi
+
+  # ----- what to restore ...
+  sDir2restore= 
+  sRestoreItem=
+  sDate=`date +%Y-%m-%d`
+
+  # duplicity target
+  sTarget=
+
+# --------------------------------------------------------------------------------
+# FUNCTIONS
+# --------------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------
+# enter name of directory to restore; menu item
+# ----------------------------------------------------------------------
+function enterBackupDir(){
+
+  h2 "select a directory to be restored"
+
+  echo "This is a list of the directories from the backup configuration."
+  echo "Enter the full path"
+  echo
+
+  echo "Enter the full path; marked entries with (*) do not exist on this machine"
+  echo
+
+  sDirs="`j_getDirs2Backup`"
+  for mydir in $sDirs
+  do
+    if [ ! -d "$mydir" ]; then
+      color error
+      echo "$mydir (*)"
+      color reset
+    else
+      echo "$mydir"
+    fi
+  done
+
+  color input
+  echo -n "[$sDir2restore] >"
+  color reset
+  read myinput
+
+  setBackupDir "${myinput}"
+
+}
+
+# ----------------------------------------------------------------------
+# enter date to restore from; menu item
+# ----------------------------------------------------------------------
+function enterDate(){
+
+  h2 "edit date to restore"
+
+  echo "The acceptible time strings are intervals (like \"3D64s\"), w3-datetime"
+  echo "strings, like \"2002-04-26T04:22:01-07:00\" (strings like"
+  echo "\"2002-04-26T04:22:01\" are also acceptable - duplicity will use the"
+  echo "current time zone), or ordinary dates like 2/4/1997 or 2001-04-23"
+  echo "(various combinations are acceptable, but the month always precedes"
+  echo "the day)."
+  echo
+  echo "today in YYYY-MM-DD: `date +%Y-%m-%d`"
+  echo 
+  color input
+  echo -n "[$sDate] >"
+  color reset
+  read sNewDate
+  if [ ! -z $sNewDate ]; then
+    sDate=$sNewDate
+  fi
+}
+
+# ----------------------------------------------------------------------
+# enter relative path to restore; menu item
+# ----------------------------------------------------------------------
+function enterRestoreitem(){
+
+  h2 "set restore item (path)"
+
+  echo "enter a relative path behind ${sDir2restore}/"
+  echo "empty means: all data"
+  echo 
+  color input
+  echo -n "[$sRestoreItem] >"
+  color reset
+  read sNewsRestoreItem
+
+  if [ ! -z $sNewsRestoreItem ]; then
+    sRestoreItem=$sNewsRestoreItem
+    setVars
+  fi
+  getRemoteFiles
+}
+
+
+# ----------------------------------------------------------------------
+# search a file in backup; menu item
+# ----------------------------------------------------------------------
+function searchFile(){
+  h2 "search a file in backup --time $sDate"
+
+  echo "Enter something that was backuped from ${sDir2restore}"
+  echo "searchtext matches anywhere in filename or path - it is a grep grep in"
+  echo "duplicity list-current-files --time $sDate [target]"
+  echo "Press just Return to exit"
+  echo
+  color input
+  echo -n "search for >"
+  color reset
+  read sSearch
+  if [ ! -z $sSearch ]; then
+    getRemoteFiles $sSearch
+  fi
+}
+
+# ----------------------------------------------------------------------
+# verify backup set with local files; menu item
+# ----------------------------------------------------------------------
+function verify(){
+
+  h2 "verify"
+
+  echo duplicity verify ${sParams} ${sTarget} -v4 $sDir2restore
+  color cmd
+  duplicity verify ${sParams} ${sTarget} -v4 $sDir2restore
+  fetchrc
+  color reset
+
+}
+
+# ----------------------------------------------------------------------
+# show file changes in backupsets; menu item
+# work in progress ... I don't know how to match a file...
+# ----------------------------------------------------------------------
+function showFilechanges(){
+
+  tmpcache=~/.cache/duplicity-changes-${sSafeName}.txt
+
+  h2 "show file changes"
+
+  egrep "\ \ (changed|deleted|new)\ \ " `fgrep -l "Localdir ${sDir2restore}" ~/.cache/duplicity/*/*.manifest` >$tmpcache
+  # ls -l $tmpcache
+  # head $tmpcache
+ 
+  echo "I hope you made a search first"
+  echo "Enter filename with complete path that was backuped from ${sDir2restore}"
+  echo "Press just Return to exit"
+  echo
+  color input
+  echo -n "search for >"
+  color reset
+  read sSearch
+  if [ ! -z "${sSearch}" ]; then
+    echo  grep "${sSearch}"
+    color cmd
+    # duplicity collection-status --file-changed "`basename ${sSearch}`" ${sParams} ${sTarget}/`dirname "${sSearch}"`
+    cat $tmpcache | grep "${sSearch}" | while read line
+    do
+       sManifest=`echo $line | cut -f 1 -d ":"`
+
+       # duplicity-inc.20161111T152106Z.to.20161111T152141Z.manifest
+       sTime=`basename "${sManifest}" | cut -f 2 -d "."` 
+       sOut=`echo $line | cut -f 2- -d ":"`
+
+       echo $sTime $sOut | sed "s#new#new    #" 
+    done | sort
+    echo
+    color reset
+  fi
+}
+
+# ----------------------------------------------------------------------
+# show remote volumes with incremental and full backups
+# ----------------------------------------------------------------------
+function getRemoteVolumes(){
+  tmpoutVolumes=/tmp/outvolumelist_$$
+
+  h2 "volumes for $sDir2restore"
+
+  echo duplicity collection-status ${sParams} ${sTarget}
+  color cmd
+  duplicity collection-status ${sParams} ${sTarget} | tee -a $tmpoutVolumes
+  fetchrc
+  color reset
+  echo
+
+  if [ `cat $tmpoutVolumes | egrep "(Full|Incremental)" | wc -l` -eq 0 ]; then
+    color error
+    echo "ERROR: no backup sets were found for directory [$sDir2restore]"
+    echo
+    color reset
+    sDir2restore=
+    setVars
+  else
+    color ok
+    echo "OK,  `cat $tmpoutVolumes | grep "Full" | wc -l` Full and  `cat $tmpoutVolumes | grep "Incremental" | wc -l` incremental backups"
+    color reset
+  fi
+
+  rm -f $tmpoutVolumes
+
+}
+
+# ----------------------------------------------------------------------
+# list files from backupset
+# ----------------------------------------------------------------------
+function getRemoteFiles(){
+  iLines=50
+  tmpout=/tmp/outfilelist_$$
+  sSearch=$1
+  if [ -z $sSearch ]; then
+    sSearch="^...\ ...\ ..\ ........\ ....\ $sRestoreItem"
+  fi
+  echo
+  echo
+  echo --- files ... filtered for date [$sDate] by [$sSearch]
+  echo duplicity list-current-files --time $sDate ${sParams} ${sTarget} 
+  color cmd
+  duplicity list-current-files --time $sDate ${sParams} ${sTarget} 2>&1 | grep "$sSearch" | tee -a $tmpout | head -$iLines
+  fetchrc
+  color reset
+  if [ `cat $tmpout | wc -l` -eq 0 ]; then
+    color error
+    echo ERROR: your file does not match ... try another time ... or another search string
+    color reset
+  else
+    echo ... max $iLines lines ... maybe the output was cut
+    echo
+    if [ -z $1 ]; then
+      echo
+      doRestoreDryRun
+      echo
+      echo
+    fi
+  fi
+  rm -f $tmpout
+}
+
+# ----------------------------------------------------------------------
+# set backup dir .. called when using cli parameter or enterBackupDir
+# param  string   full path of a directory to retore
+# ----------------------------------------------------------------------
+function setBackupDir(){
+  if [ ! -z $1 ]; then
+    sDirs2Backup="`j_getDirs2Backup`"
+    bFound=0
+    for mydir in ${sDirs2Backup}
+    do
+      if [ "${mydir}" = "${1}" ]; then
+        bFound=1
+      fi
+    done
+
+    if [ $bFound -eq 0 ]; then
+      color error
+      echo
+      echo "WARNING: seems to be wrong ... "
+      echo "At the moment I restore only known targets."
+      color reset
+
+      # TODO: if we want to retore other backup sets of other servers
+      # we cannot be as strict
+
+    else
+
+      sDir2restore=$1
+      setVars
+      getRemoteVolumes
+
+    fi
+  fi
+}
+
+# ----------------------------------------------------------------------
+# internal: set variables for target path and backup set to make 
+# duplicity calls
+# ----------------------------------------------------------------------
+function setVars(){
+  
+  sSafeName=`j_getSafename "$sDir2restore"`
+  sTarget=`j_getFullTarget "$sDir2restore"`
+
+  sRestorepath="${RESTORE_BASEDIR}/${sSafeName}"
+  if [ ! -z $sRestoreItem ]; then
+    echo ${sRestoreItem} | grep '\*' >/dev/null
+    if [ $? -eq 0 ]; then
+      sRestoreItem=`dirname $sRestoreItem | sed 's#^\.##'`
+      color error
+      echo ERROR: using a placeholder is not allowed. Using the directory above.
+      echo [$sRestoreItem]
+      color reset
+    fi
+
+    sRestorepath="${sRestorepath}/${sRestoreItem}"
+  fi
+}
+
+# ----------------------------------------------------------------------
+# restore dry run ... called in getRemoteFiles
+# ----------------------------------------------------------------------
+function doRestoreDryRun(){
+  echo "--- dry run"
+  echo duplicity restore --dry-run --file-to-restore "$sRestoreItem" --time $sDate ${sParams} ${sTarget} ${sRestorepath}
+  color cmd
+  duplicity restore --dry-run --file-to-restore "$sRestoreItem" --time $sDate ${sParams} ${sTarget} ${sRestorepath}
+  fetchrc
+  color reset
+
+}
+
+# ----------------------------------------------------------------------
+# restore and finish the script; menu item
+# ----------------------------------------------------------------------
+function doRestore(){
+  mkdir -p $sRestorepath
+
+  h2 "RESTORE"
+
+  echo duplicity restore --file-to-restore "$sRestoreItem" --time $sDate ${sParams} ${sTarget} ${sRestorepath}
+  color cmd
+  duplicity restore --file-to-restore "$sRestoreItem" --time $sDate ${sParams} ${sTarget} ${sRestorepath}
+  fetchrc
+  color reset
+  echo
+  echo
+  echo Restore is finished.
+  echo Have look to the output above.
+  echo "The restore path has `find ${sRestorepath} -type f | wc -l` files (`du -hs ${sRestorepath} | awk '{ print $1 }'`)"
+  echo 
+  echo find ${sRestorepath}
+
+  echo
+  exit 0
+}
+
+
+# --------------------------------------------------------------------------------
+# MAIN
+# --------------------------------------------------------------------------------
+
+h1 "RESTORE - GET FILES FROM STORAGE"
+
+# ----- Check requirements
+
+  j_requireUser "root"
+  j_requireBinary "duplicity"
+
+# ----- set a directory to restore to have a useful initial point
+
+  setBackupDir $1
+  if [ -z $sDir2restore ]; then
+    enterBackupDir
+  fi
+
+# ----- menu and loop
+
+  while true
+  do
+
+    h1 "Restore :: Menu"
+
+    # getRemoteVolumes
+    # getRemoteFiles
+
+    echo
+    echo " D - directory to restore: $sDir2restore"
+    echo " T - time                : $sDate"
+    echo " W - what to restore     : $sRestoreItem"
+    echo
+    echo " C - show file changes"
+    echo " S - search file"
+    echo " V - verify"
+    echo " B - Bash (Shell)"
+    echo
+    echo " R - start restore"
+    echo
+    echo "     retore from         : $sTarget"
+    echo "     retore to           : $sRestorepath"
+    echo -n "                           "
+    ls -d $sRestorepath >/dev/null 2>&1
+    if [ $? -eq 0 ]; then
+      color error
+      echo "WARNING: directory already exists! Backup will fail."
+      color reset
+    else
+      echo "OK, it does not exist yet"
+    fi
+    echo
+    echo " X - exit"
+    echo
+
+    color input
+    echo -n "Select (not case sensitive) --> "
+    color reset
+    read action
+    echo
+
+    case $action in
+      d|D)
+        enterBackupDir
+        ;;
+      t|T)
+        enterDate
+        ;;
+      c|C)
+        showFilechanges
+        ;;
+      s|S)
+        searchFile
+        ;;
+      v|V)
+        verify
+        ;;
+      b|B)
+        echo type exit to return...
+        export PS1="[`basename $0` \u@\h \w]\$ "
+        bash
+        ;;
+      w|W)
+        enterRestoreitem
+        ;;
+      r|R)
+        doRestore
+        ;;
+      x|X)
+        exit 0
+        ;;
+      *)
+        echo "Try again"
+    esac
+
+
+  done
+
+
+# --------------------------------------------------------------------------------
-- 
GitLab