[__line] Add support for '--state replace'

It is currently counter-intuitive that something like:

    # File '/thing' contents
    #SomeSetting WrongValue

    # Manifest
    __line '/thing' \
           --line 'SomeSeting GoodValue' \
           --regex '^(#[[:space:]]*)?SomeSetting[[:space:]]'

Produces:

    # Resulting '/thing' contents
    #SomeSetting WrongValue

This makes sense given the implementation, but it masks a very common use-case.

Changing the default behaviour for such a base type is not really an option, so
instead we add a `replace` as a valid value for `--state`, which would result
in:

    # Resulting '/thing' contents with: --state replace
    SomeSetting GoodValue

For compatibility, if the regex is missing, `--state replace` behaves just as
`--state present`.
This commit is contained in:
evilham 2020-10-09 06:51:44 +02:00 committed by Darko Poljak
parent 652c891858
commit c030deea3d
3 changed files with 29 additions and 6 deletions

View file

@ -53,8 +53,10 @@ function _find(_text, _pattern) {
BEGIN { BEGIN {
getline anchor < (ENVIRON["__object"] "/parameter/" position) getline anchor < (ENVIRON["__object"] "/parameter/" position)
getline pattern < (ENVIRON["__object"] "/parameter/" needle) getline pattern < (ENVIRON["__object"] "/parameter/" needle)
getline line < (ENVIRON["__object"] "/parameter/line")
found_line = 0 found_line = 0
correct_line = 0
correct_pos = (position != "after" && position != "before") correct_pos = (position != "after" && position != "before")
} }
{ {
@ -63,15 +65,18 @@ BEGIN {
getline getline
if (_find($0, pattern)) { if (_find($0, pattern)) {
found_line++ found_line++
if (index($0, line) == 1) { correct_line++ }
correct_pos = 1 correct_pos = 1
exit 0 exit 0
} }
} else if (_find($0, pattern)) { } else if (_find($0, pattern)) {
found_line++ found_line++
if (index($0, line) == 1) { correct_line++ }
} }
} else if (position == "before") { } else if (position == "before") {
if (_find($0, pattern)) { if (_find($0, pattern)) {
found_line++ found_line++
if (index($0, line) == 1) { correct_line++ }
getline getline
if (match($0, anchor)) { if (match($0, anchor)) {
correct_pos = 1 correct_pos = 1
@ -81,13 +86,18 @@ BEGIN {
} else { } else {
if (_find($0, pattern)) { if (_find($0, pattern)) {
found_line++ found_line++
if (index($0, line) == 1) { correct_line++ }
exit 0 exit 0
} }
} }
} }
END { END {
if (found_line && correct_pos) { if (found_line && correct_pos) {
if (correct_line) {
print "present" print "present"
} else {
print "matching"
}
} else if (found_line) { } else if (found_line) {
print "wrongposition" print "wrongposition"
} else { } else {

View file

@ -38,7 +38,11 @@ if [ -z "$state_is" ]; then
exit 1 exit 1
fi fi
if [ "$state_should" = "$state_is" ]; then if [ "$state_should" = "$state_is" ] || \
{ [ "$state_should" = "present" ] && [ "$state_is" = "matching" ] ;} || \
{ [ "$state_should" = "replace" ] && [ "$state_is" = "present" ] ;} ; then
# If state matches already, or 'present' is used and regex matches
# or 'replace' is used and the exact line is present, then there is
# nothing to do # nothing to do
exit 0 exit 0
fi fi
@ -61,8 +65,8 @@ fi
add=0 add=0
remove=0 remove=0
case "$state_should" in case "$state_should" in
present) present|replace)
if [ "$state_is" = "wrongposition" ]; then if [ "$state_is" = "wrongposition" ] || [ "$state_is" = "matching" ]; then
echo updated >> "$__messages_out" echo updated >> "$__messages_out"
remove=1 remove=1
else else

View file

@ -31,7 +31,7 @@ file
line line
Specifies the line which should be absent or present. Specifies the line which should be absent or present.
Must be present, if state is 'present'. Must be present, if state is 'present' or 'replace'.
Ignored if regex is given and state is 'absent'. Ignored if regex is given and state is 'absent'.
regex regex
@ -41,10 +41,13 @@ regex
If state is 'absent', ensure all lines matching the regular expression If state is 'absent', ensure all lines matching the regular expression
are absent. are absent.
If state is 'replace', ensure all lines matching the regular expression
are exactly 'line'.
The regular expression is interpreted by awk's match function. The regular expression is interpreted by awk's match function.
state state
'present' or 'absent', defaults to 'present' 'present', 'absent' or 'replace', defaults to 'present'.
onchange onchange
The code to run if line is added, removed or updated. The code to run if line is added, removed or updated.
@ -99,6 +102,12 @@ EXAMPLES
--line '-session required pam_exec.so debug log=/tmp/classify.log /usr/local/libexec/classify' \ --line '-session required pam_exec.so debug log=/tmp/classify.log /usr/local/libexec/classify' \
--after '^session[[:space:]]+include[[:space:]]+password-auth-ac$' --after '^session[[:space:]]+include[[:space:]]+password-auth-ac$'
# Uncomment as needed and set a value in a configuration file.
__line /etc/example.conf \
--line 'SomeSetting SomeValue' \
--regex '^(#[[:space:]]*)?SomeSetting[[:space:]]' \
--state replace
SEE ALSO SEE ALSO
-------- --------