From 63d41a1053bd8b03ddda130d7129d233f97ac671 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Sun, 25 Oct 2020 21:10:27 +0100 Subject: [PATCH] [type/__uci_section] Improve --match support with existing named sections Use section if named section exists without --match option (e.g. empty section). --- cdist/conf/type/__uci_section/explorer/match | 80 +++++++++++++------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/cdist/conf/type/__uci_section/explorer/match b/cdist/conf/type/__uci_section/explorer/match index a5619d4e..0768e404 100644 --- a/cdist/conf/type/__uci_section/explorer/match +++ b/cdist/conf/type/__uci_section/explorer/match @@ -20,62 +20,84 @@ # This explorer determines the "prefix" of the --type section matching --match # if set, or __object_id otherwise. +RS=$(printf '\036') +NL=$(printf '\n '); NL=${NL% } + squote_values() { sed -e '/=".*"$/{s/="/='\''/;s/"$/'\''/}' \ -e "/='.*'$/"'!{s/=/='\''/;s/$/'\''/}' } +count_lines() ( + IFS=${NL?} + # shellcheck disable=SC2048,SC2086 + set -f -- $*; echo $# +) -RS=$(printf '\036') - -if ! test -e "${__object:?}/parameter/match" -then - if ! echo "${__object_id:?}" | grep -q -e '^[^.]\{1,\}\.[^.]\{1,\}$' - then - echo 'Section identifiers are a package and section name separated by a "." (period).' >&2 - exit 1 - fi +echo "${__object_id:?}" | grep -q -e '^[^.]\{1,\}\.[^.]\{1,\}$' || { + echo 'Section identifiers are a package and section name separated by a "." (period).' >&2 + exit 1 +} +test -s "${__object:?}/parameter/match" || { # If no --match is given, we take the __object_id as the section identifier. echo "${__object_id:?}" exit 0 -fi - -# shellcheck disable=SC2015 -test -s "${__object:?}/parameter/match" && test -s "${__object:?}/parameter/type" \ -|| { +} +test -s "${__object:?}/parameter/type" || { echo 'Parameters --match and --type must be used together.' >&2 exit 1 } -# Find by match -# NOTE: Apart from section types all values are printed in single quotes by UCI. -match=$(head -n 1 "${__object:?}/parameter/match" | squote_values) - -if ! grep -q -e '^[^.]\{1,\}\.[^.]\{1,\}$' "${__object:?}/parameter/type" -then +sect_type_param=$(cat "${__object:?}/parameter/type") +expr "${sect_type_param}" : '[^.]\{1,\}\.[^.]\{1,\}$' >/dev/null 2>&1 || { echo 'Section types are a package name and section type separated by a "." (period).' >&2 exit 1 +} +package_filter=${sect_type_param%%.*} +section_filter=${sect_type_param#*.} + +# Find by --match +# NOTE: Apart from section types all values are printed in single quotes by uci show. +match=$(head -n 1 "${__object:?}/parameter/match" | squote_values) + +if uci -s -N get "${__object_id:?}" >/dev/null 2>&1 +then + # Named section exists: ensure if --match applies to it + # if the "matched" option does not exist (e.g. empty section) we use the + # section unconditionally. + if match_value_is=$(uci -s -N get "${__object_id:?}.${match%%=*}" 2>/dev/null) + then + match_value_should=$(expr "${match}" : ".*='\\(.*\\)'$") + + test "${match_value_is}" = "${match_value_should}" || { + printf 'Named section "%s" does not match --match "%s"\n' \ + "${__object_id:?}" "${match}" >&2 + exit 1 + } + fi + + echo "${__object_id:?}" + exit 0 fi -sect_type_filter=$(cat "${__object:?}/parameter/type") -package_filter=${sect_type_filter%%.*} -section_filter=${sect_type_filter#*.} -# FIXME: Does not work with named sections -regex="^${package_filter}\.@${section_filter}\[[0-9]\{1,\}\]\.${match%%=*}=" +# No correctly named section exists already: find one to which --match applies +regex="^${package_filter}\\.@${section_filter}\\[[0-9]\\{1,\\}\\]\\.${match%%=*}=" matched_sections=$( uci -s -N -d "${RS}" show "${package_filter}" 2>/dev/null \ | grep -e "${regex}" \ | while read -r _line do - if test "${_line#*=}" = "${match#*=}"; then echo "${_line}"; fi + if test "${_line#*=}" = "${match#*=}" + then + echo "${_line}" + fi done \ | sed -e 's/\.[^.]*=.*$//') -if test "$(echo "${matched_sections}" | wc -l)" -gt 1 -then +test "$(count_lines "${matched_sections}")" -le 1 || { printf 'Found multiple matching sections:\n%s\n' "${matched_sections}" >&2 exit 1 -fi +} echo "${matched_sections}"