From e6a801056729cb0ef71f359a3f65e77e060fa109 Mon Sep 17 00:00:00 2001 From: Erik Skultety Date: Tue, 16 Jul 2024 14:54:51 +0200 Subject: [PATCH] package_managers: gomod: Allow pre-release IDs & comments in version string Golang allows arbitrary pre-release version identifiers in version string, i.e. trying to parse the following in a go.mod file passes: # go.mod go 1.21.0foo458 $ go mod edit -json | jq .Go 1.21.0foo458 Golang also allows go.mod files to include commentaries on the version string line, i.e. the following passes the built-in parser: # go.mod go 1.21.0rc1//commentary go mod edit -json | jq .Go 1.21.rc1 This patches enhances our regex to support both. Signed-off-by: Erik Skultety --- cachi2/core/package_managers/gomod.py | 12 +++++++++--- tests/unit/package_managers/test_gomod.py | 7 +++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cachi2/core/package_managers/gomod.py b/cachi2/core/package_managers/gomod.py index 4912c4f44..c2de2bd99 100644 --- a/cachi2/core/package_managers/gomod.py +++ b/cachi2/core/package_managers/gomod.py @@ -678,9 +678,15 @@ def _get_gomod_version(go_mod_file: RootedPath) -> Tuple[Optional[str], Optional go_version = None toolchain_version = None - version_str_regex = r"(?P\d+\.\d+(:?\.\d+)?)" - go_version_regex = rf"^\s*go\s+{version_str_regex}\s*$" - toolchain_version_regex = rf"^\s*toolchain\s+go{version_str_regex}\s*$" + # this needs to be able to handle arbitrary pre-release version identifiers and commentaries + # as well, since Go itself can parse it + # - 'go 1.21.0' + # - ' go 1.21.0rc4' + # - 'go 1.21beta1//commentary' + version_str_regex = r"(?P\d+\.\d+(:?\.\d+)?(?:[a-zA-Z]+\d+)?)" + post_version_chars_regex = r"\s*(?:\/\/.*)?" + go_version_regex = rf"^\s*go\s+{version_str_regex}{post_version_chars_regex}$" + toolchain_version_regex = rf"^\s*toolchain\s+go{version_str_regex}{post_version_chars_regex}$" go_pattern = re.compile(go_version_regex) toolchain_pattern = re.compile(toolchain_version_regex) diff --git a/tests/unit/package_managers/test_gomod.py b/tests/unit/package_managers/test_gomod.py index 1cae29f2a..30e283198 100644 --- a/tests/unit/package_managers/test_gomod.py +++ b/tests/unit/package_managers/test_gomod.py @@ -1930,6 +1930,11 @@ def test_fetch_tags_fail(repo_remote_with_tag: tuple[RootedPath, RootedPath]) -> pytest.param("go 1.21", "1.21", None, id="go_minor"), pytest.param("go 1.21.0", "1.21.0", None, id="go_micro"), pytest.param(" go 1.21.4 ", "1.21.4", None, id="go_spaces"), + pytest.param("go 1.21rc4", "1.21rc4", None, id="go_minor_rc"), + pytest.param("go 1.21.0rc4", "1.21.0rc4", None, id="go_micro_rc"), + pytest.param("go 1.21.0 // comment", "1.21.0", None, id="go_commentary"), + pytest.param("go 1.21.0//commentary", "1.21.0", None, id="go_commentary_no_spaces"), + pytest.param("go 1.21.0beta2//comment", "1.21.0beta2", None, id="go_rc_commentary"), pytest.param(" toolchain go1.21.4 ", None, "1.21.4", id="toolchain_spaces"), pytest.param("go 1.21\ntoolchain go1.21.6", "1.21", "1.21.6", id="go_and_toolchain"), ], @@ -1949,6 +1954,8 @@ def test_get_gomod_version( "go 1.21.0.100", # non-conforming to the X.Y(.Z)? versioning template "1.21", # missing 'go' at the beginning "go 1.21 foo", # extra characters after version string + "go 1.21prerelease", # pre-release with no number + "go 1.21prerelease_4", # pre-release with non-alphanum character "toolchain 1.21", # missing 'go' prefix for the toolchain spec ]