configure_file: preserve newlines of the input file. Fixes #4817

In some cases (see #4817) it's helpful if the output file uses the
same newlines as the input file without translating them to the
platform defaults.

open() by default recognizes all newline styles and translates them
to "\n" and then to the platform default when writing.
Passing "" to "newline" disables the translation and lets us pass through
the original newline characters.
pull/4848/head
Christoph Reiter 6 years ago committed by Jussi Pakkanen
parent b45c367d92
commit 8df5afc98a
  1. 4
      mesonbuild/mesonlib.py
  2. 34
      run_unittests.py

@ -729,7 +729,7 @@ def do_mesondefine(line, confdata):
def do_conf_file(src, dst, confdata, format, encoding='utf-8'): def do_conf_file(src, dst, confdata, format, encoding='utf-8'):
try: try:
with open(src, encoding=encoding) as f: with open(src, encoding=encoding, newline='') as f:
data = f.readlines() data = f.readlines()
except Exception as e: except Exception as e:
raise MesonException('Could not read input file %s: %s' % (src, str(e))) raise MesonException('Could not read input file %s: %s' % (src, str(e)))
@ -763,7 +763,7 @@ def do_conf_file(src, dst, confdata, format, encoding='utf-8'):
result.append(line) result.append(line)
dst_tmp = dst + '~' dst_tmp = dst + '~'
try: try:
with open(dst_tmp, 'w', encoding=encoding) as f: with open(dst_tmp, 'w', encoding=encoding, newline='') as f:
f.writelines(result) f.writelines(result)
except Exception as e: except Exception as e:
raise MesonException('Could not write output file %s: %s' % (dst, str(e))) raise MesonException('Could not write output file %s: %s' % (dst, str(e)))

@ -30,6 +30,7 @@ import functools
from itertools import chain from itertools import chain
from unittest import mock from unittest import mock
from configparser import ConfigParser from configparser import ConfigParser
from contextlib import contextmanager
from glob import glob from glob import glob
from pathlib import (PurePath, Path) from pathlib import (PurePath, Path)
@ -192,6 +193,24 @@ def skip_if_not_base_option(feature):
return actual return actual
@contextmanager
def temp_filename():
'''A context manager which provides a filename to an empty temporary file.
On exit the file will be deleted.
'''
fd, filename = tempfile.mkstemp()
os.close(fd)
try:
yield filename
finally:
try:
os.remove(filename)
except OSError:
pass
class PatchModule: class PatchModule:
''' '''
Fancy monkey-patching! Whee! Can't use mock.patch because it only Fancy monkey-patching! Whee! Can't use mock.patch because it only
@ -1296,6 +1315,21 @@ class AllPlatformTests(BasePlatformTests):
prefix = opt['value'] prefix = opt['value']
self.assertEqual(prefix, '/absoluteprefix') self.assertEqual(prefix, '/absoluteprefix')
def test_do_conf_file_preserve_newlines(self):
def conf_file(in_data, confdata):
with temp_filename() as fin:
with open(fin, 'wb') as fobj:
fobj.write(in_data.encode('utf-8'))
with temp_filename() as fout:
mesonbuild.mesonlib.do_conf_file(fin, fout, confdata, 'meson')
with open(fout, 'rb') as fobj:
return fobj.read().decode('utf-8')
confdata = {'VAR': ('foo', 'bar')}
self.assertEqual(conf_file('@VAR@\n@VAR@\n', confdata), 'foo\nfoo\n')
self.assertEqual(conf_file('@VAR@\r\n@VAR@\r\n', confdata), 'foo\r\nfoo\r\n')
def test_absolute_prefix_libdir(self): def test_absolute_prefix_libdir(self):
''' '''
Tests that setting absolute paths for --prefix and --libdir work. Can't Tests that setting absolute paths for --prefix and --libdir work. Can't

Loading…
Cancel
Save