From dae3313ac3395b5e0911768d5b3007ef8f7ae1c5 Mon Sep 17 00:00:00 2001 From: Adnan9-63 Date: Mon, 2 Nov 2026 23:33:57 +0530 Subject: [PATCH] Add bump implementation for GentooVersion Implements GentooVersion.bump() to compute the branch-bump upper bound for Gentoo ebuild versions. This is required for translating GLSA advisory unaffected revision ranges (rge/rgt) into fixed version ranges in VulnerableCode GentooImporter. Closes #180 Assisted-by: Antigravity Signed-off-by: Adnan9-63 --- src/univers/gentoo.py | 35 +++++++++++++++++++++++++++++++++++ src/univers/versions.py | 4 ++++ tests/test_gentoo.py | 19 +++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/src/univers/gentoo.py b/src/univers/gentoo.py index 543f8548..26274365 100644 --- a/src/univers/gentoo.py +++ b/src/univers/gentoo.py @@ -181,3 +181,38 @@ def vercmp(ver1, ver2): # Our versions had different strings but ended up being equal. # The revision holds the final difference. return cmp(rev1, rev2) + + +def bump(ver): + """ + Return a new version string where the next to the last revision number + is one greater (e.g., 5.3.1 => 5.4) i.e., incrementing this GentooVersion + last numeric segment. + """ + if not ver: + return None + + ver = remove_spaces(ver) + if ":" in ver: + ver = ver.split(":")[0] + if ver.endswith("*"): + ver = ver[:-1] + + version, _ = parse_version_and_revision(ver) + + base = version.split("_")[0] + segments = base.split(".") + + if segments and segments[-1] and segments[-1][-1].isalpha(): + segments[-1] = segments[-1][:-1] + + int_segments = [int(s) for s in segments if s] + + if not int_segments: + return None + + if len(int_segments) > 1: + int_segments.pop() + + int_segments[-1] += 1 + return ".".join(str(s) for s in int_segments) diff --git a/src/univers/versions.py b/src/univers/versions.py index 5d6101ac..d1b0e991 100644 --- a/src/univers/versions.py +++ b/src/univers/versions.py @@ -429,6 +429,10 @@ def __gt__(self, other): return NotImplemented return gentoo.vercmp(self.value, other.value) == 1 + def bump(self): + bumped = gentoo.bump(self.value) + return self.__class__(bumped) if bumped else None + class AlpineLinuxVersion(GentooVersion): @classmethod diff --git a/tests/test_gentoo.py b/tests/test_gentoo.py index d2eddd5e..e9f30aef 100644 --- a/tests/test_gentoo.py +++ b/tests/test_gentoo.py @@ -31,3 +31,22 @@ def comparison(self): def test_gentoo_vers_cmp(test_case): avc = GentooVersionComp.from_data(data=test_case) avc.assert_result() + + +def test_gentoo_bump(): + assert GentooVersion("2.23.3").bump() == GentooVersion("2.24") + assert GentooVersion("2.24.3").bump() == GentooVersion("2.25") + assert GentooVersion("2.25.4").bump() == GentooVersion("2.26") + assert GentooVersion("2.26.2").bump() == GentooVersion("2.27") + assert GentooVersion("1.0.5").bump() == GentooVersion("1.1") + assert GentooVersion("5.3").bump() == GentooVersion("6") + assert GentooVersion("5").bump() == GentooVersion("6") + assert GentooVersion("1.3.8b").bump() == GentooVersion("1.4") + assert GentooVersion("9.9_p2").bump() == GentooVersion("10") + assert GentooVersion("0.13.4-r2").bump() == GentooVersion("0.14") + assert GentooVersion("2.23.3-r1").bump() == GentooVersion("2.24") + # Handling slots and wildcards during bump + from univers import gentoo + + assert gentoo.bump("3.24.48:3") == "3.25" + assert gentoo.bump("1.3*") == "2"