diff options
-rw-r--r-- | pkgtools/url2pkg/Makefile | 5 | ||||
-rw-r--r-- | pkgtools/url2pkg/files/url2pkg.py | 44 | ||||
-rw-r--r-- | pkgtools/url2pkg/files/url2pkg_test.py | 89 |
3 files changed, 97 insertions, 41 deletions
diff --git a/pkgtools/url2pkg/Makefile b/pkgtools/url2pkg/Makefile index 30e8d8adf4e..4b996527164 100644 --- a/pkgtools/url2pkg/Makefile +++ b/pkgtools/url2pkg/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.103 2019/10/03 09:37:40 rillig Exp $ +# $NetBSD: Makefile,v 1.104 2019/10/05 19:24:35 rillig Exp $ PKGNAME= url2pkg-19.3.1 CATEGORIES= pkgtools @@ -22,7 +22,8 @@ do-extract: do-test: ${RUN} cd ${WRKSRC} && env PKGSRCDIR=${PKGSRCDIR} perl -I. url2pkg.t - ${RUN} cd ${WRKSRC} && env PKGSRCDIR=${PKGSRCDIR} ${PREFIX}/bin/pytest-${PYVERSSUFFIX} + ${RUN} cd ${WRKSRC} && env PKGSRCDIR=${PKGSRCDIR} MAKE=${MAKE:Q} \ + ${PREFIX}/bin/pytest-${PYVERSSUFFIX} .include "../../mk/bsd.prefs.mk" diff --git a/pkgtools/url2pkg/files/url2pkg.py b/pkgtools/url2pkg/files/url2pkg.py index eb4c7dcc69c..e6eb42ed68b 100644 --- a/pkgtools/url2pkg/files/url2pkg.py +++ b/pkgtools/url2pkg/files/url2pkg.py @@ -1,5 +1,5 @@ #! @PYTHONBIN@ -# $NetBSD: url2pkg.py,v 1.11 2019/10/05 18:00:09 rillig Exp $ +# $NetBSD: url2pkg.py,v 1.12 2019/10/05 19:24:35 rillig Exp $ # Copyright (c) 2019 The NetBSD Foundation, Inc. # All rights reserved. @@ -77,18 +77,19 @@ class Varassign: class Url2Pkg: def __init__(self): - self.make = '@MAKE@' + self.make = os.getenv('MAKE') or '@MAKE@' self.libdir = '@LIBDIR@' self.perl5 = '@PERL5@' - self.pkgsrcdir = '@PKGSRCDIR@' + self.pkgsrcdir = pathlib.Path(os.getenv('PKGSRCDIR') or '@PKGSRCDIR@') self.pythonbin = '@PYTHONBIN@' self.editor = os.getenv('PKGEDITOR') or os.getenv('EDITOR') or 'vi' - self.verbose = False + # the following are overridden in tests + self.pkgdir = pathlib.Path('.') + self.out = sys.stdout + self.err = sys.stderr - self.pkgdir = pathlib.Path('.') # only overridable for tests - self.out = sys.stdout # only overridable for tests - self.err = sys.stderr # only overridable for tests + self.verbose = False def debug(self, fmt: str, *args): if self.verbose: @@ -96,14 +97,14 @@ class Url2Pkg: self.err.write(f'url2pkg: {msg}\n') def find_package(self, pkgbase: str) -> str: - candidates = glob.glob(f'{self.pkgsrcdir}/*/{pkgbase}') + candidates = list(self.pkgsrcdir.glob(f'*/{pkgbase}')) self.debug('candidates for package {0} are {1}', pkgbase, candidates) if len(candidates) != 1: return '' - return candidates[0].replace(self.pkgsrcdir, '../..') + return str(candidates[0]).replace(str(self.pkgsrcdir), '../..') def bmake(self, *args: str) -> None: - self.debug('running bmake {0}', args) + self.debug('running bmake {0} in {1}', args, str(self.pkgdir)) subprocess.check_call([self.make, *args], cwd=self.pkgdir) def show_var(self, varname: str) -> str: @@ -367,8 +368,6 @@ class Generator: if self.master_sites != '': return - if '/' not in self.url: - sys.exit(f'error: URL "{self.url}" must have at least one slash') base_url, self.distfile = re.search(r'^(.*/)(.*)$', self.url).groups() self.master_sites = base_url @@ -931,20 +930,21 @@ class Adjuster: self.up.bmake('distinfo') -def main(): +def main(argv: List[str], up: Url2Pkg): if not os.path.isfile('../../mk/bsd.pkg.mk'): - sys.exit(f'ERROR: {sys.argv[0]} must be run from a package directory (.../pkgsrc/category/package).') + sys.exit(f'{argv[0]}: must be run from a package directory (.../pkgsrc/category/package)') - up = Url2Pkg() try: - opts, args = getopt.getopt(sys.argv[1:], 'v', ['verbose']) + opts, args = getopt.getopt(argv[1:], 'v', ['verbose']) for (opt, _) in opts: if opt in ('-v', '--verbose'): up.verbose = True except getopt.GetoptError: - sys.exit(f'usage: {sys.argv[0]} [-v|--verbose] [URL]') + sys.exit(f'usage: {argv[0]} [-v|--verbose] [URL]') url = args[0] if args else input('URL: ') + if not re.fullmatch(r'\w+://[!-~]+?/[!-~]+', url): + sys.exit(f'url2pkg: invalid URL: {url}') if not up.pkgdir.glob('w*/.extract_done') or not (up.pkgdir / 'Makefile').is_file(): initial_lines = Generator(url).generate_package(up) @@ -953,11 +953,11 @@ def main(): Adjuster(up, url, initial_lines).adjust() - print('') - print('Remember to run pkglint when you\'re done.') - print('See ../../doc/pkgsrc.txt to get some help.') - print('') + up.out.write('\n') + up.out.write('Remember to run pkglint when you\'re done.\n') + up.out.write('See ../../doc/pkgsrc.txt to get some help.\n') + up.out.write('\n') if __name__ == '__main__': - main() + main(sys.argv, Url2Pkg()) diff --git a/pkgtools/url2pkg/files/url2pkg_test.py b/pkgtools/url2pkg/files/url2pkg_test.py index 810c6017563..d6641f7f155 100644 --- a/pkgtools/url2pkg/files/url2pkg_test.py +++ b/pkgtools/url2pkg/files/url2pkg_test.py @@ -1,19 +1,18 @@ -# $NetBSD: url2pkg_test.py,v 1.10 2019/10/05 18:00:09 rillig Exp $ +# $NetBSD: url2pkg_test.py,v 1.11 2019/10/05 19:24:35 rillig Exp $ import pytest from url2pkg import * mkcvsid = '# $''NetBSD$' up: Url2Pkg +prev_dir = pathlib.Path.cwd() def setup_function(_): global up up = Url2Pkg() - up.pkgsrcdir = os.getenv('PKGSRCDIR') - assert up.pkgsrcdir is not None - os.chdir(up.pkgsrcdir + '/pkgtools/url2pkg') + os.chdir(up.pkgsrcdir / 'pkgtools' / 'url2pkg') class Wr: def __init__(self) -> None: @@ -22,18 +21,19 @@ def setup_function(_): def write(self, s: str): self.buf += s - def output(self): + def written(self) -> List[str]: result = self.buf self.buf = '' - return result + return result.splitlines() up.out = Wr() up.err = Wr() def teardown_function(_): - assert up.out.output() == '' - assert up.err.output() == '' + os.chdir(str(prev_dir)) + assert up.out.written() == [] + assert up.err.written() == [] def str_vars(vars: List[Var]) -> List[str]: @@ -74,7 +74,7 @@ def test_Url2Pkg_debug(): up.debug('tuple {0}', (1, 2, 3)) up.debug('cwd {0} env {1} cmd {2}', 'directory', {'VAR': 'value'}, 'command') - assert up.err.output().splitlines() == [ + assert up.err.written() == [ 'url2pkg: plain message', 'url2pkg: list [1, 2, 3]', 'url2pkg: tuple (1, 2, 3)', @@ -88,7 +88,9 @@ def test_Url2Pkg_bmake(): up.bmake('hello', 'world') - assert up.err.output() == 'url2pkg: running bmake (\'hello\', \'world\')\n' + assert up.err.written() == [ + 'url2pkg: running bmake (\'hello\', \'world\') in \'.\'', + ] def test_Lines__write_and_read(tmp_path: pathlib.Path): @@ -532,8 +534,10 @@ def test_Generator_adjust_site_from_sites_mk__GNU(): def test_Generator_adjust_site_other__malformed_URL(): - error = 'error: URL "localhost" must have at least one slash' - with pytest.raises(SystemExit, match=error): + # This error is supposed to be handled by the URL check in main. + + error = "'NoneType' object has no attribute 'groups'" + with pytest.raises(AttributeError, match=error): Generator('localhost').generate_Makefile() @@ -939,7 +943,7 @@ def test_Adjuster_adjust_perl_module_Build_PL(tmp_path: pathlib.Path): adjuster.adjust_perl_module_Build_PL() assert str_vars(adjuster.build_vars) == ['PERL5_MODULE_TYPE=Module::Build'] - assert up.err.output().splitlines() == [ + assert up.err.written() == [ f'url2pkg: reading dependencies: cd \'{tmp_path}\' && env {{}} \'echo perl5 -I/libdir -I. Build.PL\'', 'url2pkg: unknown dependency line: \'perl5 -I/libdir -I. Build.PL\'' ] @@ -955,7 +959,7 @@ def test_Adjuster_adjust_perl_module_Makefile_PL(tmp_path: pathlib.Path): adjuster.adjust_perl_module_Makefile_PL() assert str_vars(adjuster.build_vars) == [] - assert up.err.output().splitlines() == [ + assert up.err.written() == [ f'url2pkg: reading dependencies: cd \'{tmp_path}\' && env {{}} \'echo perl5 -I/libdir -I. Makefile.PL\'', 'url2pkg: unknown dependency line: \'perl5 -I/libdir -I. Makefile.PL\'' ] @@ -1315,9 +1319,11 @@ def test_Adjuster_adjust_lines_python_module(tmp_path: pathlib.Path): '# url2pkg-marker (please do not remove this line.)', '.include "../../mk/bsd.pkg.mk"', ] - assert up.err.output() == (f"url2pkg: running ['true', " - f"'-f', '{tmp_path / 'try-pypi.mk'}', " - f"'distinfo'] to try PyPI\n") + + try_mk = tmp_path / 'try-pypi.mk' + assert up.err.written() == [ + f"url2pkg: running ['true', '-f', '{try_mk}', 'distinfo'] to try PyPI", + ] def test_Adjuster_adjust_lines_python_module__edited(): @@ -1340,3 +1346,52 @@ def test_Adjuster_adjust_lines_python_module__edited(): assert lines.get('GITHUB_PROJECT') == 'esptool' assert lines.index('TODO: Migrate MASTER_SITES to MASTER_SITE_PYPI') == 14 + + +def test_main__wrong_dir(tmp_path): + os.chdir(tmp_path) + error = r'url2pkg: must be run from a package directory' + + with pytest.raises(SystemExit, match=error): + main(['url2pkg'], up) + + +def test_main__unknown_option(): + with pytest.raises(SystemExit, match=r'usage:'): + main(['url2pkg', '--unknown'], up) + + +def test_main__verbose(): + with pytest.raises(SystemExit, match=r'url2pkg: invalid URL: broken URL'): + main(['url2pkg', '--verbose', 'broken URL'], up) + + +def test_main__valid_URL(): + import shutil + + up.editor = 'true' + up.make = os.getenv('MAKE') or sys.exit('MAKE must be set') + up.pkgdir = up.pkgsrcdir / 'pkgtools' / 'url2pkg-test-main' + up.pkgdir.is_dir() and shutil.rmtree(up.pkgdir) + try: + up.pkgdir.mkdir() + except OSError: + return # skip if the directory is not writable + os.chdir(up.pkgdir) + + main(['url2pkg', '-v', 'https://github.com/rillig/checkperms/archive/v1.12.tar.gz'], up) + + assert up.out.written() == [ + '', + 'Remember to run pkglint when you\'re done.', + 'See ../../doc/pkgsrc.txt to get some help.', + '', + ] + assert up.err.written() == [ + f'url2pkg: running bmake (\'distinfo\', \'extract\') in \'{up.pkgdir}\'', + 'url2pkg: Adjusting the Makefile', + ] + expected_files = ['DESCR', 'Makefile', 'PLIST', 'distinfo'] + assert sorted([f.name for f in up.pkgdir.glob("*")]) == expected_files + + shutil.rmtree(up.pkgdir) |