fix: resolve latest android sdk version numerically - #11
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the version sorting logic in hooks/available.lua to sort Android command-line tool versions numerically in descending order, and introduces a test suite in test/version_order.lua. The review feedback correctly points out that using tonumber directly on version strings will fail for multi-dot versions (e.g., 22.0.1), resulting in incorrect sorting. It is recommended to parse version strings into segment lists for a robust comparison and to expand the test cases to cover these multi-part versions.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| table.sort(versions, function(a, b) | ||
| return a.version < b.version | ||
| local a_number = tonumber(a.version) | ||
| local b_number = tonumber(b.version) | ||
|
|
||
| if a_number and b_number then | ||
| return a_number > b_number | ||
| elseif a_number then | ||
| return true | ||
| elseif b_number then | ||
| return false | ||
| end | ||
|
|
||
| return a.version > b.version | ||
| end) |
There was a problem hiding this comment.
Using tonumber directly on the version string only works for single-dot numeric versions (e.g., 12.0 or 2.1) because they are valid floating-point numbers in Lua. If a version with multiple dots (e.g., 12.0.1 or 12.1.0) is encountered, tonumber will return nil. This causes the version to be treated as non-numeric, resulting in incorrect sorting (sorting it after older numeric versions).
To make the version comparison robust and future-proof, we can parse the version strings into lists of numeric components by splitting them on . and comparing them segment-by-segment.
local function parse_version(version_str)
local parts = {}
for part in string.gmatch(version_str, "[^.]+") do
local num = tonumber(part)
if not num then return nil end
table.insert(parts, num)
end
return parts
end
table.sort(versions, function(a, b)
local a_parts = parse_version(a.version)
local b_parts = parse_version(b.version)
if a_parts and b_parts then
for i = 1, math.max(#a_parts, #b_parts) do
local a_val = a_parts[i] or 0
local b_val = b_parts[i] or 0
if a_val ~= b_val then
return a_val > b_val
end
end
return false
elseif a_parts then
return true
elseif b_parts then
return false
end
return a.version > b.version
end)
| local repository_xml = [[ | ||
| <sdk-repository> | ||
| <remotePackage path="cmdline-tools;1.0"></remotePackage> | ||
| <remotePackage path="cmdline-tools;9.0"></remotePackage> | ||
| <remotePackage path="cmdline-tools;10.0"></remotePackage> | ||
| <remotePackage path="cmdline-tools;22.0"></remotePackage> | ||
| <remotePackage path="cmdline-tools;2.1"></remotePackage> | ||
| <remotePackage path="cmdline-tools;latest"></remotePackage> | ||
| </sdk-repository> | ||
| ]] |
There was a problem hiding this comment.
To ensure that multi-part numeric versions (e.g., 22.0.1, 22.1.0) are correctly handled and sorted by the new comparison logic, let's add them to the mock repository XML.
local repository_xml = [[
<sdk-repository>
<remotePackage path="cmdline-tools;1.0"></remotePackage>
<remotePackage path="cmdline-tools;9.0"></remotePackage>
<remotePackage path="cmdline-tools;10.0"></remotePackage>
<remotePackage path="cmdline-tools;22.0"></remotePackage>
<remotePackage path="cmdline-tools;22.0.1"></remotePackage>
<remotePackage path="cmdline-tools;22.1.0"></remotePackage>
<remotePackage path="cmdline-tools;2.1"></remotePackage>
<remotePackage path="cmdline-tools;latest"></remotePackage>
</sdk-repository>
]]
| PLUGIN = {} | ||
| assert(loadfile(plugin_dir .. "/hooks/available.lua"))() | ||
| local versions = PLUGIN:Available({}) | ||
| local expected = { "22.0", "10.0", "9.0", "2.1", "1.0" } |
|
Thank you very much, @jdx, for the quick response in mise-plugins/mise-android-sdk#39 and for the fix. Appreciate that! |
Summary
1.0,2.1,9.0,10.0, and22.0Root cause
The available hook sorted opaque strings lexicographically in ascending order. vfox resolves an unspecified version from the first returned entry, so
1.0was selected while values such as10.0and22.0were ordered incorrectly. Android command-line tool releases use numeric identifiers, so this backend now applies tool-specific numeric ordering.Validation
mise x stylua@latest -- stylua --check metadata.lua hooks test/version_order.luamise x actionlint@latest -- actionlint .github/workflows/test.ymlmise x lua@5.4 -- lua test/version_order.lua .mise latest android-sdkresolves to22.0./test/run.shResolves #5.