#!/usr/bin/env fish

# Environment

set custom_name $argv[1]
set upload_only (test "$custom_name" = 'upload'; and echo true; or echo false)
set backups_parent /mnt/bulk/Backups
set borg_repos /mnt/bulk/Backups/future /mnt/cyan/futurerepo
set hotmounts /mnt/cyan # mountpoints to mount at start and umount at end
set b2_local_dir /mnt/bulk/Backups/future
set b2_bucket futurebackups
set keepass_file /home/cloud/Documents/passwords.kdbx
set keepass_entry Borg/futurebackups
set backup_paths /

# Settings

set show_stats true
set show_progress true
set show_list false
set dry_run false
set b2_upload true
set b2_threads 5

# Exclude
# fnmatch, fm: (--exclude default)
#    '*' any number, '?' one, '[...]' set, '[!...]' inverse set
#    Path seperator not treated specially.
#    Must match entire path.
# shell-style, sh: (--pattern default)
#    '**/' zero or more directories, '*' zero or more characters except path separator
#    Must match entire path.
# path prefix, pp:
#    Match whole subdirectories.
#    Must write the entire filesystem absolute path.
set backup_exclude \
	# Debatable
	'pp:/home/cloud/.config/vivaldi' \
	# Steam
	# -- Pretty sure everything in ~/.steam would be downloaded after a steam reinstall
	'pp:/home/cloud/.steam' \
	'pp:/mnt/bulk/SteamWine' \
	'pp:/mnt/bulk/Steam' \
	'pp:/mnt/bulk/SteamBackups' \
	# Large, not vital files
	'pp:/home/cloud/.config/discordcanary' \
	'pp:/home/cloud/.local/share/Trash' \
	'pp:/home/cloud/.local/share/dolphin-emu/StateSaves' \
	'pp:/home/cloud/.local/share/flatpak' \
	'pp:/home/cloud/Software/etterna' \
	'pp:/home/cloud/Software/FALdetector' \
	'pp:/home/cloud/Software/ffmpeg' \
	'pp:/home/cloud/Software/stepmania' \
	'pp:/home/cloud/Software/vdexExtractor' \
	'pp:/home/cloud/Software/zig-linux-x86_64-0.5.0+eff50abce/' \
	'pf:/home/cloud/unison.log' \
	'pp:/home/cloud/vm-aqemu' \
	'pp:/mnt/bulk/Lutris/overwatch' \
	# Bulk
	'pp:/mnt/bulk/Backups/future' \
	'pp:/mnt/bulk/Backups/laptop' \
	'pp:/mnt/bulk/Backups/Minecraft server' \
	'pp:/mnt/bulk/Backups/Phone' \
	'pp:/mnt/bulk/DiskImages' \
	'pp:/mnt/bulk/Dogecoin' \
	'pp:/mnt/bulk/Downloads' \
	'pp:/mnt/bulk/Movies' \
	'pf:/mnt/bulk/myst3.7z' \
	'pp:/mnt/bulk/OldBuilds' \
	'pp:/mnt/bulk/StepMania Songs' \
	'pp:/mnt/bulk/Syncthing/Aurora' \
	'pp:/mnt/bulk/Syncthing/AuroraArchive' \
	'pp:/mnt/bulk/Syncthing/Downloads' \
	'pp:/mnt/bulk/Syncthing/DownloadsArchive' \
	'pp:/mnt/bulk/Torrents' \
	'pp:/mnt/bulk/VirtualBox VMs' \
	'pp:/mnt/bulk/YouTube' \
	'pp:/mnt/bulk/.Trash-1000' \
	'pp:/mnt/bulk/lost+found' \
	'pp:/mnt/bulk/osu!' \
	'pp:/mnt/bulk/osu!old' \
	'pp:/mnt/bulk/osu!torrent' \
	# Software
	'pp:/bin' \
	'pp:/home/cloud/snap' \
	'pp:/lib' \
	'pp:/lib64' \
	'pp:/opt' \
	'pp:/sbin' \
	'pp:/snap' \
	'pp:/usr' \
	'pp:/var/lib/flatpak' \
	# System
	'pp:/dev' \
	'pp:/home/cloud/.dbus' \
	'pp:/home/cloud/.gvfs' \
	'pp:/hostlvm' \
	'pp:/lost+found' \
	'pp:/media' \
	'pp:/mnt/iso' \
	'pp:/mnt/cyan' \
	'pp:/proc' \
	'pp:/root' \
	'pp:/run' \
	'pp:/srv' \
	'pp:/sys' \
	'pp:/tmp' \
	'pp:/var/cache/apt' \
	'pp:/var/cache/pacman' \
	'pp:/var/crash' \
	'pp:/var/lib/snapd' \
	'pp:/var/lock' \
	'pp:/var/log' \
	'pp:/var/mail' \
	'pp:/var/run' \
	'pp:/var/tmp' \
	'pp:/var/www' \
	# Cache
	'pp:/home/cloud/.cache' \
	'pp:/home/cloud/.config/vivaldi/Default/Service Worker/CacheStorage' \
	'sh:/home/cloud/.config/*/Cache' \
	'sh:/home/cloud/.config/*/CachedData' \
	'pp:/home/cloud/.local/share/QuiteRss/QuiteRss/adblock' \
	'pp:/home/cloud/.gradle' \
	'pp:/home/cloud/.hunter' \
	'sh:/home/cloud/.mozilla/firefox/**/cache' \
	'pp:/home/cloud/.nuget' \
	'pp:/home/cloud/.npm/_cacache' \
	'sh:/home/cloud/.local/lib/python*/site-packages/' \
	'pp:/home/cloud/Software/nheko/build-flatpak' \
	'sh:**/node_modules' \
	# VSCode extensions
	'sh:/home/cloud/.vscode/extensions/ms-*' \
	'sh:/home/cloud/.vscode/extensions/alexdima.vscode-lcov-*' \
	'sh:/home/cloud/.vscode/extensions/eamodio.gitlens-*' \
	'sh:/home/cloud/.vscode/extensions/gruntfuggly.todo-tree-*' \
	'sh:/home/cloud/.vscode/extensions/richie5um2.vscode-sort-json-*' \
	'sh:/home/cloud/.vscode/extensions/ryanluker.vscode-coverage-gutters-*' \
	'sh:/home/cloud/.vscode/extensions/umoxfo.vscode-w3cvalidation-*'

# Compression
# Borg supports the following compression methods:
#
# none (no compression, pass through data 1:1)
# lz4 (low compression, but super fast)
# zstd (level 1-22 offering a wide range: level 1 is lower compression and high speed, level 22 is higher compression and lower speed) - since borg 1.1.4
# zlib (level 0-9, level 0 is no compression [but still adding zlib overhead], level 1 is low, level 9 is high compression, default is 6)
# lzma (level 0-9, level 0 is low, level 9 is high compression, default is 6, do not use above 6.)
#
# Speed:       none   >   lz4   >   zlib   >   lzma,lz4   >   zstd
# Compression: lzma   >   zlib   >   lz4   >   none,zstd   >   lz4
set borg_compression auto,lzma,6

if not $upload_only

	# Keepass

	echo -n 'Enter your keepass password: '
	begin
		set -l IFS ''
		set keepass_output (keepassxc-cli show $keepass_file $keepass_entry 2>/dev/null)
		set keepass_status $status
	end
	echo
	if test $keepass_status -ne 0
		echo 'That is not the correct password.'
		exit 1
	end
	set borg_passphrase (echo $keepass_output | grep -m 1 Password | string split ' ')[2]

	# Prepare borg arguments

	cd $backups_parent

	set create_args --noatime
	if $show_progress
		set -a create_args --progress
	end
	if $show_list
		set -a create_args --list
	end
	if $dry_run
		set -a create_args --dry-run
	else if $show_stats
		set -a create_args --stats
	end
	if test (count $custom_name) -eq 1
		set -a create_args '::future-snap-'$custom_name
	else
		set -a create_args '::future-auto-{now}'
	end
	set -a create_args $backup_paths
	set -a create_args --exclude=$backup_exclude # cartesian product into multiple --exclude entries

	# Prepare borg environment variables

	set -x BORG_PASSPHRASE $borg_passphrase

	# Run pre-archive scripts
	echo 'Running pre-archive scripts'
	dpkg --get-selections > /home/cloud/.config/dpkg-selections

	# Ensure everything is mounted
	for mountpoint in $hotmounts
		mount $mountpoint
	end

	# Backup to each target
	for repo in $borg_repos
		set -x BORG_REPO $repo

		# Run borg
		echo 'Using flags' $create_args
		borg create $create_args
	end

	# Unmount targets
	for mountpoint in $hotmounts
		umount $mountpoint
	end
end

# Run B2

if test $b2_upload = true -a $dry_run = false
	echo 'B2'
	b2 sync --delete --replaceNewer --threads $b2_threads $b2_local_dir b2://$b2_bucket
end