| |
@@ -0,0 +1,216 @@
|
| |
+ """
|
| |
+ Test the rpmautospec.subcommands.revert module
|
| |
+ """
|
| |
+ import pytest
|
| |
+ import re
|
| |
+
|
| |
+ from types import SimpleNamespace
|
| |
+
|
| |
+ from rpmautospec.subcommands import revert
|
| |
+ from rpmautospec.misc import (
|
| |
+ autochangelog_re,
|
| |
+ release_autorelease_re,
|
| |
+ FileIsModifiedError,
|
| |
+ PartialRpmautospecError,
|
| |
+ )
|
| |
+
|
| |
+ base_release_re = re.compile(r"(?i:Release)\s*:\s*(.+)%{\?dist}")
|
| |
+
|
| |
+ # Expected tail of %changelog, and thus the whole specfile,
|
| |
+ # when the test specfile is reverted outside of Git repository.
|
| |
+ # The changelog entry contains a changing date,
|
| |
+ # so only the fixed tail is recorded here.
|
| |
+ norepo_changelog_text = """John Doe <packager@example.com> - 1.0-1
|
| |
+ - Uncommitted changes"""
|
| |
+
|
| |
+ repo_changelog_text = """* Wed Feb 22 2023 John Doe <packager@example.com> - 1.1-1
|
| |
+ - Version 1.1 from changelog
|
| |
+
|
| |
+ * Tue Feb 21 2023 John Doe <packager@example.com> - 1.0-1
|
| |
+ - Version 1.0 from changelog"""
|
| |
+
|
| |
+
|
| |
+ def assert_no_rpmautospec(specfile):
|
| |
+ """Assert that rpmautospec is not used in given specfile."""
|
| |
+ assert not release_autorelease_re.search(specfile.read_text())
|
| |
+ assert not autochangelog_re.search(specfile.read_text())
|
| |
+
|
| |
+
|
| |
+ def assert_release_number(specfile, expected_base_release):
|
| |
+ """Assert that specfile has the expected release number."""
|
| |
+ match = base_release_re.search(specfile.read_text())
|
| |
+ assert match is not None
|
| |
+ assert match.group(1) == expected_base_release
|
| |
+
|
| |
+
|
| |
+ def test_revert_simple(specfile, repo):
|
| |
+ args = SimpleNamespace(spec_or_path=specfile)
|
| |
+ revert.main(args)
|
| |
+
|
| |
+ assert_no_rpmautospec(specfile)
|
| |
+ assert_release_number(specfile, "2")
|
| |
+ assert specfile.read_text().endswith(
|
| |
+ """Jane Doe <jane.doe@example.com> - 1.0-1
|
| |
+ - Initial commit"""
|
| |
+ )
|
| |
+
|
| |
+
|
| |
+ def test_revert_changelog_at_head(specfile, repo):
|
| |
+ # The changelog file has already been added:
|
| |
+ changelog = specfile.parent / "changelog"
|
| |
+ changelog.write_text(repo_changelog_text)
|
| |
+ repo.index.add("changelog")
|
| |
+ repo.index.write()
|
| |
+ repo.create_commit(
|
| |
+ repo.head.name,
|
| |
+ repo.default_signature,
|
| |
+ repo.default_signature,
|
| |
+ "Add changelog",
|
| |
+ repo.index.write_tree(),
|
| |
+ [repo.head.target],
|
| |
+ )
|
| |
+
|
| |
+ args = SimpleNamespace(spec_or_path=specfile)
|
| |
+ revert.main(args)
|
| |
+ print(specfile.read_text())
|
| |
+
|
| |
+ assert_no_rpmautospec(specfile)
|
| |
+ assert base_release_re.search(specfile.read_text()).group(1) == "3"
|
| |
+ assert specfile.read_text().endswith(repo_changelog_text)
|
| |
+ assert not changelog.exists()
|
| |
+
|
| |
+
|
| |
+ def test_revert_changelog_at_old_commit(specfile, repo):
|
| |
+ changelog = specfile.parent / "changelog"
|
| |
+ changelog.write_text(repo_changelog_text)
|
| |
+ repo.index.add("changelog")
|
| |
+ repo.index.write()
|
| |
+ repo.create_commit(
|
| |
+ repo.head.name,
|
| |
+ repo.default_signature,
|
| |
+ repo.default_signature,
|
| |
+ "Add changelog",
|
| |
+ repo.index.write_tree(),
|
| |
+ [repo.head.target],
|
| |
+ )
|
| |
+ repo.create_commit(
|
| |
+ repo.head.name,
|
| |
+ repo.default_signature,
|
| |
+ repo.default_signature,
|
| |
+ "Next change",
|
| |
+ repo.index.write_tree(),
|
| |
+ [repo.head.target],
|
| |
+ )
|
| |
+
|
| |
+ args = SimpleNamespace(spec_or_path=specfile)
|
| |
+ revert.main(args)
|
| |
+ print(specfile.read_text())
|
| |
+
|
| |
+ assert_no_rpmautospec(specfile)
|
| |
+ assert base_release_re.search(specfile.read_text()).group(1) == "4"
|
| |
+ expected_latest_entry = """Jane Doe <jane.doe@example.com> - 1.0-4
|
| |
+ - Next change"""
|
| |
+ assert specfile.read_text().endswith("%s\n\n%s" % (expected_latest_entry, repo_changelog_text))
|
| |
+ assert not changelog.exists()
|
| |
+
|
| |
+
|
| |
+ @pytest.mark.parametrize("changelog", [repo_changelog_text])
|
| |
+ @pytest.mark.parametrize("release", ["Release: 7%{?dist}"])
|
| |
+ def test_nothing_to_do(specfile, repo):
|
| |
+ args = SimpleNamespace(spec_or_path=specfile)
|
| |
+ revert.main(args)
|
| |
+
|
| |
+ assert_no_rpmautospec(specfile)
|
| |
+ assert_release_number(specfile, "7")
|
| |
+ assert specfile.read_text().endswith("%s\n" % repo_changelog_text)
|
| |
+
|
| |
+
|
| |
+ def test_norepo(specfile):
|
| |
+ args = SimpleNamespace(spec_or_path=specfile)
|
| |
+ revert.main(args)
|
| |
+
|
| |
+ assert_no_rpmautospec(specfile)
|
| |
+ assert_release_number(specfile, "1")
|
| |
+ assert specfile.read_text().endswith(norepo_changelog_text)
|
| |
+
|
| |
+
|
| |
+ @pytest.mark.parametrize("changelog", [repo_changelog_text])
|
| |
+ def test_error_autorelease_only(specfile, repo):
|
| |
+ args = SimpleNamespace(spec_or_path=specfile)
|
| |
+ with pytest.raises(
|
| |
+ PartialRpmautospecError, match="does not have both %autorelease and %autochangelog"
|
| |
+ ):
|
| |
+ revert.main(args)
|
| |
+
|
| |
+
|
| |
+ @pytest.mark.parametrize("release", ["Release: 7%{?dist}"])
|
| |
+ def test_error_autochangelog_only(specfile, repo):
|
| |
+ args = SimpleNamespace(spec_or_path=specfile)
|
| |
+ with pytest.raises(
|
| |
+ PartialRpmautospecError, match="does not have both %autorelease and %autochangelog"
|
| |
+ ):
|
| |
+ revert.main(args)
|
| |
+
|
| |
+
|
| |
+ def test_error_specfile_modified(specfile, repo):
|
| |
+ # The spec file has been modified without committing it:
|
| |
+ with specfile.open("a") as f:
|
| |
+ print("Modified", file=f)
|
| |
+ args = SimpleNamespace(spec_or_path=specfile)
|
| |
+ with pytest.raises(FileIsModifiedError, match="is modified"):
|
| |
+ revert.main(args)
|
| |
+
|
| |
+
|
| |
+ def test_error_specfile_deleted(specfile, repo):
|
| |
+ # The spec file has been deleted:
|
| |
+ specfile.unlink()
|
| |
+ args = SimpleNamespace(spec_or_path=specfile)
|
| |
+ with pytest.raises(FileNotFoundError, match="doesn't exist"):
|
| |
+ revert.main(args)
|
| |
+
|
| |
+
|
| |
+ def test_error_changelog_modified(specfile, repo):
|
| |
+ # The changelog file has already been added:
|
| |
+ changelog = specfile.parent / "changelog"
|
| |
+ changelog.write_text(repo_changelog_text)
|
| |
+ repo.index.add("changelog")
|
| |
+ repo.index.write()
|
| |
+ repo.create_commit(
|
| |
+ repo.head.name,
|
| |
+ repo.default_signature,
|
| |
+ repo.default_signature,
|
| |
+ "Add changelog",
|
| |
+ repo.index.write_tree(),
|
| |
+ [repo.head.target],
|
| |
+ )
|
| |
+
|
| |
+ # The changelog has been modified without committing it:
|
| |
+ with changelog.open("a") as f:
|
| |
+ print("- Another change", file=f)
|
| |
+ args = SimpleNamespace(spec_or_path=specfile)
|
| |
+ with pytest.raises(FileIsModifiedError, match="is modified"):
|
| |
+ revert.main(args)
|
| |
+
|
| |
+
|
| |
+ def test_error_changelog_deleted(specfile, repo):
|
| |
+ # The changelog file has already been added:
|
| |
+ changelog = specfile.parent / "changelog"
|
| |
+ changelog.write_text(repo_changelog_text)
|
| |
+ repo.index.add("changelog")
|
| |
+ repo.index.write()
|
| |
+ repo.create_commit(
|
| |
+ repo.head.name,
|
| |
+ repo.default_signature,
|
| |
+ repo.default_signature,
|
| |
+ "Add changelog",
|
| |
+ repo.index.write_tree(),
|
| |
+ [repo.head.target],
|
| |
+ )
|
| |
+
|
| |
+ # The changelog has been deleted without committing:
|
| |
+ changelog.unlink()
|
| |
+ args = SimpleNamespace(spec_or_path=specfile)
|
| |
+ with pytest.raises(
|
| |
+ FileIsModifiedError, match="is not found in the working directory, but is tracked"
|
| |
+ ):
|
| |
+ revert.main(args)
|
| |
Use of rpmautospec is not mandatory in Fedora, even though with
Rpmautospec by Default it is recommended 1. In case a package
using rpmautospec is transferred to a maintainer who does not want
to use it, there is a need to revert the package back to
traditional release and changelog management. The new revert
subcommand does that.
Only simple specfiles that look like this are handled:
If the changelog file exists, it is deleted and its contents are
moved to specfile %changelog as expected.
The revert subcommand performs similar checks for local
modifications as convert subcommand. An error is if there are local
changes on top of repository contents.
Relates: https://pagure.io/fesco/issue/2930
Relates: https://github.com/fedora-eln/distrobaker/issues/12
Signed-off-by: Otto Liljalaakso otto.liljalaakso@iki.fi
Co-authored-by: Maxwell G gotmax@e.email