Skip to content

Commit

Permalink
zsnapshots: allow filesystem selection when no argument is specified
Browse files Browse the repository at this point in the history
  • Loading branch information
ahesford committed Jan 31, 2024
1 parent 4de96a0 commit c83f534
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 27 deletions.
36 changes: 32 additions & 4 deletions zfsbootmenu/bin/zsnapshots
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
# vim: softtabstop=2 shiftwidth=2 expandtab

sources=(
/lib/profiling-lib.sh
Expand All @@ -24,13 +25,40 @@ global_header() {
echo -n -e "\\033[1;33m[ Recover from snapshot ]"
}

if [ $# -ne 1 ] ; then
echo "Usage: $0 filesystem"
exit
fi
fs_header() {
echo -n -e "\\033[1;33m[ Select a filesystem ]"
}

fs="${1}"

if [ -z "${fs}" ]; then
if ! candidates="$( find_be_candidates 2>/dev/null )"; then
zerror "no root candidates found; specify a filesystem manually"
exit 1
fi

header="$( column_wrap "^[RETURN] select:[ESCAPE] cancel" )"
sort_key="$( get_sort_key )"
preview_label="Sorted by: ${sort_key^}"

if ! fs="$(
fzf --header="${header}" --prompt "Filesystem > " \
${HAS_BORDER:+--border-label="$( fs_header )"} \
${HAS_BORDER:+--preview-label-pos=2:bottom} \
${HAS_BORDER:+--preview-label="$( colorize orange " ${preview_label} " )"} \
--preview-window="up:${PREVIEW_HEIGHT}${HAS_BORDER:+,border-sharp}" \
--preview="/libexec/zfsbootmenu-preview {} '${BOOTFS}'" <<< "${candidates}"
)"; then
tput clear
exit 0;
fi
fi

if [ -z "${fs}" ]; then
zerror "a filesystem must be selected to browse snapshots"
exit 1
fi

if ! is_zfs_filesystem "${fs}" ; then
zerror "'${fs}' is not a ZFS filesystem"
exit 1
Expand Down
63 changes: 40 additions & 23 deletions zfsbootmenu/lib/zfsbootmenu-ui.sh
Original file line number Diff line number Diff line change
Expand Up @@ -582,26 +582,17 @@ get_sort_key() {
echo -n "${sort_key:-name}"
}

# arg1: path to BE list
# prints: nothing
# returns: 0 iff at least one valid BE was found

populate_be_list() {
local be_list fs canmount mnt active candidates ret sort_key
# prints: potential boot environments, one per line
# returns: 0 if any candidate was found, 1 otherwise

be_list="${1}"
if [ -z "${be_list}" ]; then
zerror "be_list is undefined"
return 1
fi
zdebug "be_list set to ${be_list}"
find_be_candidates() {
local fs mnt active ret sort_key list_fields have_bootfs

list_fields="name,canmount,mountpoint,org.zfsbootmenu:active"
sort_key="$( get_sort_key )"

# Truncate the list to avoid stale entries
: > "${be_list}"

# Find valid BEs
ret=1
have_bootfs=
while IFS=$'\t' read -r fs canmount mnt active; do
if [ "${mnt}" = "/" ]; then
# When mountpoint=/, BE is a candidate unless org.zfsbootmenu:active=off
Expand All @@ -613,8 +604,10 @@ populate_be_list() {
# All other datasets are ignored
continue
fi

# If BOOTFS is defined, we'll manually append it to the array
if [ "${BOOTFS}" = "${fs}" ] ; then
# If BOOTFS is defined, we'll manually append it to the array
have_bootfs="yes"
continue
fi

Expand All @@ -623,14 +616,38 @@ populate_be_list() {
zwarn "canmount=on set for '${fs}', should be canmount=noauto"
fi

candidates+=( "${fs}" )
done <<< "$(zfs list -H -o name,canmount,mountpoint,org.zfsbootmenu:active -S "${sort_key}")"
echo "${fs}"
ret=0
done <<< "$( zfs list -H -o "${list_fields}" -S "${sort_key}" )"

# put bootfs at the end
if [ -n "${BOOTFS}" ] && [ -n "${have_bootfs}" ]; then
echo "${BOOTFS}"
ret=0
fi

return "${ret}"
}

# arg1: path to BE list
# prints: nothing
# returns: 0 iff at least one valid BE was found

populate_be_list() {
local be_list fs ret

be_list="${1}"
if [ -z "${be_list}" ]; then
zerror "be_list is undefined"
return 1
fi
zdebug "be_list set to ${be_list}"

# put bootfs on the end, so it is shown first with --tac
[ -n "${BOOTFS}" ] && candidates+=( "${BOOTFS}" )
# Truncate the list to avoid stale entries
: > "${be_list}"

ret=1
for fs in "${candidates[@]}"; do
while read -r fs; do
# Remove any existing cmdline cache
rm -f "$( be_location "${fs}" )/cmdline"

Expand All @@ -642,6 +659,6 @@ populate_be_list() {
echo "${fs}" >> "${be_list}"
ret=0
fi
done
done <<< "$( find_be_candidates 2>/dev/null )"
return $ret
}

0 comments on commit c83f534

Please sign in to comment.