Add warning when using an empty regexp in lineinfile (#42013)

* Revert "Account for empty string regexp in lineinfile (#41451)"

This reverts commit 4b5b4a760c.

* Use context managers for interacting with files

* Store line and regexp parameters in a variable

* Add warning when regexp is an empty string

* Remove '=' from error messages

* Update warning message and add changelog

* Add tests

* Improve warning message

Offer an equivalent regexp that won't trigger the warning.
Update tests to match new warning.

* Add porting guide entry for lineinfile change
This commit is contained in:
Sam Doran 2018-06-29 20:15:43 -04:00 committed by Toshio Kuratomi
commit fb55038d75
4 changed files with 34 additions and 15 deletions

View file

@ -252,7 +252,7 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create,
if module._diff:
diff['before'] = to_native(b('').join(b_lines))
if regexp:
if regexp is not None:
bre_m = re.compile(to_bytes(regexp, errors='surrogate_or_strict'))
if insertafter not in (None, 'BOF', 'EOF'):
@ -268,7 +268,7 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create,
m = None
b_line = to_bytes(line, errors='surrogate_or_strict')
for lineno, b_cur_line in enumerate(b_lines):
if regexp:
if regexp is not None:
match_found = bre_m.search(b_cur_line)
else:
match_found = b_line == b_cur_line.rstrip(b('\r\n'))
@ -410,14 +410,14 @@ def absent(module, dest, regexp, line, backup):
if module._diff:
diff['before'] = to_native(b('').join(b_lines))
if regexp:
if regexp is not None:
bre_c = re.compile(to_bytes(regexp, errors='surrogate_or_strict'))
found = []
b_line = to_bytes(line, errors='surrogate_or_strict')
def matcher(b_cur_line):
if regexp:
if regexp is not None:
match_found = bre_c.search(b_cur_line)
else:
match_found = b_line == b_cur_line.rstrip(b('\r\n'))
@ -478,18 +478,24 @@ def main():
path = params['path']
firstmatch = params['firstmatch']
regexp = params['regexp']
line = params.get('line', None)
line = params['line']
if regexp == '':
module.warn(
"The regular expression is an empty string, which will match every line in the file. "
"This may have unintended consequences, such as replacing the last line in the file rather than appending. "
"If this is desired, use '^' to match every line in the file and avoid this warning.")
b_path = to_bytes(path, errors='surrogate_or_strict')
if os.path.isdir(b_path):
module.fail_json(rc=256, msg='Path %s is a directory !' % path)
if params['state'] == 'present':
if backrefs and not regexp:
module.fail_json(msg='regexp= is required with backrefs=true')
if backrefs and regexp is None:
module.fail_json(msg='regexp is required with backrefs=true')
if params.get('line', None) is None:
module.fail_json(msg='line= is required with state=present')
if line is None:
module.fail_json(msg='line is required with state=present')
# Deal with the insertafter default value manually, to avoid errors
# because of the mutually_exclusive mechanism.
@ -497,13 +503,11 @@ def main():
if ins_bef is None and ins_aft is None:
ins_aft = 'EOF'
line = params['line']
present(module, path, regexp, line,
ins_aft, ins_bef, create, backup, backrefs, firstmatch)
else:
if not regexp and line is None:
module.fail_json(msg='one of line= or regexp= is required with state=absent')
if regexp is None and line is None:
module.fail_json(msg='one of line or regexp is required with state=absent')
absent(module, path, regexp, line, backup)