Bug#855976: [Patch] Revised

dg1727 dg1727 at protonmail.com
Fri Mar 3 23:25:39 UTC 2017


Here is an updated patch with the following improvements:

* Preserves an "advanced options" description, such as "(recovery mode)", in
the submenu entries.

* Suppresses options in the submenu that are equivalent to an option in the
main menu.

* Main-menu entries that open submenus are now indented, so the main menu is
more readable. (This affects only submenus generated by the os-prober script,
not by other GRUB scripts.)

* In part of the script, I made the indentation more consistent (in the script
only, not in its output) so the logic flow is more understandable.

The following was generated with "diff -ud" using diff version 3.3.

--- 30_os-prober 2016-07-22 20:09:25.000000000 -0400
+++ 15_os-prober 2017-03-03 17:43:52.371188836 -0500
@@ -27,6 +27,35 @@

. "${datarootdir}/grub/grub-mkconfig_lib"

+safe_echo () { printf %s\\n "$*" ; }
+safe_echo_n () { printf %s "$*" ; }
+# Based on http://www.etalabs.net/sh_tricks.html
+
+rtrim() { # remove trailing whitespace characters
+ local var="$*"
+ var="${var%"${var##*[![:space:]]}"}"
+ safe_echo_n "$var"
+}
+# Based on http://stackoverflow.com/a/3352015
+
+name_to_compare () { echo "${1}" | tr -c "[:alpha:]" " " | tr -s " " | \
+ tr "[:upper:]" "[:lower:]" | \
+ sed "s/[ ]\+$//" ; }
+# This function is used in detecting whether an /etc/lsb-release file's
+# DISTRIB_CODENAME is redundantly included at the end of the file's
+# DISTRIB_DESCRIPTION.
+# Convert all non-letters in ${1} to spaces.
+# Then convert multiple consecutive spaces to single spaces.
+# Then convert all uppercase letters to lowercase.
+# Then remove trailing spaces if present (sed "s/ $//" doesn't seem to work
+# for this).
+# We do these things so an LCODENAME of "betsy" will be detected at the end
+# of an LDESC of "LMDE 2 (Betsy)", but not in an LDESC of "LMDE blah b_e.t-s.y"
+
+menu_entry_values () { echo ${1} | cut -d ':' --complement -f 3 ; }
+# Get the values (other than the displayed name) of a menu entry.
+# This shell function is used to detect whether 2 menu entries are the same.
+
found_other_os=

adjust_timeout () {
@@ -244,71 +273,145 @@
LLABEL="${LONGNAME}"
fi

- if [ "${LROOT}" != "${LBOOT}" ]; then
- LKERNEL="${LKERNEL#/boot}"
- LINITRD="${LINITRD#/boot}"
- fi
+ if [ "${LROOT}" != "${LBOOT}" ]; then
+ LKERNEL="${LKERNEL#/boot}"
+ LINITRD="${LINITRD#/boot}"
+ fi

- if [ -z "${prepare_boot_cache}" ]; then
- prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | grub_add_tab)"
- [ "${prepare_boot_cache}" ] || continue
- fi
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | grub_add_tab)"
+ [ "${prepare_boot_cache}" ] || continue
+ fi

- found_other_os=1
- onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
- recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true
- counter=1
- while echo "$used_osprober_linux_ids" | grep 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id' > /dev/null; do
- counter=$((counter+1));
- done
- if [ -z "$boot_device_id" ]; then
- boot_device_id="$(grub_get_device_id "${DEVICE}")"
- fi
- used_osprober_linux_ids="$used_osprober_linux_ids 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id'"
+ LSB_QUERY_MOUNT_POINT=$(findmnt -flno TARGET ${DEVICE})
+
+ if [ -z "${LSB_QUERY_MOUNT_POINT}" ] ; then
+ LSB_QUERY_MOUNT_POINT=$(mktemp -d)
+ mount ${DEVICE} ${LSB_QUERY_MOUNT_POINT}
+ TEMP_MOUNT="true"
+ # It appears that this code doesn't run: Although syslog indicates
+ # that /usr/lib/os-probes/mounted/40lsb indeed scans unmounted
+ # partitions, it seems that /usr/bin/os-prober (which is indirectly
+ # the parent process of "40lsb") still doesn't report any OS that
+ # exists on such a partition. The partition tested was formatted as
+ # btrfs.
+ else
+ TEMP_MOUNT="false"
+ fi
+
+ LSB_DATABASE=${LSB_QUERY_MOUNT_POINT}/etc/lsb-release
+
+ LCODENAME=$(grep ^DISTRIB_CODENAME ${LSB_DATABASE} | cut -d "=" -f 2)
+ LDESC=$(grep ^DISTRIB_DESCRIPTION ${LSB_DATABASE} | cut -d "=" -f 2)
+
+ if [ "x${TEMP_MOUNT}" = xtrue ] ; then
+ umount ${LSB_QUERY_MOUNT_POINT}
+ fi
+
+ if safe_echo "${LDESC}" | grep -E "^(['\"]).*\1$" >/dev/null; then
+ LDESC=$(safe_echo "${LDESC}" | cut -c 2- | rev | cut -c 2- | rev)
+ fi # If ${LDESC} is quoted, then remove the quote marks.
+
+ LSPECIAL_MODE=$(rtrim "$(safe_echo "$LLABEL" | \
+ grep -Eo "\([^(]*\)[[:space:]]*$")")
+ # Get any parenthesized string (optionally followed by whitespace) at the end
+ # of $LLABEL.
+
+ if [ -n "${LSPECIAL_MODE}" ]; then
+ LSPECIAL_MODE=" ${LSPECIAL_MODE}"
+ fi
+ # After this "if", $LSPECIAL_MODE either is null or starts with " ("
+
+ LKERNEL_DISPLAY=$(safe_echo "${LKERNEL}" | cut -d "-" -f 2-)
+ # Try to extract the version number of the kernel image file.
+
+ LDESC_CMP=$(name_to_compare "${LDESC}")
+ LCODENAME_CMP=$(name_to_compare "${LCODENAME}")
+
+ if safe_echo "${LDESC_CMP}" | grep -E "${LCODENAME_CMP}$" >/dev/null; then
+ # ${LDESC} ends in ${LCODENAME}.
+ OS_SUBMENU="${LDESC}"
+ else
+ # ${LDESC} doesn't end in ${LCODENAME}.
+ OS_SUBMENU="${LDESC} \"${LCODENAME}\""
+ fi
+
+ OS="${OS_SUBMENU}${LSPECIAL_MODE}, with Linux kernel ${LKERNEL_DISPLAY}"
+ # Examples:
+ # Ubuntu 13.04 "raring", with Linux kernel 3.8.0-35-generic
+ # LMDE 2 Betsy, with Linux kernel 3.16.0-4-amd64
+ # (if codename is "betsy" & description ends in "Betsy")
+
+ found_other_os=1
+ onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+ recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true
+ counter=1
+ while echo "$used_osprober_linux_ids" | grep 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id' > /dev/null; do
+ counter=$((counter+1));
+ done
+ if [ -z "$boot_device_id" ]; then
+ boot_device_id="$(grub_get_device_id "${DEVICE}")"
+ fi
+ used_osprober_linux_ids="$used_osprober_linux_ids 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id'"

- if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
- cat << EOF
+ if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
+ printf "Adding '%s' to menu\n" "${OS}" >&2
+ cat << EOF
menuentry '$(echo "$OS $onstr" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-simple-$boot_device_id' {
EOF
- save_default_entry | grub_add_tab
- printf '%s\n' "${prepare_boot_cache}"
- cat << EOF
+ save_default_entry | grub_add_tab
+ printf '%s\n' "${prepare_boot_cache}"
+ cat << EOF
linux ${LKERNEL} ${LPARAMS}
EOF
- if [ -n "${LINITRD}" ] ; then
- cat << EOF
+ if [ -n "${LINITRD}" ] ; then
+ cat << EOF
initrd ${LINITRD}
EOF
- fi
- cat << EOF
+ fi
+ cat << EOF
}
EOF
- echo "submenu '$(gettext_printf "Advanced options for %s" "${OS} $onstr" | grub_quote)' \$menuentry_id_option 'osprober-gnulinux-advanced-$boot_device_id' {"
- is_top_level=false
- fi
- title="${LLABEL} $onstr"
- cat << EOF
- menuentry '$(echo "$title" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-$LKERNEL-${recovery_params}-$boot_device_id' {
+ echo "submenu '$(gettext_printf " Advanced options for %s" "${OS_SUBMENU} $onstr" | grub_quote)' \$menuentry_id_option 'osprober-gnulinux-advanced-$boot_device_id' {"
+
+ PRIMARY_VALUES="$(menu_entry_values ${LINUX})"
+ # Stash the values (other than the displayed name) of the primary
+ # menu entry.
+
+ is_top_level=false
+ fi
+
+ SUBMENU_VALUES="$(menu_entry_values ${LINUX})"
+ if [ "x${is_top_level}" = xfalse ] && \
+ [ "x${SUBMENU_VALUES}" != "x${PRIMARY_VALUES}" ]; then
+ # Allow only submenu entries that are different than their primary
+ # menu entry.
+
+ title="${OS} $onstr"
+ printf "Adding '%s' to submenu\n" "${OS}" >&2
+ cat << EOF
+ menuentry '$(echo "$title" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-$LKERNEL-${recovery_params}-$boot_device_id' {
EOF
- save_default_entry | sed -e "s/^/$grub_tab$grub_tab/"
- printf '%s\n' "${prepare_boot_cache}" | grub_add_tab
- cat << EOF
- linux ${LKERNEL} ${LPARAMS}
+ save_default_entry | sed -e "s/^/$grub_tab$grub_tab/"
+ printf '%s\n' "${prepare_boot_cache}" | grub_add_tab
+ cat << EOF
+ linux ${LKERNEL} ${LPARAMS}
EOF
- if [ -n "${LINITRD}" ] ; then
+ if [ -n "${LINITRD}" ] ; then
cat << EOF
- initrd ${LINITRD}
+ initrd ${LINITRD}
EOF
- fi
- cat << EOF
- }
+ fi
+ cat << EOF
+ }
EOF
- if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
- replacement_title="$(echo "Advanced options for ${OS} $onstr" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"
- quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
- title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
- grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"
- fi
+ if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
+ replacement_title="$(echo " Advanced options for ${OS} $onstr" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"
+ quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
+ title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
+ grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"
+ fi
+ fi
done
if [ x"$is_top_level" != xtrue ]; then
echo '}'
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.alioth.debian.org/pipermail/pkg-grub-devel/attachments/20170303/66fe15a9/attachment-0001.html>


More information about the Pkg-grub-devel mailing list