v2: Fix wrong sorting order if version contains "-" delimiter --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -203,12 +203,17 @@ version_sort () { case $version_sort_sort_has_v in + rpmsort) + LC_ALL=C /usr/lib/rpm/rpmsort "$@";; yes) LC_ALL=C sort -V "$@";; no) LC_ALL=C sort -n "$@";; *) - if sort -V /dev/null 2>&1; then + if test -x /usr/lib/rpm/rpmsort; then + version_sort_sort_has_v=rpmsort + LC_ALL=C /usr/lib/rpm/rpmsort "$@" + elif sort -V /dev/null 2>&1; then version_sort_sort_has_v=yes LC_ALL=C sort -V "$@" else --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -229,12 +229,56 @@ # yet, so it's empty. In a submenu it will be equal to '\t' (one tab). submenu_indentation="" +listvrf="" +pre_sort () { + local l="" + + for f in $list; do + vr="`echo $f | sed -e 's/[^-]*-//' -e 's/-\([^0-9]*\)$/\.\1/' -e 's/-/~/g' -e 's/~\([^~]*\)$/-\1/'`" + l="$l $vr" + listvrf="$listvrf $vr:$f" + done + + list=$l +} + +post_sort () { + local l="" + local vr="" + local f="" + local found="" + + for i in $reverse_sorted_list; do + found="" + for vrf in $listvrf; do + vr=${vrf%%:*} + f=${vrf#*:} + if test x"$vr" = x"$i"; then + l="$l $f" + found=$vrf + break + fi + done + if test -n "$found"; then + listvrf="`echo $listvrf | (sed -e 's!'$found'!!' 2>/dev/null || echo $listvrf)`" + fi + done + + for vrf in $listvrf; do + f=${vrf#*:} + l="$l $f" + done + + reverse_sorted_list=$l +} +pre_sort # Perform a reverse version sort on the entire list. # Temporarily replace the '.old' suffix by ' 1' and append ' 2' for all # other files to order the '.old' files after their non-old counterpart # in reverse-sorted order. reverse_sorted_list=$(echo $list | tr ' ' '\n' | sed -e 's/\.old$/ 1/; / 1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//') +post_sort if [ "x$GRUB_TOP_LEVEL" != x ]; then reverse_sorted_list=$(grub_move_to_front "$GRUB_TOP_LEVEL" ${reverse_sorted_list}) --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -255,13 +255,57 @@ # yet, so it's empty. In a submenu it will be equal to '\t' (one tab). submenu_indentation="" +listvrf="" +pre_sort () { + local l="" + + for f in $linux_list; do + vr="`echo $f | sed -e 's/[^-]*-//' -e 's/-\([^0-9]*\)$/\.\1/' -e 's/-/~/g' -e 's/~\([^~]*\)$/-\1/'`" + l="$l $vr" + listvrf="$listvrf $vr:$f" + done + + linux_list=$l +} + +post_sort () { + local l="" + local vr="" + local f="" + local found="" + + for i in $reverse_sorted_linux_list; do + found="" + for vrf in $listvrf; do + vr=${vrf%%:*} + f=${vrf#*:} + if test x"$vr" = x"$i"; then + l="$l $f" + found=$vrf + break + fi + done + if test -n "$found"; then + listvrf="`echo $listvrf | (sed -e 's!'$found'!!' 2>/dev/null || echo $listvrf)`" + fi + done + + for vrf in $listvrf; do + f=${vrf#*:} + l="$l $f" + done + + reverse_sorted_linux_list=$l +} # Perform a reverse version sort on the entire xen_list and linux_list. # Temporarily replace the '.old' suffix by ' 1' and append ' 2' for all # other files to order the '.old' files after their non-old counterpart # in reverse-sorted order. reverse_sorted_xen_list=$(echo ${xen_list} | tr ' ' '\n' | sed -e 's/\.old$/ 1/; / 1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//') +pre_sort reverse_sorted_linux_list=$(echo ${linux_list} | tr ' ' '\n' | sed -e 's/\.old$/ 1/; / 1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//') +post_sort if [ "x$GRUB_TOP_LEVEL_XEN" != x ]; then reverse_sorted_xen_list=$(grub_move_to_front "$GRUB_TOP_LEVEL_XEN" ${reverse_sorted_xen_list})