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

View file

@ -38,7 +38,11 @@ if [ -z "$state_is" ]; then
exit 1
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
exit 0
fi
@ -61,8 +65,8 @@ fi
add=0
remove=0
case "$state_should" in
present)
if [ "$state_is" = "wrongposition" ]; then
present|replace)
if [ "$state_is" = "wrongposition" ] || [ "$state_is" = "matching" ]; then
echo updated >> "$__messages_out"
remove=1
else

View file

@ -31,7 +31,7 @@ file
line
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'.
regex
@ -41,10 +41,13 @@ regex
If state is 'absent', ensure all lines matching the regular expression
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.
state
'present' or 'absent', defaults to 'present'
'present', 'absent' or 'replace', defaults to 'present'.
onchange
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' \
--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
--------