173 lines
6.4 KiB
Bash
Executable File
173 lines
6.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
declare -a pkgs
|
|
while read pkg; do
|
|
pkgs+=("${pkg}")
|
|
done
|
|
|
|
declare operation
|
|
operation="${1}"
|
|
|
|
declare conf_file
|
|
conf_file='/etc/pacman-zfs-snapshot.conf'
|
|
|
|
declare important_names snaps_trivial_keep snaps_important_keep snaps_trivial_suffix snaps_important_suffix
|
|
if [[ -r "${conf_file}" ]]; then
|
|
source "${conf_file}"
|
|
fi
|
|
|
|
if [[ ! "${do_dry_run}" ]]; then do_dry_run='true'; fi
|
|
if [[ ! "${important_names}" ]]; then important_names='linux'; fi
|
|
if [[ ! "${snaps_trivial_keep}" ]]; then snaps_trivial_keep='5'; fi
|
|
if [[ ! "${snaps_important_keep}" ]]; then snaps_important_keep='5'; fi
|
|
if [[ ! "${snaps_trivial_suffix}" ]]; then snaps_trivial_suffix='trv'; fi
|
|
if [[ ! "${snaps_important_suffix}" ]]; then snaps_important_suffix='imp'; fi
|
|
if [[ ! "${pkgs_list_max_length}" ]]; then pkgs_list_max_length='24'; fi
|
|
if [[ ! "${snap_only_local_datasets}" ]]; then snap_only_local_datasets='true'; fi
|
|
if [[ ! "${snap_field_separator}" ]]; then snap_field_separator='_'; fi
|
|
if [[ ! "${snap_name_prefix}" ]]; then snap_name_prefix='pac'; fi
|
|
if [[ ! "${snap_date_format}" ]]; then snap_date_format='+F-%H%M'; fi
|
|
if [[ ! "${snap_op_installation_suffix}" ]]; then snap_op_installation_suffix='inst'; fi
|
|
if [[ ! "${snap_op_remove_suffix}" ]]; then snap_op_remove_suffix='rmvl'; fi
|
|
if [[ ! "${snap_op_upgrade_suffix}" ]]; then snap_op_upgrade_suffix='upgr'; fi
|
|
|
|
function split_pkgs_by_importance () {
|
|
local pkgs_in_transaction
|
|
pkgs_in_transaction=("${@}")
|
|
for pkg in "${pkgs_in_transaction[@]}"; do
|
|
if grep -Piq -- '^'"${important_names}"'$' <<<"${pkg}"; then
|
|
important_pkgs_in_transaction+=("${pkg}")
|
|
else
|
|
trivial_pkgs_in_transaction+=("${pkg}")
|
|
fi
|
|
done
|
|
}
|
|
|
|
function set_severity () {
|
|
if [[ "${#important_pkgs_in_transaction[@]}" -ge '1' ]]; then
|
|
severity='imp'
|
|
else
|
|
severity='trv'
|
|
fi
|
|
}
|
|
|
|
function get_globally_snappable_datasets () {
|
|
local datasets_list
|
|
# For all datasets show their 'space.quico:auto-snapshot' property; only
|
|
# print dataset name in column 1 and property value in column 2. In awk
|
|
# limit this list to datasets where tab-delimited column 2 has exact
|
|
# string '^true$' then further limit output by eliminating snapshots
|
|
# from list, i.e. dataset names that contain an '@' character.
|
|
datasets_list="$(zfs get -H -o 'name,value' 'space.quico:auto-snapshot' | \
|
|
awk -F'\t' '{if($2 ~ /^true$/ && $1 !~ /@/) print $1}')"
|
|
while IFS= read -r dataset; do
|
|
globally_snappable_datasets+=("${dataset}")
|
|
done <<<"${datasets_list}"
|
|
}
|
|
|
|
function get_local_snappable_datasets () {
|
|
local datasets_list
|
|
datasets_list="$(findmnt --json --list --output 'fstype,source,target' | \
|
|
jq --raw-output '.[][] | select(.fstype=="zfs") | .source')"
|
|
while IFS= read -r dataset; do
|
|
local_snappable_datasets+=("${dataset}")
|
|
done <<<"${datasets_list}"
|
|
}
|
|
|
|
function trim_globally_snappable_datasets () {
|
|
for global_dataset in "${globally_snappable_datasets[@]}"; do
|
|
for local_dataset in "${local_snappable_datasets[@]}"; do
|
|
if grep -Piq -- '^'"${local_dataset}"'$' <<<"${global_dataset}"; then
|
|
snappable_datasets+=("${global_dataset}")
|
|
fi
|
|
done
|
|
done
|
|
}
|
|
|
|
function write_pkg_list_oneline () {
|
|
local unabridged_pkg_list_oneline
|
|
if [[ "${severity}" == 'imp' ]]; then
|
|
for pkg in "${important_pkgs_in_transaction[@]}"; do
|
|
if [[ "${unabridged_pkg_list_oneline}" ]]; then
|
|
unabridged_pkg_list_oneline="${unabridged_pkg_list_oneline}"','"${pkg}"
|
|
else
|
|
unabridged_pkg_list_oneline="${pkg}"
|
|
fi
|
|
done
|
|
fi
|
|
if [[ "${#trivial_pkgs_in_transaction[@]}" -ge '1' ]]; then
|
|
for pkg in "${trivial_pkgs_in_transaction[@]}"; do
|
|
if [[ "${unabridged_pkg_list_oneline}" ]]; then
|
|
unabridged_pkg_list_oneline="${unabridged_pkg_list_oneline}"','"${pkg}"
|
|
else
|
|
unabridged_pkg_list_oneline="${pkg}"
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
function find_max_dataset_name_length () {
|
|
local longest_op_suffix op_suffix_string
|
|
longest_op_suffix='0'
|
|
for op_suffix in "${snap_op_installation_suffix}" "${snap_op_remove_suffix}" "${snap_op_upgrade_suffix}"; do
|
|
if [[ "${#op_suffix}" -gt "${longest_op_suffix}" ]]; then
|
|
longest_op_suffix="${#op_suffix}"
|
|
fi
|
|
done
|
|
op_suffix_string="$(head -c "${longest_op_suffix}" '/dev/zero' | tr '\0' '_')"
|
|
|
|
local longest_sev_suffix sev_suffix_string
|
|
longest_sev_suffix='0'
|
|
for sev_suffix in "${snaps_trivial_suffix}" "${snaps_important_suffix}"; do
|
|
if [[ "${#sev_suffix}" -gt "${longest_sev_suffix}" ]]; then
|
|
longest_sev_suffix="${#sev_suffix}"
|
|
fi
|
|
done
|
|
sev_suffix_string="$(head -c "${longest_sev_suffix}" '/dev/zero' | tr '\0' '_')"
|
|
|
|
local max_dataset_name_length example_date_string dataset_name_no_pkgs
|
|
max_dataset_name_length='0'
|
|
example_date_string="$(date +"${snap_date_format}")"
|
|
for dataset in "${snappable_datasets[@]}"; do
|
|
dataset_name_no_pkgs="${dataset}"'@'"${snap_name_prefix}${snap_field_separator}${example_date_string}${snap_field_separator}"'op:'"${op_suffix_string}${snap_field_separator}"'sev:'"${sev_suffix_string}${snap_field_separator}"'pkgs:'
|
|
if [[ "${#dataset_name_no_pkgs}" -gt "${max_dataset_name_length}" ]]; then
|
|
max_dataset_name_length="${#dataset_name_no_pkgs}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
function main () {
|
|
local pkgs_in_transaction
|
|
pkgs_in_transaction=("${@}")
|
|
|
|
local -a important_pkgs_in_transaction trivial_pkgs_in_transaction
|
|
split_pkgs_by_importance "${pkgs_in_transaction[@]}"
|
|
|
|
local severity
|
|
set_severity
|
|
|
|
local -a globally_snappable_datasets
|
|
get_globally_snappable_datasets
|
|
|
|
local -a snappable_datasets
|
|
if [[ "${snap_only_local_datasets}" == 'true' ]]; then
|
|
local local_snappable_datasets
|
|
get_local_snappable_datasets
|
|
trim_globally_snappable_datasets
|
|
else
|
|
snappable_datasets=("${globally_snappable_datasets}")
|
|
fi
|
|
|
|
local pkg_list_oneline
|
|
write_pkg_list_oneline
|
|
|
|
local max_dataset_name_length
|
|
find_max_dataset_name_length
|
|
|
|
#for pkg in "${!important_pkgs_in_transaction[@]}"; do
|
|
# printf -- 'Array item '"'"'%s'"'"' equals '"'"'%s'"'"'\n' "${pkg}" "${important_pkgs_in_transaction[${pkg}]}"
|
|
#done
|
|
}
|
|
|
|
main "${pkgs[@]}"
|