summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2026-08-01 19:30:55 -0700
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2026-08-01 19:30:55 -0700
commit3df85966bd608863cf5ed02b85385d0b33665482 (patch)
tree91cfe3c377fa2dc37533a6fe517f6f2a34859889
parent27d127a861ae9707473b2eaf77bb39fe5350fd8e (diff)
downloadbackomp-3df85966bd608863cf5ed02b85385d0b33665482.tar.gz
backomp-3df85966bd608863cf5ed02b85385d0b33665482.tar.xz
add dry-run, backup-only and prune-only optionsHEADmaster
-rwxr-xr-xbackomp53
-rwxr-xr-xpre-copy-rclone-hardlink.sh2
2 files changed, 36 insertions, 19 deletions
diff --git a/backomp b/backomp
index f955916..1d465fa 100755
--- a/backomp
+++ b/backomp
@@ -42,7 +42,7 @@ BEGIN {
wshift = (11 - arr2[opt_week_start])*24*60*60
}
-!n_buckets || NR == 1 {
+!n_buckets || keep_first && NR == 1 {
++keep[$0]
}
@@ -113,7 +113,7 @@ parse_flags() {
}
qargs() {
- local arg str=
+ local arg str
for arg; do
[[ "${arg:-*}" =~ [^A-Za-z0-9%+./:=@_-] ]] && arg="${arg@Q}"
@@ -198,7 +198,7 @@ filter() {
local -n __src="${1}" __dest="${2}"
local __label="${3}" __script="${4}"
shift 4
- local res
+ local res c="${#__src[@]}"
mapfile -td '' __dest < <(
printf '%s\0' "${__src[@]}" | \
@@ -210,7 +210,7 @@ filter() {
return 1
fi
- if ((${#__src[@]})); then
+ if ((!DRY && c)); then
exists "${__dest[0]}" && return 0
[[ "$?" -eq 1 ]] &&
err "${__label} returned empty or invalid list"
@@ -238,10 +238,12 @@ populate() {
fi
if [[ "${__dir}" =~ ^([^:/]*):(.*) ]]; then
- mapfile -td '' __arr < <(
- ssh_run "${BASH_REMATCH[1]}" \
- "shopt -s nullglob; printf '%s\0' $( \
- printf '%q' "${BASH_REMATCH[2]}")/*")
+ read -rd '' cmd <<-EOF
+ shopt -s nullglob
+ x=($(printf '%q' "${BASH_REMATCH[2]}")/*)
+ ((!\${#x[@]})) || printf '%s\0' \"\${x[@]}\"
+ EOF
+ mapfile -td '' __arr < <(ssh_run "${BASH_REMATCH[1]}" "${cmd}")
wait "$!" || return 1
__arr=("${__arr[@]/#/${BASH_REMATCH[1]}:}")
@@ -249,7 +251,9 @@ populate() {
fi
mapfile -td '' __arr < <(
- shopt -s nullglob; printf '%s\0' "${__dir}/"*)
+ shopt -s nullglob
+ x=("${__dir}/"*)
+ ((!${#x[@]})) || printf '%s\0' "${x[@]}")
}
copy() {
@@ -266,6 +270,11 @@ copy() {
fi
done
+ if ((DRY)); then
+ echo "* DRY: copy ${dest}${link_dest:+ (link: ${link_dest})}"
+ return
+ fi
+
if [[ -n "${opts['pre_copy']}" ]]; then
bash -c "$(declare -p src dest link_dest opts \
); temp_dest=$(printf '%q' "${dest}.tmp" \
@@ -318,7 +327,9 @@ prune() {
if [[ "${__snaps[__i]}" == "${__keep[__k]}" ]]; then
((++__k))
else
- if [[ "${__snaps[__i]}" == rclone://* ]]; then
+ if ((DRY)); then
+ echo "* DRY: prune ${__snaps[__i]}"
+ elif [[ "${__snaps[__i]}" == rclone://* ]]; then
run rclone purge -- "${__snaps[__i]#*//}"
elif [[ "${__snaps[__i]}" =~ ^([^:/]*):(.*) ]]; then
USE_RUN=1 ssh_run "${BASH_REMATCH[1]}" \
@@ -337,7 +348,7 @@ backup() {
local rsync_flags="${6}" rclone_flags="${7}" ssh_flags="${8}"
local dest_path snaps keep
- if [[ ! -e "${src_path}" ]]; then
+ if ((!NO_BACKUP)) && [[ ! -e "${src_path}" ]]; then
err "source does not exist: ${src_path}"
return 1
fi
@@ -348,22 +359,28 @@ backup() {
populate snaps "${dest_dir}" || return 1
filter snaps snaps 'pre-snapshot awk prefilter' "${AWK_PREFILTER}" \
|| return 1
- [[ -n "${snaps}" ]] && current "${snaps[0]##*/}" "${interval}" \
- && return
- dest_path="${dest_dir}/$(date -u '+%Y-%m-%d-%H%M%S')"
- copy "${src_path}" "${dest_path}" "${snaps[0]}" || return 1
+ if ((!NO_BACKUP)) && ( [[ -z "${snaps}" ]] ||
+ ! current "${snaps[0]##*/}" "${interval}" ); then
+ dest_path="${dest_dir}/$(date -u '+%Y-%m-%d-%H%M%S')"
+ copy "${src_path}" "${dest_path}" "${snaps[0]}" || return 1
+ snaps+=("${dest_path}")
+ fi
+
+ ((NO_PRUNE)) && return
if [[ ! "${retain}" =~ ^( *([0-9]+|\*)\^?[hdwM])*\ *$ ]]; then
err "invalid \$retain setting: ${retain}"
return 1
fi
- snaps+=("${dest_path}")
- filter snaps snaps 'post-snapshot awk prefilter' "${AWK_PREFILTER}" \
- || return 1
+ if [[ -n "${dest_path}" ]]; then
+ filter snaps snaps 'post-snapshot awk prefilter' \
+ "${AWK_PREFILTER}" || return 1
+ fi
filter snaps keep 'awk filter' "${AWK_FILTER}" \
-v "opt_retain=${retain}" -v "opt_week_start=${week_start}" \
+ -v "keep_first=$((!NO_BACKUP))" \
|| return 1
prune snaps keep
}
diff --git a/pre-copy-rclone-hardlink.sh b/pre-copy-rclone-hardlink.sh
index 01f7b6e..aa763b5 100755
--- a/pre-copy-rclone-hardlink.sh
+++ b/pre-copy-rclone-hardlink.sh
@@ -3,7 +3,7 @@
# Copyright 2023 David Vazgenovich Shakaryan
qargs() {
- local arg str=
+ local arg str
for arg; do
[[ "${arg:-*}" =~ [^A-Za-z0-9%+./:=@_-] ]] && arg="${arg@Q}"