[PATCH 1/3] metadata/install-qa-check.d: refactor 60udev-eclass

Lukas Schmelting <[email protected]>
Newsgroups gmane.linux.gentoo.devel
Message-ID <[email protected]>
Add `_dir_has_nonhidden_files` helper and consolidate udev rule
detection logic using a single `need_udev_reload` flag.

No functional change intended.

Signed-off-by: Lukas Schmelting <[email protected]>
---
 metadata/install-qa-check.d/60udev-eclass | 109 ++++++++++++++--------
 1 file changed, 68 insertions(+), 41 deletions(-)

diff --git a/metadata/install-qa-check.d/60udev-eclass b/metadata/install-qa-check.d/60udev-eclass
index 3ba779ec4ac4..1cc9dcd1e7a5 100644
--- a/metadata/install-qa-check.d/60udev-eclass
+++ b/metadata/install-qa-check.d/60udev-eclass
@@ -4,29 +4,39 @@
 # QA check: ensure that packages installing udev rules inherit the eclass
 # Maintainer: Sam James <[email protected]>
 
-# Implements three checks:
-# 1) Installation to /etc/udev/rules.d (which is a user-customization location);
-# 2) Installation of any udev rules to /lib/udev/rules.d without inheriting the eclass
-#    (needed for udev_reload in pkg_postinst);
-# 3) Check for installation of udev rules without calling udev_reload in
-#    pkg_postinst.
+# Implements the following checks:
+# 1) Installation to user-customization locations
+#    1a) /etc/udev/rules.d (udev rules files)
+# 2) Installation of udev files without inheriting udev.eclass, which provides
+#    helper functions used in pkg_postinst and pkg_postrm to update udev state.
+#    2a) /lib/udev/rules.d (udev rules files)
+# 3) Installation of udev files without triggering udev state updates in
+#    pkg_postinst and pkg_postrm via eclass helper functions.
+#    3a) udev_reload
+
+
+# Check whether a directory contains any non-hidden files (i.e avoid triggering
+# on keepdir). Returns 0 if at least one file exists, 1 otherwise.
+_dir_has_nonhidden_files() {
+    local path="$1"
+
+    shopt -s nullglob
+    local files=( "${ED}/${path}"/* )
+    shopt -u nullglob
+
+    (( ${#files[@]} > 0 ))
+}
+
 udev_rules_check() {
-	# Check 1
-	# Scan image for files in /etc/udev/rules.d which is a forbidden location
-	# (We use this glob to avoid triggering on keepdir)
-	shopt -s nullglob
-	local files=( "${ED}"/etc/udev/rules.d/* )
-	shopt -u nullglob
-
-	if [[ ${#files[@]} -gt 0 ]]; then
+ 	# Check 1a: Scan image for files in /etc/udev/rules.d which is a forbidden location
+	if _dir_has_nonhidden_files "etc/udev/rules.d"; then
 		eqawarn "QA Notice: files installed to /etc/udev/rules.d found"
 		eqawarn "udev rules files supplied by ebuilds must be installed to /lib/udev/rules.d/"
 	fi
 
 	# Check 2
-	# We're now going to check for whether we install files to /lib/udev/rules.d/ without
-	# inheriting the eclass (weak catch for ebuilds not calling udev_reload in pkg_postinst)
-
+    # Detect whether udev.eclass must be inherited which provides helper
+    # functions for updating udev state
 	if [[ -n ${UDEV_OPTIONAL} ]] ; then
 		# While imperfect, using ${UDEV_OPTIONAL} is good enough to allow opting out
 		# for e.g. sys-apps/portage, sys-apps/systemd, sys-libs/pam, etc. We may want
@@ -36,30 +46,47 @@ udev_rules_check() {
 		return
 	fi
 
-	if [[ -d "${ED}"/lib/udev/rules.d  || -d "${ED}"/usr/lib/udev/rules.d ]] ; then
-		if ! has udev ${INHERITED} ; then
-			eqawarn "QA Notice: package is installing udev rules without inheriting udev.eclass!"
-			eqawarn "Packages must inherit udev.eclass then call udev_reload in pkg_postinst."
-			return
-		fi
-
-		# Check 3
-		# Check whether we're installing udev rules without explicitly
-		# calling udev_reload in pkg_postinst, but we have inherited
-		# the eclass.
-		# Small risk of false positives if called indirectly.
-		# See: https://archives.gentoo.org/gentoo-dev/message/7bdfdc9a7560fd07436defd0253af0b8
-		local pkg_postinst_body="$(declare -fp pkg_postinst 2>&1)"
-		if [[ ! ${pkg_postinst_body} == *udev_reload* ]] ; then
-			eqawarn "QA Notice: package is installing udev rules without calling"
-			eqawarn "udev_reload in pkg_postinst phase"
-		fi
-		local pkg_postrm_body="$(declare -fp pkg_postrm 2>&1)"
-		if [[ ! ${pkg_postrm_body} == *udev_reload* ]] ; then
-			eqawarn "QA Notice: package is installing udev rules without calling"
-			eqawarn "udev_reload in pkg_postrm phase"
-		fi
-	fi
+    local need_udev_reload=0
+
+    # Check 2a: Check if udev rules must be updated
+    if _dir_has_nonhidden_files "lib/udev/rules.d"
+        || _dir_has_nonhidden_files "usr/lib/udev/rules.d"; then
+        need_udev_reload=1
+    fi
+
+    # No relevant files -> nothing to enforce
+    if [[ ${need_udev_reload} -eq 0 ]]; then
+	    return
+    fi
+
+    # If any udev rules or hwdb files are present, the eclass must be inherited
+    if [[ ${need_udev_reload} -eq 1 ]] && ! has udev ${INHERITED}; then
+	    eqawarn "QA Notice: package is installing udev-related files without inheriting"
+        eqawarn "udev.eclass! Packages must inherit udev.eclass then call the respective"
+        eqawarn "eclass function (udev_reload) in pkg_postinst and pkg_postrm."
+	    return
+    fi
+
+    # Check 3
+    # Check if the respective eclass helper function intended to update udev
+    # state is called in pkg_postinst and pkg_postrm (small risk of false
+    # positives if called indirectly).
+	# See: https://archives.gentoo.org/gentoo-dev/message/7bdfdc9a7560fd07436defd0253af0b8
+
+    local pkg_postinst_body="$(declare -fp pkg_postinst 2>&1)"
+    local pkg_postrm_body="$(declare -fp pkg_postrm 2>&1)"
+
+    if [[ ${need_udev_reload} -eq 1 ]]; then
+	    if [[ ! ${pkg_postinst_body} == *udev_reload* ]]; then
+		    eqawarn "QA Notice: package is installing udev rules without calling"
+		    eqawarn "udev_reload in pkg_postinst phase"
+	    fi
+
+	    if [[ ! ${pkg_postrm_body} == *udev_reload* ]]; then
+		    eqawarn "QA Notice: package is installing udev rules without calling"
+		    eqawarn "udev_reload in pkg_postrm phase"
+	    fi
+    fi
 }
 
 udev_rules_check
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.