git: 6d3c0798ccbe - main - bsdconfig: rework packages selection TUI

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Tue, 10 Oct 2023 07:01:56 UTC
The branch main has been updated by bapt:

URL: https://cgit.FreeBSD.org/src/commit/?id=6d3c0798ccbe7f6d3b677eed31206efc1227be50

commit 6d3c0798ccbe7f6d3b677eed31206efc1227be50
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2023-10-10 06:56:36 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2023-10-10 07:01:51 +0000

    bsdconfig: rework packages selection TUI
    
    Rework the packages TUI, do that the index caching is now done with
    dialog --gauge (tested with cdialog and bsddialog).
    With pkg we can know in avance the number of packages making it
    possible to have a real gauge.
    
    The cache of the index is now a file that can be sourced, meaning it
    is not anymore an index like file, but a post process one, simplifying
    the code.
    
    Each menu is now built calling directly pkg rquery with just the
    informations required to build the menu instead of parsing an indexfile
    
    install all the awk index processing into a separate file to ease
    reading and debuggung
---
 usr.sbin/bsdconfig/share/packages/Makefile      |   2 +-
 usr.sbin/bsdconfig/share/packages/index.awk     |  98 +++++++++++++++++
 usr.sbin/bsdconfig/share/packages/index.subr    | 138 +++++-------------------
 usr.sbin/bsdconfig/share/packages/packages.subr |  12 ++-
 4 files changed, 133 insertions(+), 117 deletions(-)

diff --git a/usr.sbin/bsdconfig/share/packages/Makefile b/usr.sbin/bsdconfig/share/packages/Makefile
index e694bf4157cf..c8e710902bec 100644
--- a/usr.sbin/bsdconfig/share/packages/Makefile
+++ b/usr.sbin/bsdconfig/share/packages/Makefile
@@ -1,5 +1,5 @@
 
 FILESDIR=	${SHAREDIR}/bsdconfig/packages
-FILES=		categories.subr index.subr musthavepkg.subr packages.subr
+FILES=		categories.subr index.awk index.subr musthavepkg.subr packages.subr
 
 .include <bsd.prog.mk>
diff --git a/usr.sbin/bsdconfig/share/packages/index.awk b/usr.sbin/bsdconfig/share/packages/index.awk
new file mode 100644
index 000000000000..f22aa150bd63
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/packages/index.awk
@@ -0,0 +1,98 @@
+function _asorti(src, dest)
+{
+	k = nitems = 0
+
+	# Copy src indices to dest and calculate array length
+	for (i in src) dest[++nitems] = i
+
+	# Sort the array of indices (dest) using insertion sort method
+	for (i = 1; i <= nitems; k = i++)
+	{
+		idx = dest[i]
+		while ((k > 0) && (dest[k] > idx))
+		{
+			dest[k+1] = dest[k]
+			k--
+		}
+		dest[k+1] = idx
+	}
+
+	return nitems
+}
+
+function print_category(category, npkgs, desc)
+{
+	cat = category
+	# Accent the category if the first page has been
+	# cached (also acting as a visitation indicator)
+	if ( ENVIRON["_index_page_" varcat "_1"] )
+		cat = cat "*"
+	printf "'\''%s'\'' '\''%s " packages "'\'' '\''%s'\''\n",
+	       cat, npkgs, desc >>tmpfile
+}
+
+BEGIN{
+	cnt=0
+	div=int(npkg / 100)
+	last=0
+	prefix = ""
+}
+{
+	cnt+=1
+	i = int(cnt / div)
+	if (i > last) {
+		last = i
+		print "XXX"
+		print i
+		print msg
+		print "XXX"
+		fflush("/dev/stdout");
+	}
+	varpkg = $1
+	gsub("[^" valid_chars "]", "_", varpkg)
+	print "_categories_" varpkg "=\"" $7 "\"" >> tmpfile
+	split($7, pkg_categories, /[[:space:]]+/)
+	for (pkg_category in pkg_categories)
+		categories[pkg_categories[pkg_category]]++
+	print "_rundeps_" varpkg "=\"" $9 "\"" >> tmpfile
+
+}
+END {
+	n = _asorti(categories, categories_sorted)
+	# Produce package counts for each category
+	for (i = 1; i <= n; i++)
+	{
+		cat = varcat = categories_sorted[i]
+		npkgs = categories[cat]
+		gsub("[^" valid_chars "]", "_", varcat)
+		print "_npkgs_" varcat "=\"" npkgs "\"" >>tmpfile
+	}
+	#
+	# Create menu list and generate list of categories at same time
+	print "CATEGORY_MENU_LIST=\"" >>tmpfile
+	print_category(msg_all, npkg, msg_all_desc)
+	category_list = ""
+	for (i = 1; i <= n; i++)
+	{
+		cat = varcat = categories_sorted[i]
+		npkgs = categories[cat]
+		cur_prefix = tolower(substr(cat, 1, 1))
+		if ( prefix != cur_prefix )
+			prefix = cur_prefix
+		else
+			cat = " " cat
+		gsub("[^" valid_chars "]", "_", varcat)
+		desc = ENVIRON["_category_" varcat]
+		if ( ! desc ) desc = default_desc
+		print_category(cat, npkgs, desc)
+		category_list = category_list " " cat
+	}
+	print "\"" >>tmpfile
+
+	# Produce the list of categories (calculated in above block)
+	sub(/^ /, "", category_list)
+	print "PACKAGE_CATEGORIES=\"" category_list "\"" >> tmpfile
+	print "_npkgs=\""npkg"\"" >>tmpfile
+
+	print "EOF"
+}
diff --git a/usr.sbin/bsdconfig/share/packages/index.subr b/usr.sbin/bsdconfig/share/packages/index.subr
index 34c40d6905ab..04f28603426b 100644
--- a/usr.sbin/bsdconfig/share/packages/index.subr
+++ b/usr.sbin/bsdconfig/share/packages/index.subr
@@ -146,7 +146,7 @@ f_index_initialize()
 				# one populate the environment from the on-disk
 				# cache and provide success exit status.
 				#
-				if [ "$digest" = "$__sqlite_digest" ]; then
+				if [ "$digest" = "#$__sqlite_digest" ]; then
 					cat
 					exit $SUCCESS
 				else
@@ -171,24 +171,27 @@ f_index_initialize()
 	# If we reach this point, we need to generate the data from scratch
 	#
 
-	eval "$__var_to_set"='$( pkg rquery -I | (
-		exec 2<&1; dpv -ko /dev/stderr >&$TERMINAL_STDOUT_PASSTHRU \
-			-b "$DIALOG_BACKTITLE" \
-			-- "$msg_generating_index_from_pkg_database"
-	) | sort )'
-
-	#
-	# Attempt to create the persistent on-disk cache
-	#
-
 	# Create a new temporary file to write to
 	local __tmpfile
 	if f_eval_catch -dk __tmpfile $__funcname mktemp \
-		'mktemp -t "%s"' "$pgm"
-	then
+		'mktemp -t "%s"' "$pgm"; then
+		local _npkg
 		# Write the temporary file contents
-		echo "$__sqlite_digest" > "$__tmpfile"
-		debug= f_getvar "$__var_to_set" >> "$__tmpfile"
+		echo "#$__sqlite_digest" > "$__tmpfile"
+		f_eval_catch -k _npkg $__funcname pkg \
+			"pkg stat -r | awk '%s'" '/Packages available/ { print $3 }'
+		pkg rquery -I | awk -v npkg=$_npkg \
+			-v msg="$msg_generating_index_from_pkg_database" \
+			-v tmpfile="$__tmpfile" \
+			-v valid_chars="$VALID_VARNAME_CHARS" \
+			-v default_desc="$msg_no_description_provided" \
+			-v packages="$msg_packages" \
+			-v msg_all="$msg_all" \
+			-v msg_all_desc="$msg_all_desc" \
+			-F "|" \
+			-f $BSDCFG_SHARE/packages/index.awk | \
+			$DIALOG --backtitle "$DIALOG_BACKTITLE" \
+			--gauge "$msg_generating_index_from_pkg_database" 0 0
 
 		# Finally, move the temporary file into place
 		case "$PACKAGES_INDEX_CACHEFILE" in
@@ -197,10 +200,13 @@ f_index_initialize()
 		esac
 		f_eval_catch -d $__funcname mv 'mv -f "%s" "%s"' \
 			"$__tmpfile" "$PACKAGES_INDEX_CACHEFILE"
+	else
+		return $FAILURE
 	fi
 
 	if ! f_index_read "$__var_to_set"; then
-		f_show_err "$msg_io_or_format_error_on_index_file"
+		f_show_err \
+			"$msg_io_or_format_error_on_index_file"
 		return $FAILURE
 	fi
 
@@ -234,98 +240,7 @@ f_index_read()
 	export VALID_VARNAME_CHARS
 	export msg_packages
 
-	eval "$( debug= f_getvar "$var_to_get" | awk -F'|' '
-	function _asorti(src, dest)
-	{
-		k = nitems = 0
-
-		# Copy src indices to dest and calculate array length
-		for (i in src) dest[++nitems] = i
-
-		# Sort the array of indices (dest) using insertion sort method
-		for (i = 1; i <= nitems; k = i++)
-		{
-			idx = dest[i]
-			while ((k > 0) && (dest[k] > idx))
-			{
-				dest[k+1] = dest[k]
-				k--
-			}
-			dest[k+1] = idx
-		}
-
-		return nitems
-	}
-	function print_category(category, npkgs, desc)
-	{
-		cat = category
-		# Accent the category if the first page has been
-		# cached (also acting as a visitation indicator)
-		if ( ENVIRON["_index_page_" varcat "_1"] )
-			cat = cat "*"
-		printf "'\''%s'\'' '\''%s " packages "'\'' '\''%s'\''\n",
-		       cat, npkgs, desc
-	}
-	BEGIN {
-		valid_chars = ENVIRON["VALID_VARNAME_CHARS"]
-		default_desc = ENVIRON["msg_no_description_provided"]
-		packages = ENVIRON["msg_packages"]
-		tpkgs = 0
-		prefix = ""
-	}
-	{
-		tpkgs++
-		varpkg = $1
-		gsub("[^" valid_chars "]", "_", varpkg)
-		print "_categories_" varpkg "=\"" $7 "\""
-		split($7, pkg_categories, /[[:space:]]+/)
-		for (pkg_category in pkg_categories)
-			categories[pkg_categories[pkg_category]]++
-		print "_rundeps_" varpkg "=\"" $9 "\""
-	}
-	END {
-		print "_npkgs=" tpkgs # For convenience, total package count
-
-		n = _asorti(categories, categories_sorted)
-
-		# Produce package counts for each category
-		for (i = 1; i <= n; i++)
-		{
-			cat = varcat = categories_sorted[i]
-			npkgs = categories[cat]
-			gsub("[^" valid_chars "]", "_", varcat)
-			print "_npkgs_" varcat "=\"" npkgs "\""
-		}
-
-		# Create menu list and generate list of categories at same time
-		print "CATEGORY_MENU_LIST=\""
-		print_category(ENVIRON["msg_all"], tpkgs,
-		               ENVIRON["msg_all_desc"])
-		category_list = ""
-		for (i = 1; i <= n; i++)
-		{
-			cat = varcat = categories_sorted[i]
-			npkgs = categories[cat]
-			cur_prefix = tolower(substr(cat, 1, 1))
-			if ( prefix != cur_prefix )
-				prefix = cur_prefix
-			else
-				cat = " " cat
-			gsub("[^" valid_chars "]", "_", varcat)
-			desc = ENVIRON["_category_" varcat]
-			if ( ! desc ) desc = default_desc
-			print_category(cat, npkgs, desc)
-			category_list = category_list " " cat
-		}
-		print "\""
-
-		# Produce the list of categories (calculated in above block)
-		sub(/^ /, "", category_list)
-		print "PACKAGE_CATEGORIES=\"" category_list "\""
-
-	}' | ( exec 2<&1; dpv -ko /dev/stderr >&$TERMINAL_STDOUT_PASSTHRU \
-		-b "$DIALOG_BACKTITLE" -- "$msg_reading_package_index_data"
-	) )" # End-Quote
+	. $PACKAGES_INDEX_CACHEFILE
 }
 
 # f_index_extract_pages $var_to_get $var_basename $pagesize [$category]
@@ -342,19 +257,14 @@ f_index_read()
 f_index_extract_pages()
 {
 	local var_to_get="${1:-PACKAGE_INDEX}" var_basename="$2" pagesize="$3"
-	local category="$4" # Optional
 
 	eval "$(
 		debug= f_getvar "$var_to_get" | awk -F'|' \
-			-v cat="$category" \
 			-v pagesize="$pagesize" \
-			-v var_basename="$var_basename" \
-			-v i18n_all="$msg_all" '
+			-v var_basename="$var_basename" ' \
 		BEGIN { n = page = 0 }
 		/'\''/{ gsub(/'\''/, "'\''\\'\'\''") }
 		{
-			if ( cat !~ "(^$|^" i18n_all "$)" && $7 !~ \
-			     "(^|[[:space:]])" cat "([[:space:]]|$)" ) next
 			starting_new_page = (n++ == (pagesize * page))
 			if ( starting_new_page )
 				printf "%s%s", ( n > 1 ? "'\''\n" : "" ),
diff --git a/usr.sbin/bsdconfig/share/packages/packages.subr b/usr.sbin/bsdconfig/share/packages/packages.subr
index 554e7f9bb9e0..38059d4748a6 100644
--- a/usr.sbin/bsdconfig/share/packages/packages.subr
+++ b/usr.sbin/bsdconfig/share/packages/packages.subr
@@ -378,6 +378,7 @@ f_package_index_get_page()
 #
 f_package_menu_select()
 {
+	local __funcname=f_package_menu_deselect
 	local category="$1" page="${2:-1}"
 	local prompt= # Calculated below
 	local menu_list # Calculated below
@@ -424,8 +425,15 @@ f_package_menu_select()
 			next_page="$next_page*"
 	fi
 
-	local index_page
-	f_package_index_get_page "$category" $page index_page
+	local index_page __index
+	if [ "$category" = "$msg_all" ]; then
+		f_eval_catch -k __index $__funcname pkg \
+			"pkg rquery -a '%s'"  "%n|%o||%c"
+	else
+		f_eval_catch -k __index $__funcname pkg \
+			"pkg rquery -g '%s' '%s/\*'"  "%n|%o||%c" "$category"
+	fi
+	f_package_index_get_page "$category" $page index_page __index
 
 	menu_list="
 		${add_prev:+'> $previous_page' '' ${SHOW_DESC:+''}}