Fix trailing newlines on Windows (#39842).

The file module incorrectly handled trailing newline characters in
files when running on Windows. This hand the consequence that a
trailing newline character was always removed from a file handled by
the file module, even if it was present in the reference file or
contents.

This is fixed now so that a managed file will have a trailing newline
character if and only if the reference file or contents have a trailing
newline character.
This commit is contained in:
Sebastian Marsching 2017-03-08 12:06:18 +01:00
parent 6d0f15c31a
commit 76cb7bf612
2 changed files with 32 additions and 6 deletions

View file

@ -137,6 +137,26 @@ def _get_bkroot():
return os.path.join(__salt__['config.get']('cachedir'), 'file_backup')
def _splitlines_preserving_trailing_newline(str):
'''
Returns a list of the lines in the string, breaking at line boundaries and
preserving a trailing newline (if present).
Essentially, this works like ``str.striplines(False)`` but preserves an
empty line at the end. This is equivalent to the following code:
.. code-block:: python
lines = str.splitlines()
if str.endswith('\n') or str.endswith('\r'):
lines.append('')
'''
lines = str.splitlines()
if str.endswith('\n') or str.endswith('\r'):
lines.append('')
return lines
def gid_to_group(gid):
'''
Convert the group id to the group name on this system
@ -1837,8 +1857,10 @@ def line(path, content, match=None, mode=None, location=None,
if changed:
if show_changes:
with salt.utils.fopen(path, 'r') as fp_:
path_content = fp_.read().splitlines()
changes_diff = ''.join(difflib.unified_diff(path_content, body.splitlines()))
path_content = _splitlines_preserving_trailing_newline(
fp_.read())
changes_diff = ''.join(difflib.unified_diff(
path_content, _splitlines_preserving_trailing_newline(body)))
if __opts__['test'] is False:
fh_ = None
try:
@ -4425,7 +4447,8 @@ def check_file_meta(
tmp = salt.utils.mkstemp(prefix=salt.utils.files.TEMPFILE_PREFIX,
text=True)
if salt.utils.is_windows():
contents = os.linesep.join(contents.splitlines())
contents = os.linesep.join(
_splitlines_preserving_trailing_newline(contents))
with salt.utils.fopen(tmp, 'w') as tmp_:
tmp_.write(str(contents))
# Compare the static contents with the named file
@ -4700,7 +4723,8 @@ def manage_file(name,
tmp = salt.utils.mkstemp(prefix=salt.utils.files.TEMPFILE_PREFIX,
text=True)
if salt.utils.is_windows():
contents = os.linesep.join(contents.splitlines())
contents = os.linesep.join(
_splitlines_preserving_trailing_newline(contents))
with salt.utils.fopen(tmp, 'w') as tmp_:
tmp_.write(str(contents))
@ -4885,7 +4909,8 @@ def manage_file(name,
tmp = salt.utils.mkstemp(prefix=salt.utils.files.TEMPFILE_PREFIX,
text=True)
if salt.utils.is_windows():
contents = os.linesep.join(contents.splitlines())
contents = os.linesep.join(
_splitlines_preserving_trailing_newline(contents))
with salt.utils.fopen(tmp, 'w') as tmp_:
tmp_.write(str(contents))
# Copy into place

View file

@ -59,7 +59,8 @@ from salt.modules.file import (check_hash, # pylint: disable=W0611
touch, append, contains, contains_regex, get_source_sum,
contains_glob, find, psed, get_sum, _get_bkroot, _mkstemp_copy,
get_hash, manage_file, file_exists, get_diff, line, list_backups,
__clean_tmp, check_file_meta, _binary_replace, restore_backup,
__clean_tmp, check_file_meta, _binary_replace,
_splitlines_preserving_trailing_newline, restore_backup,
access, copy, readdir, rmdir, truncate, replace, delete_backup,
search, _get_flags, extract_hash, _error, _sed_esc, _psed,
RE_FLAG_TABLE, blockreplace, prepend, seek_read, seek_write, rename,