From ca34f03e9f43397e82142e46ee4c14ec42a3b82a Mon Sep 17 00:00:00 2001 From: Stephen Coady Date: May 11 2021 16:33:21 +0000 Subject: feat: function to check whether a specfile uses rpmautospec Signed-off-by: Stephen Coady --- diff --git a/rpmautospec/__init__.py b/rpmautospec/__init__.py index 0311468..2429bae 100644 --- a/rpmautospec/__init__.py +++ b/rpmautospec/__init__.py @@ -1 +1 @@ -from .misc import AUTORELEASE_MACRO # noqa: F401 +from .misc import specfile_uses_rpmautospec # noqa: F401 diff --git a/rpmautospec/misc.py b/rpmautospec/misc.py index 5c26a7d..d28f253 100644 --- a/rpmautospec/misc.py +++ b/rpmautospec/misc.py @@ -16,10 +16,12 @@ import rpm # The %autorelease macro including parameters. This is imported into the main package to be used # from 3rd party code like fedpkg etc. AUTORELEASE_MACRO = "autorelease(e:s:hp)" +AUTORELEASE_SENTINEL = "__AUTORELEASE_SENTINEL__" release_re = re.compile(r"^(?P\d+)(?:(?P.*?)(?:\.(?P\d+))?)?$") disttag_re = re.compile(r"\.?(?P[^\d\.]+)(?P\d+)") evr_re = re.compile(r"^(?:(?P\d+):)?(?P[^-:]+)(?:-(?P[^-:]+))?$") +autochangelog_re = re.compile(r"\s*%(?:autochangelog|\{\??autochangelog\})\s*") rpmvercmp_key = cmp_to_key( lambda b1, b2: rpm.labelCompare( @@ -185,3 +187,53 @@ def run_command(command: list, cwd: Optional[str] = None) -> bytes: raise return output + + +def specfile_uses_rpmautospec( + specfile: str, check_autorelease: bool = True, check_autochangelog: bool = True +) -> bool: + """Check whether or not an RPM spec file uses rpmautospec features.""" + + autorelease = check_autorelease_presence(specfile) + autochangelog = check_autochangelog_presence(specfile) + + if check_autorelease and check_autochangelog: + return autorelease or autochangelog + elif check_autorelease: + return autorelease + elif check_autochangelog: + return autochangelog + else: + raise ValueError("One of check_autorelease and check_autochangelog must be set") + + +def check_autorelease_presence(filename: str) -> bool: + """ + Use the rpm package to detect the presence of an + autorelease macro and return true if found. + """ + cmd = ( + "rpm", + "--define", + "{} {}".format(AUTORELEASE_MACRO, AUTORELEASE_SENTINEL), + "-q", + "--queryformat", + "%{release}\n", + "--specfile", + filename, + ) + popen = subprocess.Popen(cmd, stdout=subprocess.PIPE) + release = popen.communicate()[0].decode(errors="replace").split("\n")[0] + return release == AUTORELEASE_SENTINEL + + +def check_autochangelog_presence(filename: str) -> bool: + """ + Search for the autochangelog macro and return true if found. + """ + with open(filename, "r") as specfile: + for _, line in enumerate(iter(specfile), start=1): + line = line.rstrip("\n") + if autochangelog_re.match(line): + return True + return False diff --git a/tests/rpmautospec/test_misc.py b/tests/rpmautospec/test_misc.py index 92a88f0..dc94f99 100644 --- a/tests/rpmautospec/test_misc.py +++ b/tests/rpmautospec/test_misc.py @@ -1,4 +1,5 @@ import logging +import os import subprocess from unittest import mock @@ -6,6 +7,8 @@ import pytest from rpmautospec import misc +__here__ = os.path.dirname(__file__) + class TestMisc: """Test the rpmautospec.misc module""" @@ -32,3 +35,79 @@ class TestMisc: misc.run_command(["command"]) assert str(excinfo.value) == "Command '['command']' returned non-zero exit status 139." assert any(rec.levelno == logging.ERROR for rec in caplog.records) + + def test_specfile_uses_rpmautospec_no_macros(self, caplog): + """Test no macros on specfile_uses_rpmautospec()""" + caplog.set_level(logging.DEBUG) + + specfile_path = os.path.join( + __here__, + os.path.pardir, + "test-data", + "test-specfiles", + "no-macros.spec", + ) + + result = misc.specfile_uses_rpmautospec(specfile_path) + + assert result is False + + def test_specfile_uses_rpmautospec_autorelease_only(self, caplog): + """Test autorelease only on specfile_uses_rpmautospec()""" + caplog.set_level(logging.DEBUG) + + specfile_path = os.path.join( + __here__, + os.path.pardir, + "test-data", + "test-specfiles", + "autorelease-only.spec", + ) + + result = misc.specfile_uses_rpmautospec(specfile_path) + assert result is True + + result_no_autorelease = misc.specfile_uses_rpmautospec( + specfile_path, check_autorelease=False + ) + assert result_no_autorelease is False + + def test_specfile_uses_rpmautospec_autochangelog_only(self, caplog): + """Test autochangelog only on specfile_uses_rpmautospec()""" + caplog.set_level(logging.DEBUG) + + specfile_path = os.path.join( + __here__, + os.path.pardir, + "test-data", + "test-specfiles", + "autochangelog-only.spec", + ) + + result = misc.specfile_uses_rpmautospec(specfile_path) + assert result is True + + result_no_changelog = misc.specfile_uses_rpmautospec( + specfile_path, check_autochangelog=False + ) + assert result_no_changelog is False + + def test_specfile_uses_rpmautospec_throws_error(self, caplog): + """Test specfile_uses_rpmautospec() throws an error when both params are false""" + caplog.set_level(logging.DEBUG) + + specfile_path = os.path.join( + __here__, + os.path.pardir, + "test-data", + "test-specfiles", + "autochangelog-only.spec", + ) + + result = misc.specfile_uses_rpmautospec(specfile_path) + assert result is True + + with pytest.raises(ValueError): + misc.specfile_uses_rpmautospec( + specfile_path, check_autochangelog=False, check_autorelease=False + ) diff --git a/tests/test-data/test-specfiles/autochangelog-only.spec b/tests/test-data/test-specfiles/autochangelog-only.spec new file mode 100644 index 0000000..b97d3a1 --- /dev/null +++ b/tests/test-data/test-specfiles/autochangelog-only.spec @@ -0,0 +1,34 @@ +# Our dummy-test-packages are named after canary varieties, meet Gloster, Rubino and Crested +# Source: https://www.omlet.co.uk/guide/finches_and_canaries/canary/canary_varieties +Name: dummy-test-package-gloster + +Version: 0 +Release: 7 +Summary: Dummy Test Package called Gloster +License: MIT +URL: http://fedoraproject.org/wiki/DummyTestPackages + +# The tarball contains a file with an uuid to test later and a LICENSE +Source0: %{name}-%{version}.tar.gz + +BuildArch: noarch + +%description +This is a dummy test package for the purposes of testing if the Fedora CI +pipeline is working. There is nothing useful here. + +%prep +%autosetup + +%build +# nothing to do + +%install +mkdir -p %{buildroot}%{_datadir} +cp -p uuid %{buildroot}%{_datadir}/%{name} + +%files +%license LICENSE +%{_datadir}/%{name} + +%autochangelog \ No newline at end of file diff --git a/tests/test-data/test-specfiles/autorelease-only.spec b/tests/test-data/test-specfiles/autorelease-only.spec new file mode 100644 index 0000000..16f8f7a --- /dev/null +++ b/tests/test-data/test-specfiles/autorelease-only.spec @@ -0,0 +1,58 @@ +# Our dummy-test-packages are named after canary varieties, meet Gloster, Rubino and Crested +# Source: https://www.omlet.co.uk/guide/finches_and_canaries/canary/canary_varieties +Name: dummy-test-package-gloster + +Version: 0 +Release: %{autorelease} +Summary: Dummy Test Package called Gloster +License: MIT +URL: http://fedoraproject.org/wiki/DummyTestPackages + +# The tarball contains a file with an uuid to test later and a LICENSE +Source0: %{name}-%{version}.tar.gz + +BuildArch: noarch + +%description +This is a dummy test package for the purposes of testing if the Fedora CI +pipeline is working. There is nothing useful here. + +%prep +%autosetup + +%build +# nothing to do + +%install +mkdir -p %{buildroot}%{_datadir} +cp -p uuid %{buildroot}%{_datadir}/%{name} + +%files +%license LICENSE +%{_datadir}/%{name} + +%changelog +* Fri Mar 27 2020 Pierre-Yves Chibon - 0-7 +- Undo vandalism +- Change license to MIT + +* Fri Mar 27 2020 King ISØ-8859 - 0-7 +- Honour the tradition of antiquated encodings! + +* Fri Mar 27 2020 Nils Philippsen - 0-6 +- Convert to automatic release and changelog + +* Tue Jan 21 2020 Pierre-Yves Chibon - 0-5 +- rebuilt + +* Thu Jan 16 2020 Pierre-Yves Chibon - 0-4 +- rebuilt + +* Fri Jan 10 2020 Pierre-Yves Chibon - 0-3 +- rebuilt + +* Fri Jan 10 2020 Pierre-Yves Chibon - 0-2 +- rebuilt + +* Thu Dec 19 2019 Pierre-Yves Chibon - 0-1 +- Initial packaging work diff --git a/tests/test-data/test-specfiles/both-macros.spec b/tests/test-data/test-specfiles/both-macros.spec new file mode 100644 index 0000000..2cd349c --- /dev/null +++ b/tests/test-data/test-specfiles/both-macros.spec @@ -0,0 +1,34 @@ +# Our dummy-test-packages are named after canary varieties, meet Gloster, Rubino and Crested +# Source: https://www.omlet.co.uk/guide/finches_and_canaries/canary/canary_varieties +Name: dummy-test-package-gloster + +Version: 0 +Release: %{autorelease} +Summary: Dummy Test Package called Gloster +License: MIT +URL: http://fedoraproject.org/wiki/DummyTestPackages + +# The tarball contains a file with an uuid to test later and a LICENSE +Source0: %{name}-%{version}.tar.gz + +BuildArch: noarch + +%description +This is a dummy test package for the purposes of testing if the Fedora CI +pipeline is working. There is nothing useful here. + +%prep +%autosetup + +%build +# nothing to do + +%install +mkdir -p %{buildroot}%{_datadir} +cp -p uuid %{buildroot}%{_datadir}/%{name} + +%files +%license LICENSE +%{_datadir}/%{name} + +%autochangelog diff --git a/tests/test-data/test-specfiles/no-macros.spec b/tests/test-data/test-specfiles/no-macros.spec new file mode 100644 index 0000000..27079bd --- /dev/null +++ b/tests/test-data/test-specfiles/no-macros.spec @@ -0,0 +1,58 @@ +# Our dummy-test-packages are named after canary varieties, meet Gloster, Rubino and Crested +# Source: https://www.omlet.co.uk/guide/finches_and_canaries/canary/canary_varieties +Name: dummy-test-package-gloster + +Version: 0 +Release: 7 +Summary: Dummy Test Package called Gloster +License: MIT +URL: http://fedoraproject.org/wiki/DummyTestPackages + +# The tarball contains a file with an uuid to test later and a LICENSE +Source0: %{name}-%{version}.tar.gz + +BuildArch: noarch + +%description +This is a dummy test package for the purposes of testing if the Fedora CI +pipeline is working. There is nothing useful here. + +%prep +%autosetup + +%build +# nothing to do + +%install +mkdir -p %{buildroot}%{_datadir} +cp -p uuid %{buildroot}%{_datadir}/%{name} + +%files +%license LICENSE +%{_datadir}/%{name} + +%changelog +* Fri Mar 27 2020 Pierre-Yves Chibon - 0-7 +- Undo vandalism +- Change license to MIT + +* Fri Mar 27 2020 King ISØ-8859 - 0-7 +- Honour the tradition of antiquated encodings! + +* Fri Mar 27 2020 Nils Philippsen - 0-6 +- Convert to automatic release and changelog + +* Tue Jan 21 2020 Pierre-Yves Chibon - 0-5 +- rebuilt + +* Thu Jan 16 2020 Pierre-Yves Chibon - 0-4 +- rebuilt + +* Fri Jan 10 2020 Pierre-Yves Chibon - 0-3 +- rebuilt + +* Fri Jan 10 2020 Pierre-Yves Chibon - 0-2 +- rebuilt + +* Thu Dec 19 2019 Pierre-Yves Chibon - 0-1 +- Initial packaging work