Skip to content

Commit a55286a

Browse files
badFizzadar
authored andcommitted
files.line, crontab.crontab: actually delete lines when present=False
* operations/utils/files.py: Add sed_delete(). Factor out common code from sed_replace and sed_delete into _sed_command(). Add _set_delete_builder() and _sed_replace_builder() to build the actual sed expression. * operations/files.py line(): use sed_delete(). * operations/crontab.py crontab(): use sed_delete(). * tests/operations/apt.repo/remove.json, tests/operations/bsdinit.service/disabled.json, tests/operations/crontab.crontab.remove.json: adjust expected commands.
1 parent b1dcf16 commit a55286a

File tree

6 files changed

+59
-11
lines changed

6 files changed

+59
-11
lines changed

pyinfra/operations/crontab.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from pyinfra.api import StringCommand, operation
77
from pyinfra.api.util import try_int
88
from pyinfra.facts.crontab import Crontab, CrontabFile
9-
from pyinfra.operations.util.files import sed_replace
9+
from pyinfra.operations.util.files import sed_delete, sed_replace
1010

1111

1212
@operation()
@@ -111,7 +111,7 @@ def comma_sep(value):
111111
# Don't want the cron and it does exist? Remove the line
112112
if not present and exists:
113113
edit_commands.append(
114-
sed_replace(
114+
sed_delete(
115115
temp_filename,
116116
existing_crontab_match,
117117
"",

pyinfra/operations/files.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,14 @@
5656
from pyinfra.facts.server import Date, Which
5757

5858
from .util import files as file_utils
59-
from .util.files import adjust_regex, ensure_mode_int, get_timestamp, sed_replace, unix_path_join
59+
from .util.files import (
60+
adjust_regex,
61+
ensure_mode_int,
62+
get_timestamp,
63+
sed_delete,
64+
sed_replace,
65+
unix_path_join,
66+
)
6067

6168

6269
@operation()
@@ -427,9 +434,9 @@ def line(
427434
else:
428435
host.noop('line "{0}" exists in {1}'.format(replace or line, path))
429436

430-
# Line(s) exists and we want to remove them, replace with nothing
437+
# Line(s) exists and we want to remove them
431438
elif present_lines and not present:
432-
yield sed_replace(
439+
yield sed_delete(
433440
path,
434441
match_line,
435442
"",

pyinfra/operations/util/files.py

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import re
44
from datetime import datetime
5+
from typing import Callable
56

67
from pyinfra.api import QuoteString, StringCommand
78

@@ -32,13 +33,55 @@ def get_timestamp() -> str:
3233
return datetime.now().strftime("%y%m%d%H%M")
3334

3435

36+
_sed_ignore_case = re.compile("[iI]")
37+
38+
39+
def _sed_delete_builder(line: str, replace: str, flags: str, interpolate_variables: bool) -> str:
40+
return (
41+
'"/{0}/{1}d"' if interpolate_variables else # fmt: skip
42+
"'/{0}/{1}d'"
43+
).format(line, "I" if _sed_ignore_case.search(flags) else "")
44+
45+
46+
def sed_delete(
47+
filename: str,
48+
line: str,
49+
replace: str,
50+
flags: list[str] | None = None,
51+
backup=False,
52+
interpolate_variables=False,
53+
) -> StringCommand:
54+
return _sed_command(**locals(), sed_script_builder=_sed_delete_builder)
55+
56+
57+
def _sed_replace_builder(line: str, replace: str, flags: str, interpolate_variables: bool) -> str:
58+
return (
59+
'"s/{0}/{1}/{2}"' if interpolate_variables else # fmt: skip
60+
"'s/{0}/{1}/{2}'"
61+
).format(line, replace, flags)
62+
63+
3564
def sed_replace(
3665
filename: str,
3766
line: str,
3867
replace: str,
3968
flags: list[str] | None = None,
4069
backup=False,
4170
interpolate_variables=False,
71+
) -> StringCommand:
72+
return _sed_command(**locals(), sed_script_builder=_sed_replace_builder)
73+
74+
75+
def _sed_command(
76+
filename: str,
77+
line: str,
78+
replace: str,
79+
flags: list[str] | None = None,
80+
backup=False,
81+
interpolate_variables=False,
82+
# Python requires a default value here, so use _sed_replace_builder for
83+
# backwards compatibility.
84+
sed_script_builder: Callable[[str, str, str, bool], str] = _sed_replace_builder,
4285
) -> StringCommand:
4386
flags_str = "".join(flags) if flags else ""
4487

@@ -51,15 +94,13 @@ def sed_replace(
5194
if interpolate_variables:
5295
line = line.replace('"', '\\"')
5396
replace = replace.replace('"', '\\"')
54-
sed_script_formatter = '"s/{0}/{1}/{2}"'
5597
else:
5698
# Single quotes cannot contain other single quotes, even when escaped , so turn
5799
# each ' into '"'"' (end string, double quote the single quote, (re)start string)
58100
line = line.replace("'", "'\"'\"'")
59101
replace = replace.replace("'", "'\"'\"'")
60-
sed_script_formatter = "'s/{0}/{1}/{2}'"
61102

62-
sed_script = sed_script_formatter.format(line, replace, flags_str)
103+
sed_script = sed_script_builder(line, replace, flags_str, interpolate_variables)
63104

64105
sed_command = StringCommand(
65106
"sed",

tests/operations/apt.repo/remove.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
}
1717
},
1818
"commands": [
19-
"sed -i.a-timestamp 's/^.*deb http:\\/\\/archive\\.canonical\\.com\\/ubuntu hardy partner.*$//' /etc/apt/sources.list && rm -f /etc/apt/sources.list.a-timestamp"
19+
"sed -i.a-timestamp '/^.*deb http:\\/\\/archive\\.canonical\\.com\\/ubuntu hardy partner.*$/d' /etc/apt/sources.list && rm -f /etc/apt/sources.list.a-timestamp"
2020
]
2121
}

tests/operations/bsdinit.service/disabled.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
}
1616
},
1717
"commands": [
18-
"sed -i.a-timestamp 's/^nginx_enable=.*$//' /etc/rc.conf.local && rm -f /etc/rc.conf.local.a-timestamp"
18+
"sed -i.a-timestamp '/^nginx_enable=.*$/d' /etc/rc.conf.local && rm -f /etc/rc.conf.local.a-timestamp"
1919
]
2020
}

tests/operations/crontab.crontab/remove.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
},
2020
"commands": [
2121
"crontab -l > _tempfile_",
22-
"sed -i.a-timestamp 's/.*this_is_a_command.*//' _tempfile_ && rm -f _tempfile_.a-timestamp",
22+
"sed -i.a-timestamp '/.*this_is_a_command.*/d' _tempfile_ && rm -f _tempfile_.a-timestamp",
2323
"crontab _tempfile_"
2424
]
2525
}

0 commit comments

Comments
 (0)