commit 284075257591e01a56a9fefd3326df8cf5d47601 Author: Muhamed H. Asadi Date: Sun Sep 6 22:39:57 2026 +0330 Initial Commit diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..7a40439 --- /dev/null +++ b/backup.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Script directory and backups directory setup +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BACKUP_DIR="${SCRIPT_DIR}/backups" +mkdir -p "${BACKUP_DIR}" + +# Timestamp for archive name +TIMESTAMP="$(date +"%Y%m%d_%H%M%S")" +ZIP_FILENAME="konsole_backup_${TIMESTAMP}.zip" +ZIP_FILEPATH="${BACKUP_DIR}/${ZIP_FILENAME}" + +# Temporary staging directory +TEMP_DIR="$(mktemp -d)" +trap 'rm -rf "${TEMP_DIR}"' EXIT + +echo "=== Starting Konsole Configuration Backup ===" + +# Define target paths relative to HOME +CONFIG_PATHS=( + ".config/konsolerc" + ".local/share/konsole" + ".local/share/kxmlgui5/konsole" + ".config/konsole.notifyrc" + ".config/konsolesshconfig" +) + +COPIED_COUNT=0 + +for rel_path in "${CONFIG_PATHS[@]}"; do + src_path="${HOME}/${rel_path}" + dest_path="${TEMP_DIR}/${rel_path}" + + if [ -e "${src_path}" ]; then + mkdir -p "$(dirname "${dest_path}")" + cp -a "${src_path}" "${dest_path}" + echo " [+] Staged: ~/${rel_path}" + COPIED_COUNT=$((COPIED_COUNT + 1)) + else + echo " [-] Skipped (not found): ~/${rel_path}" + fi +done + +if [ "${COPIED_COUNT}" -eq 0 ]; then + echo "Error: No Konsole configuration files found to backup." + exit 1 +fi + +# Create zip file from staging area +echo "Creating backup archive: ${ZIP_FILENAME}..." +( + cd "${TEMP_DIR}" + zip -q -r "${ZIP_FILEPATH}" . +) + +echo "Backup successfully saved to: ${ZIP_FILEPATH}" + +# Retention Policy: keep at most 10 recent backup zip files +MAX_BACKUPS=10 + +mapfile -t BACKUP_FILES < <(find "${BACKUP_DIR}" -maxdepth 1 -name "konsole_backup_*.zip" | sort -r) + +TOTAL_BACKUPS="${#BACKUP_FILES[@]}" +if [ "${TOTAL_BACKUPS}" -gt "${MAX_BACKUPS}" ]; then + echo "Cleaning up older backups (keeping top ${MAX_BACKUPS})..." + for (( i=MAX_BACKUPS; i/dev/null; then + git diff --no-index --color "${dest_item}" "${item}" || true + else + diff -u --color=always "${dest_item}" "${item}" || true + fi + fi + fi + done < <(find "${source_dir}" -type f -print0) + + if [ "${changes_found}" -eq 0 ]; then + echo -e "\n\033[1;32mNo differences detected. Current configuration matches the backup exactly.\033[0m" + fi + echo "================================================================" + echo "" +} + +ARCHIVE_PATH="" + +# 1. Check positional argument +if [ $# -ge 1 ] && [ -n "$1" ]; then + ARCHIVE_PATH="$1" +# 2. Check if piped via stdin +elif [ ! -t 0 ]; then + read -r ARCHIVE_PATH || true +fi + +# 3. Interactive prompt / selection menu if no input given +if [ -z "${ARCHIVE_PATH}" ]; then + if [ ! -d "${BACKUP_DIR}" ]; then + echo "Error: No backups directory found at ${BACKUP_DIR}" + exit 1 + fi + + mapfile -t AVAILABLE_BACKUPS < <(find "${BACKUP_DIR}" -maxdepth 1 -name "konsole_backup_*.zip" | sort -r) + + if [ "${#AVAILABLE_BACKUPS[@]}" -eq 0 ]; then + echo "Error: No backup archives found in ${BACKUP_DIR}." + exit 1 + fi + + echo "Available Konsole backups:" + for i in "${!AVAILABLE_BACKUPS[@]}"; do + echo " [$((i + 1))] $(basename "${AVAILABLE_BACKUPS[$i]}")" + done + echo " [q] Quit" + + read -r -p "Select a backup to restore [1-${#AVAILABLE_BACKUPS[@]}]: " choice < /dev/tty + if [[ "${choice}" =~ ^[0-9]+$ ]] && [ "${choice}" -ge 1 ] && [ "${choice}" -le "${#AVAILABLE_BACKUPS[@]}" ]; then + ARCHIVE_PATH="${AVAILABLE_BACKUPS[$((choice - 1))]}" + else + echo "Aborted." + exit 0 + fi +fi + +# Expand relative paths +if [[ "${ARCHIVE_PATH}" != /* ]]; then + if [ -f "${BACKUP_DIR}/${ARCHIVE_PATH}" ]; then + ARCHIVE_PATH="${BACKUP_DIR}/${ARCHIVE_PATH}" + elif [ -f "./${ARCHIVE_PATH}" ]; then + ARCHIVE_PATH="$(pwd)/${ARCHIVE_PATH}" + fi +fi + +if [ ! -f "${ARCHIVE_PATH}" ]; then + echo "Error: Backup file not found: ${ARCHIVE_PATH}" + exit 1 +fi + +echo "Selected backup archive: ${ARCHIVE_PATH}" + +# Extract to temporary staging directory +TEMP_DIR="$(mktemp -d)" +trap 'rm -rf "${TEMP_DIR}"' EXIT + +unzip -q -o "${ARCHIVE_PATH}" -d "${TEMP_DIR}" + +# Interactive confirmation loop (allows viewing diffs) +while true; do + echo "" + echo "Konsole configuration files to be restored:" + find "${TEMP_DIR}" -mindepth 1 -maxdepth 3 | while read -r f; do + rel="${f#"${TEMP_DIR}"/}" + echo " - ~/${rel}" + done + echo "" + + if [ -t 0 ]; then + INPUT_SRC="/dev/stdin" + else + INPUT_SRC="/dev/tty" + fi + + read -r -p "Choose action: [r] Restore / [d] View Diff / [c] Cancel: " action < "${INPUT_SRC}" + + case "${action,,}" in + r|y|yes) + echo "Restoring configuration files..." + cp -a "${TEMP_DIR}/." "${HOME}/" + echo -e "\033[1;32mKonsole configurations restored successfully from $(basename "${ARCHIVE_PATH}")!\033[0m" + echo "Note: If Konsole is currently running, please restart it to apply all settings." + break + ;; + d|diff) + show_diff "${TEMP_DIR}" + ;; + c|q|n|no|cancel) + echo "Restoration cancelled." + exit 0 + ;; + *) + echo "Invalid option. Please enter 'r', 'd', or 'c'." + ;; + esac +done