-
Notifications
You must be signed in to change notification settings - Fork 34
base: deps_version_parser.lua #47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
e274472
feat(core): 添加依赖版本解析
MoYingJi 9703454
deps_version_parser: 优化版本号比较功能
MoYingJi e2b9c4f
deps_version_parser: match_version
MoYingJi 0f05d49
deps_version_parser: fun is_range_illegal() and support more cases
MoYingJi 7abf010
fix: remove repeated line in match_version()
MoYingJi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
-- 解析单个版本字符串到版本对象 | ||
function parse_single_version(version_str) | ||
function parse_single_version_range(version_str) | ||
local version = {} | ||
if version_str == "any" or version_str == "*" then | ||
return version end | ||
|
@@ -51,10 +51,10 @@ function parse_single_version(version_str) | |
end | ||
|
||
-- 解析复合版本字符串到版本对象 | ||
function parse_version(version_str) | ||
function parse_version_ranges(version_str) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. local Constraint = {}
Constraint.__index = Constraint
function Constraint:new(str)
local self = setmetatable({},Constraint)
self:parse(str)
return self
end
function Constraint:parse(str)
local pattern = (...)
local op,version_str = str:match(pattern)
self.op = op
self.version = Version:new(version_str)
end
function Constraint:include(version)
if self.operator == "*" then
return true -- "*" means any version
elseif self.operator == "<=" then
return version <= self.version
elseif self.operator == "<" then
return version < self.version
elseif self.operator == ">=" then
return version >= self.version
elseif self.operator == ">" then
return version > self.version
elseif self.operator == "=" then
return version == self.version
else
return false
end
end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. local Constraints = {}
Constraints.__index = Constraints
function Constraints:new(str)
local self = setmetatable({},Constraints)
self:parse(str)
return self
end
function Constraints:parse(str)
self.constraints = {}
for part in str:gmatch(...) do
table.insert(self.constraints,Constraint:new(part))
end
end
function Constraints:include(version)
for _,constraint in ipairs(self.constraints) do
if not constraint:include(verison) then
return false
end
end
return true
end |
||
local conditions = {} | ||
for cond in version_str:gmatch("[^ ,]+") do | ||
table.insert(conditions, parse_single_version(cond)) | ||
table.insert(conditions, parse_single_version_range(cond)) | ||
end | ||
local merged_version | ||
for _, cond in ipairs(conditions) do | ||
|
@@ -87,36 +87,16 @@ function merge_range(a, b) | |
return merged | ||
end | ||
|
||
-- 比较两个版本字符串 | ||
|
||
function compare_version(a, b) | ||
-- TODO 这正则没研究明白 | ||
local av, ar = a:match("^([%d%.]+)([-.+]?.*)$") | ||
local bv, br = b:match("^([%d%.]+)([-.+]?.*)$") | ||
av = av or a; bv = bv or b | ||
local cv = compare_version_number(av, bv) | ||
if cv ~= 0 then return cv end | ||
ar = string.sub(ar, -#ar+1) | ||
br = string.sub(br, -#br+1) | ||
return compare_version_suffix(ar, br) | ||
end | ||
|
||
function compare_version_number(a, b) | ||
--print("comparing number", a or "nil", b or "nil") | ||
if not a then return -1 end | ||
if not b then return 1 end | ||
if a == b then return 0 end | ||
local a_parts = {} | ||
local a_parts = {} local b_parts = {} | ||
for num in a:gmatch("%d+") do table.insert(a_parts, tonumber(num)) end | ||
local b_parts = {} | ||
for num in b:gmatch("%d+") do table.insert(b_parts, tonumber(num)) end | ||
local length = math.max(#a_parts, #b_parts) | ||
while #a_parts < length do table.insert(a_parts, 0) end | ||
while #b_parts < length do table.insert(b_parts, 0) end | ||
for i = 1, length do if a_parts[i] ~= b_parts[i] then | ||
return a_parts[i] > b_parts[i] and 1 or -1 | ||
end end | ||
return 0 | ||
end end return 0 | ||
end | ||
|
||
pre_flags = { | ||
|
@@ -125,7 +105,6 @@ pre_flags = { | |
alpha = -3, a = -3, | ||
} | ||
function compare_version_suffix(a, b) | ||
--print("comparing suffix", a or "nil", b or "nil") | ||
a = a or ""; b = b or "" | ||
if a == b then return 0 end | ||
if a == "" and b ~= "" then return 1 end | ||
|
@@ -141,43 +120,85 @@ function compare_version_suffix(a, b) | |
return 0 | ||
end | ||
|
||
function compare_version(a, b) | ||
-- TODO 这正则没研究明白 | ||
local av, ar = a:match("^([%d%.]+)([-.+]?.*)$") | ||
local bv, br = b:match("^([%d%.]+)([-.+]?.*)$") | ||
av = av or a; bv = bv or b | ||
local cv = compare_version_number(av, bv) | ||
if cv ~= 0 then return cv end | ||
ar = string.sub(ar, -#ar+1) | ||
br = string.sub(br, -#br+1) | ||
return compare_version_suffix(ar, br) | ||
end | ||
|
||
-- 生成所需依赖 | ||
function gen_deps(deps) | ||
local needed_deps = {} | ||
for _, dep_set in ipairs(deps) do for pkg_name, version_str in pairs(dep_set) do | ||
needed_deps[pkg_name] = not needed_deps[pkg_name] and | ||
parse_version(version_str) or | ||
merge_range(needed_deps[pkg_name], parse_version(version_str)) | ||
parse_version_ranges(version_str) or | ||
merge_range(needed_deps[pkg_name], parse_version_ranges(version_str)) | ||
end end return needed_deps | ||
end | ||
|
||
function match_version(range, version) | ||
range = range or {} local cv | ||
cv = range.min and compare_version(range.min, version) or -1 | ||
if cv > 0 then return false end | ||
if cv == 0 and not range.min_inclusive then return false end | ||
cv = range.max and compare_version(range.max, version) or 1 | ||
cv = range.max and compare_version(range.max, version) or 1 | ||
if cv < 0 then return false end | ||
if cv == 0 and not range.max_inclusive then return false end | ||
return true | ||
end | ||
|
||
|
||
-- 测试代码 | ||
function main() | ||
-- test gen_deps | ||
local deps = { | ||
{ packageA = "*", packageB = "*", packageC = ">=2" }, | ||
{ packageB = "~5.7.1", packageC = "~3.2.7" }, | ||
{ packageC = "3.0.x" }, | ||
{ packageC = "3.0.5", packageD = ">=3 <4" }, | ||
{ packageE = ">3.15" }, | ||
{ packageA = "*", packageB = "*", packageC = ">=2" }, | ||
{ packageB = "~5.7.1", packageC = "~3.2.7" }, | ||
{ packageC = "3.0.x" }, | ||
{ packageD = ">=3 <4", packageC = "3.0.5", }, | ||
{ packageE = ">3.15" }, | ||
} | ||
local needed_deps = gen_deps(deps) | ||
for pkg, range in pairs(needed_deps) do | ||
print(pkg, range) | ||
end | ||
|
||
-- test compare_version | ||
local versions = { | ||
{ a = "1.2.3", b = "1.3.2" }, | ||
{ a = "1.0.0-beta1", b = "1.0.0-beta2" }, | ||
{ a = "1.0.0", b = "1.0-beta3" }, | ||
{ a = "1.0.0-alpha1", b = "1.0.0-beta2" } | ||
{ a = "1.2.3", b = "1.3.2", result = -1 }, -- < | ||
{ a = "1.0.0-beta1", b = "1.0.0-beta2", result = -1 }, -- < | ||
{ a = "1.0.0-alpha2", b = "1.0.0-beta1", result = -1 }, -- < | ||
{ a = "1.0.0", b = "1.0-beta3", result = 1 }, -- > | ||
} | ||
local function c(a, b) | ||
local r = compare_version(a, b) | ||
if r == 0 then return "[ (==) equals (==) ]" end | ||
return r > 0 and "[ greater (>) than ]" or "[ less (<) than ]" | ||
return r, r > 0 and "[ greater (>) than ]" or "[ less (<) than ]" | ||
end | ||
for _, v in ipairs(versions) do | ||
print(v.a, c(v.a, v.b), v.b) | ||
local r, a = c(v.a, v.b) | ||
print(v.a, a, v.b, " \t\t--", | ||
r == v.result and "test pass" or "TEST ERROR!") | ||
end | ||
|
||
-- test match_version | ||
local matches = { | ||
{ version = "1.2.3", range = "*", result = true }, | ||
{ version = "1.2.3", range = "~1.2.4", result = false }, | ||
{ version = "1.2.3", range = ">=1.2.3-beta", result = true }, | ||
{ version = "1.2.3", range = "1.2.3-beta", result = false }, | ||
} | ||
for _, m in ipairs(matches) do | ||
local range = parse_version_ranges(m.range) | ||
local r = match_version(range, m.version) | ||
print(m.version, r and "in" or "not in", m.range, " \t\t--", | ||
r == m.result and "test pass" or "TEST ERROR!") | ||
end | ||
end |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.