summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2017-09-11 22:56:08 +0800
committerruki <[email protected]>2017-09-11 11:36:50 +0800
commitc3a7d94a71c62bbccc2931d84b713b1b44c6a5c5 (patch)
tree288b9efaaee0f087b09d6b9631692dc654117aae
parent9f42256a7eef0c84267d5f88cf71865e58dc54f2 (diff)
improve semver module and select master version
-rw-r--r--core/src/sv/include/semver.h15
-rw-r--r--core/src/xmake/semver/parse.c40
-rw-r--r--core/src/xmake/semver/prefix.h23
-rw-r--r--core/src/xmake/semver/satisfies.c33
-rw-r--r--core/src/xmake/semver/select.c267
-rw-r--r--core/src/xmake/semver/semver.c48
-rwxr-xr-xtests/modules/semver/test.lua4
-rw-r--r--xmake/core/sandbox/modules/import/core/base/semver.lua1
8 files changed, 291 insertions, 140 deletions
diff --git a/core/src/sv/include/semver.h b/core/src/sv/include/semver.h
index bdc005702..0cde4cdd9 100644
--- a/core/src/sv/include/semver.h
+++ b/core/src/sv/include/semver.h
@@ -198,8 +198,11 @@ SV_API void semvers_pclear(semvers_t *self);
#define semvers_growth(s, n) \
semvers_pgrowth(&(s),n)
+#define semvers_pgrow(s, n) \
+ semvers_pgrowth((s),(s)->length+(n))
+
#define semvers_grow(s, n) \
- semvers_pgrowth(&(s),(s).length+(n))
+ semvers_pgrow(&(s), n)
#define semvers_resize(s, n) \
((s).length=semvers_growth(s, n))
@@ -207,11 +210,17 @@ SV_API void semvers_pclear(semvers_t *self);
#define semvers_erase(s, i) \
semvers_perase(&(s), i)
+#define semvers_ppush(s, x) \
+ (semvers_pgrow(s,1),(s)->data[(s)->length++]=(x))
+
#define semvers_push(s, x) \
- (semvers_grow(s,1),(s).data[(s).length++]=(x))
+ semvers_ppush(&(s), x)
+
+#define semvers_ppop(s) \
+ (s)->data[--(s)->length]
#define semvers_pop(s) \
- (s).data[--(s).length]
+ semvers_ppop(&(s))
#define semvers_unshift(s, x) \
(semvers_grow(s,1),memmove((s).data+1,(s).data,(s).length++*sizeof(semver_t)),(s).data[0]=(x))
diff --git a/core/src/xmake/semver/parse.c b/core/src/xmake/semver/parse.c
index 976f198fb..2180d7800 100644
--- a/core/src/xmake/semver/parse.c
+++ b/core/src/xmake/semver/parse.c
@@ -38,28 +38,46 @@
* implementation
*/
-// parse wrapper
+/* version = semver.parse("v1.0.1-beta")
+ *
+ *
+ {
+ patch = 1
+ , raw = v1.0.1-beta
+ , version = v1.0.1-beta
+ , major = 1
+ , build =
+ {
+ }
+
+ , minor = 0
+ , prerelease =
+ {
+ beta
+ }
+ }
+ *
+ */
tb_int_t xm_semver_parse(lua_State* lua)
{
- semver_t semver = {0};
-
// check
tb_assert_and_check_return_val(lua, 0);
// get the version string
- tb_char_t const* str = luaL_checkstring(lua, 1);
- tb_check_return_val(str, 0);
+ tb_char_t const* version_str = luaL_checkstring(lua, 1);
+ tb_check_return_val(version_str, 0);
- if (semvern(&semver, str, tb_strlen(str))) {
+ // parse version string
+ semver_t semver = {0};
+ if (semvern(&semver, version_str, tb_strlen(version_str)))
+ {
lua_pushnil(lua);
- lua_pushfstring(lua, "Unable to parse semver '%s'", str);
-
+ lua_pushfstring(lua, "unable to parse semver '%s'", version_str);
return 2;
}
- lua_pushsemver(lua, semver);
- semver_dtor(&semver);
-
// ok
+ lua_pushsemver(lua, &semver);
+ semver_dtor(&semver);
return 1;
}
diff --git a/core/src/xmake/semver/prefix.h b/core/src/xmake/semver/prefix.h
index 17c4e9f5a..2a4155aa8 100644
--- a/core/src/xmake/semver/prefix.h
+++ b/core/src/xmake/semver/prefix.h
@@ -29,9 +29,28 @@
* includes
*/
#include "../prefix.h"
-
#include "semver.h"
-void lua_pushsemver(lua_State *lua, semver_t semver);
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/* push struct semver
+ *
+ * @param lua the lua context
+ * @param semver the semver struct
+ *
+ */
+tb_void_t lua_pushsemver(lua_State *lua, semver_t const* semver);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * leave
+ */
+__tb_extern_c_leave__
#endif
diff --git a/core/src/xmake/semver/satisfies.c b/core/src/xmake/semver/satisfies.c
index f3b34890f..f630558d9 100644
--- a/core/src/xmake/semver/satisfies.c
+++ b/core/src/xmake/semver/satisfies.c
@@ -38,37 +38,40 @@
* implementation
*/
-// satisfies wrapper
+/* satisfies the given version range?
+ *
+ * semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') => true
+ */
tb_int_t xm_semver_satisfies(lua_State* lua)
{
- semver_t semver = {0};
- semver_range_t range = {0};
-
// check
tb_assert_and_check_return_val(lua, 0);
// get the version string
- tb_char_t const* str = luaL_checkstring(lua, 1);
- tb_char_t const* range_str = luaL_checkstring(lua, 2);
+ tb_char_t const* version_str = luaL_checkstring(lua, 1);
+ tb_char_t const* range_str = luaL_checkstring(lua, 2);
+ tb_assert_and_check_return_val(version_str && range_str, 0);
- tb_check_return_val(str, 0);
- tb_check_return_val(range_str, 0);
-
- if (semvern(&semver, str, tb_strlen(str))) {
+ // parse the version string
+ semver_t semver = {0};
+ if (semvern(&semver, version_str, tb_strlen(version_str)))
+ {
lua_pushnil(lua);
- lua_pushfstring(lua, "Unable to parse semver '%s'", str);
-
+ lua_pushfstring(lua, "unable to parse semver '%s'", version_str);
return 2;
}
- if (semver_rangen(&range, range_str, tb_strlen(range_str))) {
+ // parse the version range string
+ semver_range_t range = {0};
+ if (semver_rangen(&range, range_str, tb_strlen(range_str)))
+ {
semver_dtor(&semver);
lua_pushnil(lua);
- lua_pushfstring(lua, "Unable to parse semver range '%s'", range_str);
-
+ lua_pushfstring(lua, "unable to parse semver range '%s'", range_str);
return 2;
}
+ // satisfies this range?
lua_pushboolean(lua, semver_range_match(semver, range));
semver_dtor(&semver);
semver_range_dtor(&range);
diff --git a/core/src/xmake/semver/select.c b/core/src/xmake/semver/select.c
index 6400de6a8..ea81b1e0c 100644
--- a/core/src/xmake/semver/select.c
+++ b/core/src/xmake/semver/select.c
@@ -32,129 +32,226 @@
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
-#include <stdlib.h>
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
+ * private implementation
*/
-
-// satisfies wrapper
-tb_int_t xm_semver_select(lua_State* lua)
+static tb_bool_t xm_semver_select_from_versions_tags(lua_State* lua, tb_int_t fromidx, semver_t* semver, semver_range_t const* range, semvers_t* matches)
{
- semver_t semver = {0};
- semvers_t matches = {0};
- semver_range_t range = {0};
- lua_Integer i;
- size_t range_len = 0, source_len;
- tb_char_t const* source_str;
- tb_char_t const* source;
- tb_bool_t is_range;
+ // clear matches
+ semvers_pclear(matches);
- lua_settop(lua, 4);
+ // select all matches
+ tb_int_t i = 0;
+ luaL_checktype(lua, fromidx, LUA_TTABLE);
+ for (i = lua_objlen(lua, fromidx); i > 0; --i)
+ {
+ lua_pushinteger(lua, i);
+ lua_gettable(lua, fromidx);
- // check
- tb_assert_and_check_return_val(lua, 0);
+ tb_char_t const* source_str = luaL_checkstring(lua, -1);
+ if (source_str && semver_tryn(semver, source_str, tb_strlen(source_str)) == 0)
+ {
+ if (semver_range_pmatch(semver, range)) semvers_ppush(matches, *semver);
+ else semver_dtor(semver);
+ }
+ }
- // get the version string
- tb_char_t const* range_str = luaL_checkstring(lua, 1);
- tb_check_return_val(range_str, 0);
- range_len = tb_strlen(range_str);
+ // no matches?
+ tb_check_return_val(matches->length, tb_false);
- is_range = semver_rangen(&range, range_str, range_len) == 0;
- if (is_range) {
- source = "versions";
- luaL_checktype(lua, 2, LUA_TTABLE);
- for (i = lua_objlen(lua, 2); i > 0; --i) {
- lua_pushinteger(lua, i);
- lua_gettable(lua, 2);
+ // sort matches
+ semvers_psort(matches);
- source_str = luaL_checkstring(lua, -1);
- tb_check_return_val(source_str, 0);
+ // get the newest version
+ semver_t top = semvers_ppop(matches);
+ lua_createtable(lua, 0, 2);
- if (semver_tryn(&semver, source_str, tb_strlen(source_str)) == 0) {
- if (semver_range_match(semver, range)) {
- semvers_push(matches, semver);
- } else {
- semver_dtor(&semver);
- }
- }
- }
- if (matches.length) {
- goto match;
- }
- semvers_clear(matches);
- source = "tags";
- luaL_checktype(lua, 3, LUA_TTABLE);
- for (i = lua_objlen(lua, 3); i > 0; --i) {
- lua_pushinteger(lua, i);
- lua_gettable(lua, 3);
+ // return results
+ lua_pushstring(lua, top.raw);
+ lua_setfield(lua, -2, "version");
- source_str = luaL_checkstring(lua, -1);
- tb_check_return_val(source_str, 0);
+ lua_pushstring(lua, fromidx == 2? "versions" : "tags");
+ lua_setfield(lua, -2, "source");
- if (semver_tryn(&semver, source_str, tb_strlen(source_str)) == 0) {
- if (semver_range_match(semver, range)) {
- semvers_push(matches, semver);
- } else {
- semver_dtor(&semver);
- }
- }
- }
- if (matches.length) {
- goto match;
- }
- semvers_dtor(matches);
- semver_range_dtor(&range);
- }
+ // exit the popped semver
+ semver_dtor(&top);
- source = "branches";
- luaL_checktype(lua, 4, LUA_TTABLE);
- for (i = lua_objlen(lua, 4); i > 0; --i) {
+ // ok
+ return tb_true;
+}
+static tb_bool_t xm_semver_select_from_branches(lua_State* lua, tb_int_t fromidx, tb_char_t const* range_str, tb_size_t range_len)
+{
+ tb_int_t i = 0;
+ luaL_checktype(lua, fromidx, LUA_TTABLE);
+ for (i = lua_objlen(lua, fromidx); i > 0; --i)
+ {
lua_pushinteger(lua, i);
- lua_gettable(lua, 4);
+ lua_gettable(lua, fromidx);
- source_str = luaL_checkstring(lua, -1);
- tb_check_return_val(source_str, 0);
- source_len = tb_strlen(source_str);
+ tb_char_t const* source_str = luaL_checkstring(lua, -1);
+ tb_check_continue(source_str);
- if (source_len == range_len && tb_memcmp(source_str, range_str, source_len) == 0) {
+ tb_size_t source_len = tb_strlen(source_str);
+ if (source_len == range_len && tb_memcmp(source_str, range_str, source_len) == 0)
+ {
lua_createtable(lua, 0, 2);
lua_pushlstring(lua, source_str, source_len);
lua_setfield(lua, -2, "version");
- lua_pushstring(lua, source);
+ lua_pushstring(lua, "branches");
lua_setfield(lua, -2, "source");
- return 1;
+ // ok
+ return tb_true;
}
}
- if (!is_range) {
- lua_pushnil(lua);
- lua_pushfstring(lua, "Unable to parse semver range '%s'", range_str);
+ // no matches
+ return tb_false;
+}
+static tb_bool_t xm_semver_select_master_from_versions_tags(lua_State* lua, tb_int_t fromidx, semver_t* semver, semvers_t* matches)
+{
+ // clear matches
+ semvers_pclear(matches);
- return 2;
+ // push all versions to matches
+ tb_int_t i = 0;
+ luaL_checktype(lua, fromidx, LUA_TTABLE);
+ for (i = lua_objlen(lua, fromidx); i > 0; --i)
+ {
+ lua_pushinteger(lua, i);
+ lua_gettable(lua, fromidx);
+
+ tb_char_t const* source_str = luaL_checkstring(lua, -1);
+ if (source_str && semver_tryn(semver, source_str, tb_strlen(source_str)) == 0)
+ semvers_ppush(matches, *semver);
}
- lua_pushnil(lua);
- lua_pushfstring(lua, "Unable to select version for range '%s'", range_str);
- return 2;
- match:
- semvers_sort(matches);
- semver = semvers_pop(matches);
+ // no matches?
+ tb_check_return_val(matches->length, tb_false);
+
+ // sort matches
+ semvers_psort(matches);
+
+ // get the newest match
+ semver_t top = semvers_ppop(matches);
lua_createtable(lua, 0, 2);
- lua_pushstring(lua, semver.raw);
+ // return results
+ lua_pushstring(lua, top.raw);
lua_setfield(lua, -2, "version");
- lua_pushstring(lua, source);
+ lua_pushstring(lua, fromidx == 2? "versions" : "tags");
lua_setfield(lua, -2, "source");
+ // exit the popped semver
+ semver_dtor(&top);
+
+ // ok
+ return tb_true;
+}
+
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
+/* select version
+ *
+ * local versioninfo, errors = semver.select(">=1.5.0 <1.6", {"1.5.0", "1.5.1"}, {"v1.5.0", ..}, {"master", "dev"})
+ */
+tb_int_t xm_semver_select(lua_State* lua)
+{
+// lua_settop(lua, 4);
+
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ // select version
+ tb_bool_t ok = tb_false;
+ tb_bool_t is_range = tb_false;
+ tb_char_t const* range_str = tb_null;
+ semver_t semver = {0};
+ semvers_t matches = {0};
+ semver_range_t range = {0};
+ do
+ {
+ // get the version range string
+ range_str = luaL_checkstring(lua, 1);
+ tb_check_break(range_str);
+
+ // get the range string length
+ tb_size_t range_len = tb_strlen(range_str);
+
+ // 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_tags(lua, 2, &semver, &range, &matches))
+ {
+ ok = tb_true;
+ break;
+ }
+
+ // attempt to select version from the tags list
+ if (xm_semver_select_from_versions_tags(lua, 3, &semver, &range, &matches))
+ {
+ ok = tb_true;
+ break;
+ }
+ }
+
+ // attempt to select version from the branches
+ if (xm_semver_select_from_branches(lua, 4, range_str, range_len))
+ {
+ ok = tb_true;
+ break;
+ }
+
+ // select the lastest version from the tags and versions if be master
+ if (!tb_strcmp(range_str, "master"))
+ {
+ // attempt to select master version from the versions list
+ if (xm_semver_select_master_from_versions_tags(lua, 2, &semver, &matches))
+ {
+ ok = tb_true;
+ break;
+ }
+
+ // attempt to select master version from the tags list
+ if (xm_semver_select_master_from_versions_tags(lua, 3, &semver, &matches))
+ {
+ ok = tb_true;
+ break;
+ }
+ }
+
+ } while (0);
+
+ // exit matches
semvers_dtor(matches);
- semver_dtor(&semver);
+
+ // exit range
semver_range_dtor(&range);
+ // failed?
+ if (!ok)
+ {
+ if (!is_range)
+ {
+ lua_pushnil(lua);
+ lua_pushfstring(lua, "unable to parse semver range '%s'", range_str);
+ }
+
+ lua_pushnil(lua);
+ lua_pushfstring(lua, "unable to select version for range '%s'", range_str);
+ return 2;
+ }
+
+ // ok
return 1;
}
diff --git a/core/src/xmake/semver/semver.c b/core/src/xmake/semver/semver.c
index 27dfb3fb6..f6e93dc23 100644
--- a/core/src/xmake/semver/semver.c
+++ b/core/src/xmake/semver/semver.c
@@ -19,7 +19,7 @@
* Copyright (C) 2015 - 2017, TBOOX Open Source Group.
*
* @author uael
- * @file semver.c
+ * @file semver->c
*
*/
@@ -37,53 +37,53 @@
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
-
-void lua_pushsemver(lua_State *lua, const semver_t semver)
+tb_void_t lua_pushsemver(lua_State *lua, semver_t const* semver)
{
- semver_id_t const *id;
- tb_uchar_t i = 0;
+ // check
+ tb_assert(lua && semver);
+ // return a semver table
lua_createtable(lua, 0, 7);
- lua_pushstring(lua, semver.raw);
+ lua_pushstring(lua, semver->raw);
lua_setfield(lua, -2, "raw");
- lua_pushlstring(lua, semver.raw, semver.len);
+ lua_pushlstring(lua, semver->raw, semver->len);
lua_setfield(lua, -2, "version");
- lua_pushinteger(lua, semver.major);
+ lua_pushinteger(lua, semver->major);
lua_setfield(lua, -2, "major");
- lua_pushinteger(lua, semver.minor);
+ lua_pushinteger(lua, semver->minor);
lua_setfield(lua, -2, "minor");
- lua_pushinteger(lua, semver.patch);
+ lua_pushinteger(lua, semver->patch);
lua_setfield(lua, -2, "patch");
+ // push prelease table
lua_pushstring(lua, "prerelease");
lua_newtable(lua);
- id = &semver.prerelease;
- while (id && id->len) {
- if (id->numeric) {
- lua_pushinteger(lua, id->num);
- } else {
- lua_pushlstring(lua, id->raw, id->len);
- }
+
+ tb_uchar_t i = 0;
+ semver_id_t const* id = &semver->prerelease;
+ while (id && id->len)
+ {
+ if (id->numeric) lua_pushinteger(lua, id->num);
+ else lua_pushlstring(lua, id->raw, id->len);
id = id->next;
lua_rawseti(lua, -2, ++i);
}
lua_settable(lua, -3);
+ // push the build table
i = 0;
lua_pushstring(lua, "build");
lua_newtable(lua);
- id = &semver.build;
- while (id && id->len) {
- if (id->numeric) {
- lua_pushinteger(lua, id->num);
- } else {
- lua_pushlstring(lua, id->raw, id->len);
- }
+ id = &semver->build;
+ while (id && id->len)
+ {
+ if (id->numeric) lua_pushinteger(lua, id->num);
+ else lua_pushlstring(lua, id->raw, id->len);
id = id->next;
lua_rawseti(lua, -2, ++i);
}
diff --git a/tests/modules/semver/test.lua b/tests/modules/semver/test.lua
index 884eaf82e..f6583930e 100755
--- a/tests/modules/semver/test.lua
+++ b/tests/modules/semver/test.lua
@@ -33,6 +33,10 @@ function _test_semver_select()
, {"v1.2.0", "v1.6.0"}
, {"master", "dev"})
+ _check_semver_select({"1.5.1", "versions"}
+ , "master"
+ , {"1.4.0", "1.5.0", "1.5.1"})
+
print("semver.select: ok!")
end
diff --git a/xmake/core/sandbox/modules/import/core/base/semver.lua b/xmake/core/sandbox/modules/import/core/base/semver.lua
index 08a43dd76..85642195b 100644
--- a/xmake/core/sandbox/modules/import/core/base/semver.lua
+++ b/xmake/core/sandbox/modules/import/core/base/semver.lua
@@ -51,6 +51,7 @@ end
-- semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') => true
--
function sandbox_core_base_semver.satisfies(version, range)
+
-- satisfies version
local result, errors = semver.satisfies(version, range)
if errors then