#!/usr/bin/env bash
import core/linux-helper
## Setup, configure, backup my personal linux systems
#
# Aims to have a single folder to contain all backup-able items
##
# Set up a new system from my setup source files. Do this AFTER a restore
#
#
function linux_setup(){
# - prompt for system/user home dir
# - prompt for system files directory (source of truth)
# - prompt for Documents parent directory
# - Contains 'Documents', 'Pictures', and so on. We will make symlinks
# - prompt for home_symlinks directory where each immediate child is directly symlinked into home dir
# - prompt for scripts directory of scripts to execute after built-in system setup
# - copy my firefox profile
# - copy spacevim's init.toml file
# - prompt if old home dirs ('documents', etc) should be deleted or moved
# - backup home dir (for symlinking)
# - target home directory (on the system we're setting up)
# - Execution
# - execute pre-setup scripts
# - create symlinks to each file in `home_symlinks` dir
# - remove existing `Documents` & other dirs if empty. Move otherwise
# - symlink to own documents & pictures directories
# - execute post-setup scripts
homeDir=""
rootDir=""
if [[ -f ~/.tlfsetup ]];then
source ~/.tlfsetup
fi
while [[ ! -d "$homeDir" ]]; do
prompt "Absolute path to your home directory:" homeDir
done
while [[ ! -d "$rootDir" ]]; do
prompt "Absolute path to all your files:" rootDir
done
echo "# Enter paths relative to '$rootDir'"
echo ""
## Where 'Documents' and 'Pictures' & the like go
filesDir="$rootDir/Files/"
while [[ ! -d "$filesDir" ]]; do
prompt "Relative path to Files dir (contains Documents/, Pictures/, etc):" filesDir
filesDir="$rootDir/$filesDir"
done
## System Dir, where setup files are located
systemDir="$rootDir/Linux"
while [[ ! -d "$systemDir" ]]; do
prompt "Relative path to system dir" systemDir
systemDir="$rootDir/$systemDir"
done
echo "Root Paths Found"
echo ""
echo "----"
echo "# Enter paths relative to '$systemDir'"
echo ""
## Home Symlinks. link ~/FILE to $homelinkDir/* (including directories)
homeLinkDir="$systemDir/homelink"
while [[ ! -d "$homeLinkDir" ]]; do
prompt "Relative path to homelinks dir:" homeLinkDir
homeLinkDir="$systemDir/$homeLinkDir"
done
## Home Symlinks. link ~/FILE to $homelinkDir/* (including directories)
systemFilesDir="$systemDir/files"
while [[ ! -d "$systemFilesDir" ]]; do
prompt "Relative path to system files dir (requires special setup by scripts):" homeLinkDir
systemFilesDir="$systemDir/$systemFilesDir"
done
## Where to put files that we (re)move during setup
trashDir="$systemDir/setup_trash/"
while [[ ! -d "$trashDir" ]]; do
prompt "Relative path to setup trash dir:" trashDir
trashDir="$systemDir/$trashDir"
done
trashDir="$trashDir/$(date +%d-%m-%Y-%H:%M)/"
mkdir "$trashDir"
## Setup Dir, to load scripts & packages to install & such
setupDir="$systemDir/setup/"
while [[ ! -d "$setupDir" ]]; do
prompt "Relative path to setup dir, to load scripts & info from: " setupDir
postSetupScriptsDir="$systemDir/$setupDir"
done
## Source directory for scripts & things
sourceDir="$systemDir/src/"
while [[ ! -d "$sourceDir" ]]; do
prompt "Relative path to source dir, where your scripts will load from:" sourceDir
sourceDir="$systemDir/$sourceDir"
done
echo "System Paths Found"
echo ""
###
##
#
##### done getting paths
##### start doing actual setup
#
##
###
preSetupScript="$setupDir/pre-setup.bash"
if [[ -f "$preSetupScript" ]];then
step "Run pre Setup Script?" source "$setupDir/pre-setup.bash"
fi
step "Write symlinks to files. " write_home_symlinks_to "$homeLinkDir" "$homeDir" "$trashDir"
step "Write symlinks to Documents, Pictures, etc" write_home_symlinks_to "$filesDir" "$homeDir" "$trashDir"
if [[ -f "$setupDir/dnf-remove" ]];then
dnfRemoveList="$(cat "$setupDir/dnf-remove")"
prompt=$(echo -e "\nRemove ${dnfRemoveList[@]}")
step "$prompt" sudo dnf remove ${dnfRemoveList[@]}
fi
if [[ -f "$setupDir/dnf-install" ]];then
dnfInstallList="$(cat "$setupDir/dnf-install")"
prompt=$(echo -e "\nInstall ${dnfInstallList[@]}")
step "$prompt" sudo dnf install ${dnfInstallList[@]}
fi
postSetupScript="$setupDir/post-setup.bash"
if [[ -f "$postSetupScript" ]];then
step "Run Post Setup Script?" source "$setupDir/post-setup.bash"
fi
step_run
}
##
# Restore backup files from backup drive onto system drive
#
function linux_restore(){
echo "Being run from '$(pwd)'"
echo "Use absolute paths"
# Executing it for backup would
# - prompt for backup path
# - prompt for target restore path
# - Ask if we should do a dry run
# - ask if we should --delete on restore
# - The backup
# - Delete files that don't exist in source of truth
# - overrwrite existing files unless they're the same (how do I do that with rsync?)
# - execute 'pre-restore' scripts
# - rsync everything
# - execute 'post-backup' scripts
# - decompress git folders
# - Write a .last_backup file that shows when the backup was performed
backupDir=""
restoreDir=""
# backupDir="/path/to/test/backup/dir/"
# restoreDir="/path/to/test/source/dir"
# backupDir="/mnt/BackupDrive/a/"
# restoreDir="/home/reed/.disk"
while [[ ! -d "$backupDir" ]]; do
prompt "The directory to restore your files from" backupDir
done
backupDir="$backupDir/"
# Location to restore to
while [[ ! -d "$restoreDir" ]]; do
prompt "Enter path to restore files into" restoreDir
done
restoreDir="${restoreDir%/}"
prompt_yes_or_no "Delete files in target directory, if they're not found in the backup?" doDelete
prompt_yes_or_no "Overwrite files in target directory?" doOverwrite
prompt_yes_or_no "Do dry run?" doDryRun
echo "Restoring from '$backupDir' into '$restoreDir'"
## --archive equals -rlptgoD or:
# --recursive # recurse into directories
# --links # copy symlinks as symlinks
# --perms # preserve permissions
# --times # preserve modification times
# --group # preserve group
# --owner # preserve owner
# -D is --devices --specials # "preserve device files" & "preserve special files" respectively
## Others:
# --hard-links preserve hard links (probably not needed)
# --executability preserve executability
# --acls preserve ACLs (implies --perms) (see `info ACL`. I think this is needed for sticky bits to work? idk)
rsync_args=(--verbose --archive --hard-links --executability --acls --progress)
if [[ $doDelete ]];then
rsync_args+=(--delete)
echo "Delete files not in backup!"
fi
if [[ ! $doOverwrite ]];then
rsync_args+=(--ignore-existing)
echo "Overwrite files!"
fi
if [[ $doDryRun ]]; then
rsync_args+=(--dry-run)
echo "Do dry run!"
fi
echo "Restore into dir: $restoreDir"
echo "Backup Dir: $backupDir"
read -p "[enter] continue "
rsync "${rsync_args[@]}" "$backupDir" "$restoreDir"
run_decompress_git "$restoreDir"
postRestoreScript="$restoreDir/post-restore.bash"
if [[ -f "$postRestoreScript" ]];then
source "$postRestoreScript"
fi
echo -e "\nShould be all done!!\n"
}
##
# Run a backup from system drive to external drive
#
function linux_backup(){
echo "Being run from '$(pwd)'"
echo "Use absolute paths"
# Executing it for backup would
# - prompt for target backup path
# - prompt for source of truth
# - ask if git folders should be backed up
# - Ask if we should do a dry run
# - The backup
# - Delete files that don't exist in source of truth
# - overrwrite existing files unless they're the same (how do I do that with rsync?)
# - execute 'pre-backup' scripts
# - compress git folders
# - rsync compressed git folders
# - rsync everything else except ignored directories (ignore git folders)
# - execute 'post-backup' scripts
# - decompress git folders
# - Write a .last_backup file that shows when the backup was performed
sourceDir=""
backupDir=""
# sourceDir="/path/to/test/source/dir/"
# backupDir="/path/to/test/backup/dir"
while [[ ! -d "$sourceDir" ]]; do
prompt "The directory to backup" sourceDir
sourceDir="$sourceDir/"
done
excludesListFile=""
useExcludesFile=true
while [[ ! -f "$excludesListFile" ]]; do
prompt "Enter relative path to your rsync excludes file (within '$sourceDir') or 's' to skip" excludesListRelFile
if [[ "$excludesListRelFile" == "s" ]];then
useExcludesFile=false
break;
fi
excludesListFile="$sourceDir/$excludesListRelFile"
done
# Location to backup sourcedir to
while [[ ! -d "$backupDir" ]]; do
prompt "Enter path to backup dir" backupDir
backupDir="${backupDir%/}"
done
prompt_yes_or_no "Backup .git folders?" doBackupGit
prompt_yes_or_no "Do dry run?" doDryRun
echo "Backing up from '$sourceDir' into '$backupDir'"
preBackupScript="$sourceDir/pre-backup.bash"
if [[ -f "$preBackupScript" ]];then
step "Run pre backup Script?" source "$preBackupScript"
fi
if [[ $doBackupGit ]];then
msg_notice "compressing git dirs"
run_compress_git "$sourceDir"
echo -e "\n\n-------- .git folders compressed: \n"
find "$sourceDir" | grep ".git.tar.gz"
echo -e "\n----------------\n"
read -p "(enter) to continue"
else
msg_notice "git not backed up"
fi
## --archive equals -rlptgoD or:
# --recursive # recurse into directories
# --links # copy symlinks as symlinks
# --perms # preserve permissions
# --times # preserve modification times
# --group # preserve group
# --owner # preserve owner
# -D is --devices --specials # "preserve device files" & "preserve special files" respectively
## Others:
# --hard-links preserve hard links (probably not needed)
# --executability preserve executability
# --acls preserve ACLs (implies --perms) (see `info ACL`. I think this is needed for sticky bits to work? idk)
rsync_args=(--verbose --archive --hard-links --executability --acls --progress)
if [[ $doDryRun ]]; then
rsync_args+=(--dry-run)
msg_notice "Do dry run!"
fi
rsync_end_args=()
if $useExcludesFile;then
rsync_end_args+=("--exclude-from=$excludesListFile")
fi
echo "Source Dir: $sourceDir"
echo "Backup Dir: $backupDir"
rsync "${rsync_args[@]}" --delete --delete-before --delete-excluded --exclude=".git/" --exclude="vendor/" "${rsync_end_args[@]}" "$sourceDir" "$backupDir"
if [[ $doBackupGit ]];then
msg_notice "Decompressing git dirs"
run_decompress_git "$sourceDir"
fi
echo -e "\nShould be all done!!\n"
}