diff options
| author | apocelipes <[email protected]> | 2026-08-09 05:35:46 +0800 |
|---|---|---|
| committer | apocelipes <[email protected]> | 2026-08-09 06:08:45 +0800 |
| commit | 1d8683111e485d8a1172b6b689da6dddb3127735 (patch) | |
| tree | c575cedb7b6cf3f18ec255441c8dc6c25c82df22 | |
| parent | 6ac4ea833193a4319a1eb6e5f588d1877fd48064 (diff) | |
fix(semver): correct version selection
semver_rangen() accepts an exact version as a range, and SemVer comparison ignores build metadata.
This can select a different version than requested.
Try exact string matches for versions and tags before falling back to the range selection.
| -rw-r--r-- | core/src/xmake/semver/select.c | 51 | ||||
| -rwxr-xr-x | tests/modules/semver/test.lua | 35 |
2 files changed, 64 insertions, 22 deletions
diff --git a/core/src/xmake/semver/select.c b/core/src/xmake/semver/select.c index 283afb050..82de60e74 100644 --- a/core/src/xmake/semver/select.c +++ b/core/src/xmake/semver/select.c @@ -33,6 +33,14 @@ /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ +static tb_bool_t xm_semver_is_exact_version(tb_char_t const *version_str, tb_size_t version_len) { + semver_t version = { 0 }; + if (!semvern(&version, version_str, version_len)) { + semver_dtor(&version); + return tb_true; + } + return tb_false; +} static tb_bool_t xm_semver_select_from_versions_tags1( lua_State *lua, tb_int_t fromidx, semver_t *semver, semver_range_t const *range, semvers_t *matches) { // clear matches @@ -179,6 +187,7 @@ tb_int_t xm_semver_select(lua_State *lua) { // select version tb_bool_t ok = tb_false; tb_bool_t is_range = tb_false; + tb_bool_t is_exact = tb_false; tb_char_t const *range_str = tb_null; semver_t semver = { 0 }; semvers_t matches = { 0 }; @@ -193,30 +202,28 @@ tb_int_t xm_semver_select(lua_State *lua) { // parse the version range string is_range = semver_rangen(&range, range_str, range_len) == 0; - if (is_range) { - // attempt to select version from the versions list first - if (xm_semver_select_from_versions_tags1(lua, 2, &semver, &range, &matches)) { - ok = tb_true; - break; - } + is_exact = xm_semver_is_exact_version(range_str, range_len); - // attempt to select version from the tags list - if (xm_semver_select_from_versions_tags1(lua, 3, &semver, &range, &matches)) { - ok = tb_true; - break; - } - } else { - // attempt to select version from the versions list first - if (xm_semver_select_from_versions_tags2(lua, 2, &semver, range_str, range_len)) { - ok = tb_true; - break; - } + // attempt to select version from the versions list first + if ((is_exact || !is_range) && + xm_semver_select_from_versions_tags2(lua, 2, &semver, range_str, range_len)) { + ok = tb_true; + break; + } + if (is_range && xm_semver_select_from_versions_tags1(lua, 2, &semver, &range, &matches)) { + ok = tb_true; + break; + } - // attempt to select version from the tags list - if (xm_semver_select_from_versions_tags2(lua, 3, &semver, range_str, range_len)) { - ok = tb_true; - break; - } + // attempt to select version from the tags list + if ((is_exact || !is_range) && + xm_semver_select_from_versions_tags2(lua, 3, &semver, range_str, range_len)) { + ok = tb_true; + break; + } + if (is_range && xm_semver_select_from_versions_tags1(lua, 3, &semver, &range, &matches)) { + ok = tb_true; + break; } // attempt to select version from the branches diff --git a/tests/modules/semver/test.lua b/tests/modules/semver/test.lua index 1ab6dc8aa..3c14ad1d7 100755 --- a/tests/modules/semver/test.lua +++ b/tests/modules/semver/test.lua @@ -18,6 +18,41 @@ function test_semver_select(t) , "^1.5.0" ,{"1.4.0", "1.5.0", "1.5.1"}) + _check_semver_select(t, {"3.53.0+200", "version"} + , "3.53.0+200" + , {"3.53.0+0", "3.53.0+100", "3.53.0+200"}) + + _check_semver_select(t, {"3.53.0+100", "version"} + , "3.53.0+999" + , {"3.53.0+100"}) + + _check_semver_select(t, {"1.2.3", "version"} + , "1.2.3" + , {"1.2.3+1", "1.2.3"}) + + _check_semver_select(t, {"1.2.9", "version"} + , "1.2" + , {"1.2", "1.2.9"}) + + _check_semver_select(t, {"1.9.0", "version"} + , "^1.2.3" + , {"^1.2.3", "1.2.3", "1.9.0"}) + + _check_semver_select(t, {"v1.2.3+7", "version"} + , "1.2.3" + , {"v1.2.3+7"} + , {"1.2.3"}) + + _check_semver_select(t, {"3.53.0+200", "tag"} + , "3.53.0+200" + , nil + , {"3.53.0+0", "3.53.0+200"}) + + _check_semver_select(t, {"3.53.0+100", "tag"} + , "3.53.0+999" + , nil + , {"3.53.0+100"}) + _check_semver_select(t, {"master", "branch"} , "master" , {"1.4.0", "1.5.0", "1.5.1"} |
