diff options
| author | apocelipes <[email protected]> | 2026-08-10 18:06:42 +0800 |
|---|---|---|
| committer | apocelipes <[email protected]> | 2026-08-10 18:06:42 +0800 |
| commit | 30c7ad380873ec4c2e52de15ee8e236dfcd38948 (patch) | |
| tree | 193a0e5d1db5ee86ae1f0e41e4cfa257a498f9a3 /core/src | |
| parent | 139a626e2ba4a9c3381e7c00116654f5bdc3bf11 (diff) | |
fix: fix numeric build metadata
Diffstat (limited to 'core/src')
| -rw-r--r-- | core/src/xmake/semver/select.c | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/core/src/xmake/semver/select.c b/core/src/xmake/semver/select.c index 563b24945..e95840eab 100644 --- a/core/src/xmake/semver/select.c +++ b/core/src/xmake/semver/select.c @@ -40,20 +40,49 @@ static tb_char_t const *xm_semver_skip_version_prefix(tb_char_t const *version_s } return version_str; } -static tb_bool_t xm_semver_is_exact_version(tb_char_t const *version_str, tb_size_t version_len) { +static tb_bool_t xm_semver_is_exact_version( + tb_char_t const *version_str, tb_size_t version_len, tb_bool_t *is_exact_with_build) { + *is_exact_with_build = tb_false; version_str = xm_semver_skip_version_prefix(version_str, &version_len); semver_t version = { 0 }; if (!semvern(&version, version_str, version_len)) { + *is_exact_with_build = version.build.len > 0; semver_dtor(&version); return tb_true; } return tb_false; } +static tb_long_t xm_semver_compare_build(semver_id_t const *left, semver_id_t const *right) { + while (left && right && left->len && right->len) { + if (left->numeric && right->numeric) { + if (left->num != right->num) { + return left->num > right->num ? 1 : -1; + } + } else { + tb_size_t size = left->len < right->len ? left->len : right->len; + tb_long_t result = tb_memcmp(left->raw, right->raw, size); + if (result) { + return result; + } + if (left->len != right->len) { + return left->len > right->len ? 1 : -1; + } + } + left = left->next; + right = right->next; + } + if (left && left->len) { + return 1; + } + if (right && right->len) { + return -1; + } + return 0; +} static tb_long_t xm_semver_compare_with_build(semver_t const *left, semver_t const *right) { tb_long_t result = semver_pcmp(left, right); // xmake-repo orders build metadata as package revisions - return result ? result : tb_strcmp(left->build.raw ? left->build.raw : "", - right->build.raw ? right->build.raw : ""); + return result ? result : xm_semver_compare_build(&left->build, &right->build); } static semver_t const *xm_semvers_find_newest(semvers_t const *versions) { tb_assert_and_check_return_val(versions && versions->length, tb_null); @@ -107,8 +136,10 @@ static tb_bool_t xm_semver_select_from_versions_tags1( return tb_true; } static tb_bool_t xm_semver_select_from_versions_tags2( - lua_State *lua, tb_int_t fromidx, tb_char_t const *version_str, tb_size_t version_len) { - version_str = xm_semver_skip_version_prefix(version_str, &version_len); + lua_State *lua, tb_int_t fromidx, tb_char_t const *version_str, tb_size_t version_len, tb_bool_t is_exact) { + if (is_exact) { + version_str = xm_semver_skip_version_prefix(version_str, &version_len); + } lua_Integer i = 0; luaL_checktype(lua, fromidx, LUA_TTABLE); for (i = lua_objlen(lua, fromidx); i > 0; --i) { @@ -118,9 +149,12 @@ static tb_bool_t xm_semver_select_from_versions_tags2( tb_char_t const *source_str = luaL_checkstring(lua, -1); tb_size_t source_len = tb_strlen(source_str); tb_size_t source_version_len = source_len; - tb_char_t const *source_version_str = xm_semver_skip_version_prefix(source_str, &source_version_len); + tb_char_t const *source_version_str = source_str; + // ignore a leading v/= prefix when comparing exact versions + if (is_exact) { + source_version_str = xm_semver_skip_version_prefix(source_str, &source_version_len); + } lua_pop(lua, 1); - // semver comparison ignores build metadata, so compare the normalized strings if (source_version_len == version_len && tb_strncmp(source_version_str, version_str, version_len) == 0) { lua_createtable(lua, 0, 2); lua_pushlstring(lua, source_str, source_len); @@ -208,6 +242,7 @@ tb_int_t xm_semver_select(lua_State *lua) { tb_bool_t ok = tb_false; tb_bool_t is_range = tb_false; tb_bool_t is_exact = tb_false; + tb_bool_t is_exact_with_build = tb_false; tb_char_t const *range_str = tb_null; semver_t semver = { 0 }; semvers_t matches = { 0 }; @@ -222,21 +257,22 @@ tb_int_t xm_semver_select(lua_State *lua) { // parse the version range string is_range = semver_rangen(&range, range_str, range_len) == 0; - is_exact = xm_semver_is_exact_version(range_str, range_len); + is_exact = xm_semver_is_exact_version(range_str, range_len, &is_exact_with_build); // matching order: versions exact -> tags exact -> versions range -> tags range if (is_exact || !is_range) { - if (xm_semver_select_from_versions_tags2(lua, 2, range_str, range_len)) { + if (xm_semver_select_from_versions_tags2(lua, 2, range_str, range_len, is_exact)) { ok = tb_true; break; } - if (xm_semver_select_from_versions_tags2(lua, 3, range_str, range_len)) { + if (xm_semver_select_from_versions_tags2(lua, 3, range_str, range_len, is_exact)) { ok = tb_true; break; } } - if (is_range) { + // a build-qualified exact version identifies a specific package revision + if (is_range && !is_exact_with_build) { if (xm_semver_select_from_versions_tags1(lua, 2, &semver, &range, &matches)) { ok = tb_true; break; |
