From 356da62750082d28dca54ef9d1ecc8ecc2f1ca97 Mon Sep 17 00:00:00 2001 From: William Douglas Date: Wed, 24 Jul 2024 15:59:53 -0700 Subject: [PATCH] Enable working with Jinja2 spec templates Allow autospec to handle building packages that use a Jinja2 formatted *.spec.template file. Currently only package_name, package_version, package_release and package_url fields are supported but others can be added as needed (patches and archives are good next steps). Signed-off-by: William Douglas --- autospec/autospec.py | 9 +++++++-- autospec/specfiles.py | 43 ++++++++++++++++++++++++++++++++++++------ tests/test_specfile.py | 15 +-------------- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/autospec/autospec.py b/autospec/autospec.py index 673b24fa..97a36b06 100644 --- a/autospec/autospec.py +++ b/autospec/autospec.py @@ -269,9 +269,13 @@ def package(args, url, name, archives, workingdir): pkg_integrity.check(url, conf, interactive=interactive_mode) pkg_integrity.load_specfile(specfile) - specfile.write_spec() + spec_type = specfile.write_spec() + while 1: package.package(filemanager, args.mock_config, args.mock_opts, conf, requirements, content, args.cleanup) + if spec_type == "template": + # specfile template is assumed "correct" and any failures need to be manually addressed + break filemanager.load_specfile(specfile) specfile.write_spec() filemanager.newfiles_printed = 0 @@ -304,7 +308,8 @@ def package(args, url, name, archives, workingdir): except Exception: pass - check.check_regression(conf.download_path, conf.config_opts['skip_tests'], package.round - 1) + if spec_type == "generate": + check.check_regression(conf.download_path, conf.config_opts['skip_tests'], package.round - 1) examine_abi(conf.download_path, content.name) if os.path.exists("/var/lib/rpm"): diff --git a/autospec/specfiles.py b/autospec/specfiles.py index 7c11ffdb..6165175e 100644 --- a/autospec/specfiles.py +++ b/autospec/specfiles.py @@ -26,6 +26,8 @@ from collections import OrderedDict import git +from jinja2 import Environment +from jinja2.loaders import DictLoader from util import _file_write, open_auto AVX2_CFLAGS = "-march=x86-64-v3" @@ -73,12 +75,42 @@ def __init__(self, url, version, name, release, config, requirements, content): def write_spec(self): """Write spec file.""" - self.specfile = open_auto("{}/{}.spec".format(self.config.download_path, self.name), "w") + spec_path = f"{os.path.join(self.config.download_path, self.name)}.spec" + self.specfile = open_auto(spec_path, "w") self.specfile.write_strip = types.MethodType(_file_write, self.specfile) + # last chance to sanitize url for template and build types + if self.config.urlban: + clean_url = re.sub(self.config.urlban, "localhost", self.url) + # Duplicate prefixes entry before we change the url + self.content.prefixes[clean_url] = self.content.prefixes.get(self.url) + self.url = clean_url + + template_path = f"{spec_path}.template" + + if os.path.isfile(template_path): + # make templates have a template build pattern + self.config.default_pattern = "template" # spec file comment header self.write_comment_header() + if os.path.isfile(template_path): + with open_auto(template_path) as tfile: + template_content = tfile.read() + template = Environment(loader=DictLoader({'spec': template_content})).get_template('spec') + kw = { + 'package_name': self.name, + 'package_version': self.version, + 'package_url': self.url, + 'package_release': self.release, + } + self.specfile.write(template.render(**kw)) + self.specfile.write_strip('\n') + self.specfile.close() + # return specfile type built so autospec knows how to + # handle build results (template should only builds once) + return "template" + if self.config.config_opts.get('keepstatic'): self._write("%define keepstatic 1\n") @@ -110,6 +142,10 @@ def write_spec(self): self.specfile.close() + # return specfile type built so autospec knows how to + # handle build results (generate has multiple builds) + return "generate" + def write_comment_header(self): """Write comment header to spec file.""" self._write("#\n") @@ -132,11 +168,6 @@ def write_comment_header(self): def write_nvr(self): """Write name, version, and release information.""" - if self.config.urlban: - clean_url = re.sub(self.config.urlban, "localhost", self.url) - # Duplicate prefixes entry before we change the url - self.content.prefixes[clean_url] = self.content.prefixes.get(self.url) - self.url = clean_url self._write("Name : {}\n".format(self.name)) self._write("Version : {}\n".format(self.version)) self._write("Release : {}\n".format(str(self.release))) diff --git a/tests/test_specfile.py b/tests/test_specfile.py index 9db6e72d..3b5cbbe1 100644 --- a/tests/test_specfile.py +++ b/tests/test_specfile.py @@ -47,7 +47,7 @@ def test_write_comment_header(self): self.WRITES = self.WRITES[:4] + self.WRITES[6:] self.assertEqual(expect, self.WRITES) - def test_write_nvr_no_urlban(self): + def test_write_nvr(self): """ test Specfile.write_nvr with no urlban set """ @@ -59,19 +59,6 @@ def test_write_nvr_no_urlban(self): "Source0 : http://www.testpkg.com/testpkg/pkg-1.0.tar.gz\n"] self.assertEqual(expect, self.WRITES) - def test_write_nvr_urlban(self): - """ - test Specfile.write_nvr with urlban set - """ - self.specfile.config.urlban = "www.testpkg.com" - self.specfile.write_nvr() - expect = ["Name : pkg\n", - "Version : 1.0\n", - "Release : 2\n", - "URL : http://localhost/testpkg/pkg-1.0.tar.gz\n", - "Source0 : http://localhost/testpkg/pkg-1.0.tar.gz\n"] - self.assertEqual(expect, self.WRITES) - def test_write_sources(self): """ test write_sources with all Specfile.sources set.