From 42238f4ff13ae6c75bc1925f366429a35c26317d Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Sun, 26 May 2019 23:11:28 -0700 Subject: [PATCH] write_make_conf: support multi-line GENTOO_MIRRORS (bug 543814) Use shlex to support multi-line GENTOO_MIRRORS assignments. Bug: https://bugs.gentoo.org/543814 Signed-off-by: Zac Medico --- .gitignore | 1 - mirrorselect/configs.py | 33 +++++++++++++++++++++++----- setup.py | 37 +++++++++++++++---------------- tests/__init__.py | 0 tests/test_write_make_conf.py | 41 +++++++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 26 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/test_write_make_conf.py diff --git a/.gitignore b/.gitignore index f7a7e7e..8e480b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ *.py[co] testing* -test* *.geany build* .gitignore diff --git a/mirrorselect/configs.py b/mirrorselect/configs.py index 9fa4f2c..8c4b4df 100644 --- a/mirrorselect/configs.py +++ b/mirrorselect/configs.py @@ -4,7 +4,7 @@ """Mirrorselect 2.x Tool for selecting Gentoo source and rsync mirrors. -Copyright 2005-2012 Gentoo Foundation +Copyright 2005-2019 Gentoo Authors Copyright (C) 2005 Colin Kingsley Copyright (C) 2008 Zac Medico @@ -75,10 +75,32 @@ def write_make_conf(output, config_path, var, mirror_string): except IOError: lines = [] - regex = re.compile('^%s=.*' % var) - for line in lines: - if regex.match(line): - lines.remove(line) + with open(config_path + '.backup', 'r') as f: + lex = shlex.shlex(f, posix=True) + lex.wordchars = string.digits + letters + r"~!@#$%*_\:;?,./-+{}" + lex.quotes = "\"'" + while True: + key = lex.get_token() + + if key == var: + begin_line = lex.lineno + equ = lex.get_token() + if equ is None: + break + if equ != '=': + continue + + val = lex.get_token() + if val is None: + break + end_line = lex.lineno + + new_lines = [] + for index, line in enumerate(lines): + if index < begin_line - 1 or index >= end_line - 1: + new_lines.append(line) + lines = new_lines + break lines.append(mirror_string) @@ -92,7 +114,6 @@ def write_make_conf(output, config_path, var, mirror_string): config.close() output.print_info('Done.\n') - sys.exit(0) def write_repos_conf(output, config_path, var, value): diff --git a/setup.py b/setup.py index 919dcce..5571711 100755 --- a/setup.py +++ b/setup.py @@ -8,9 +8,11 @@ import re import sys from distutils import core, log from distutils.command.sdist import sdist +from distutils.core import Command import os import io +import unittest __version__ = os.getenv('VERSION', default=os.getenv('PVR', default='9999')) @@ -80,26 +82,23 @@ class x_sdist(sdist): sdist.finalize_options(self) -def load_test(): - """Only return the real test class if it's actually being run so that we - don't depend on snakeoil just to install.""" +class TestCommand(Command): + user_options = [] - desc = "run the test suite" - if 'test' in sys.argv[1:]: - try: - from snakeoil import distutils_extensions - except ImportError: - sys.stderr.write("Error: We depend on dev-python/snakeoil ") - sys.stderr.write("to run tests.\n") - sys.exit(1) - class test(distutils_extensions.test): - description = desc - default_test_namespace = 'mirrorselect.test' - else: - class test(core.Command): - description = desc + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + suite = unittest.TestSuite() + tests = unittest.defaultTestLoader.discover('tests') + suite.addTests(tests) + result = unittest.TextTestRunner(verbosity=2).run(suite) + if result.errors or result.failures: + raise SystemExit(1) - return test test_data = { 'mirrorselect': [ @@ -125,7 +124,7 @@ core.setup( ['mirrorselect.8']), ), cmdclass={ - 'test': load_test(), + 'test': TestCommand, 'sdist': x_sdist, 'set_version': set_version, }, diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_write_make_conf.py b/tests/test_write_make_conf.py new file mode 100644 index 0000000..3dedd93 --- /dev/null +++ b/tests/test_write_make_conf.py @@ -0,0 +1,41 @@ +# Copyright 2019 Gentoo Authors + +import os +import shutil +import tempfile +import unittest + +from mirrorselect.configs import write_make_conf +from mirrorselect.output import Output + + +class WriteMakeConfTestCase(unittest.TestCase): + def test_write_make_conf(self): + + var = 'GENTOO_MIRRORS' + mirror_string = '{}="a b"'.format(var) + + cases = ( + ('{}="foo\nbar"\n'.format(var), '{}\n'.format(mirror_string)), + ('\n{}="foo\nbar"\n'.format(var), '\n{}\n'.format(mirror_string)), + ('\n{}="foo bar"\n'.format(var), '\n{}\n'.format(mirror_string)), + ('\n{}="foo bar"\n\n'.format(var), '\n\n{}\n'.format(mirror_string)), + ('\n{}="foo \\\nbar"\n'.format(var), '\n{}\n'.format(mirror_string)), + ('\n\n{}="foo \\\nbar"\n'.format(var), '\n\n{}\n'.format(mirror_string)), + ('\n\n{}="foo \\\nbar"\na="b"\n'.format(var), '\n\na="b"\n{}\n'.format(mirror_string)), + ) + + for make_conf, expected_result in cases: + tempdir = tempfile.mkdtemp() + status_output = open(os.devnull, 'w') + try: + config_path = os.path.join(tempdir, 'make.conf') + with open(config_path, 'wt') as f: + f.write(make_conf) + write_make_conf(Output(out=status_output), config_path, var, mirror_string) + with open(config_path, 'rt') as f: + result = f.read() + self.assertEqual(result, expected_result) + finally: + shutil.rmtree(tempdir) + status_output.close() -- 2.21.0