summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorapocelipes <[email protected]>2026-08-10 18:06:42 +0800
committerapocelipes <[email protected]>2026-08-10 18:06:42 +0800
commit30c7ad380873ec4c2e52de15ee8e236dfcd38948 (patch)
tree193a0e5d1db5ee86ae1f0e41e4cfa257a498f9a3 /core/src
parent139a626e2ba4a9c3381e7c00116654f5bdc3bf11 (diff)
fix: fix numeric build metadata
Diffstat (limited to 'core/src')
-rw-r--r--core/src/xmake/semver/select.c58
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;