import("core.base.semver") import("net.http") import("devel.git") import("private.action.require.impl.utils.filter") function shasum_of(package, url, version) local shasum local tmpfile = os.tmpfile() package:version_set(version) url = filter.handle(url, package) local ok = try { function() http.download(url, tmpfile); return true end } if ok and os.isfile(tmpfile) and os.filesize(tmpfile) > 1024 then shasum = hash.sha256(tmpfile) end os.tryrm(tmpfile) return shasum end function _is_valid_version(version) if not semver.is_valid(version) then return false end local v = semver.new(version) local prerelease = v:prerelease() if prerelease and #prerelease > 0 then return false end return true end function _get_version_and_shasum(package, url, version_latest) if version_latest then local has_prefix_v = false for _, version in ipairs(package:versions()) do if version:startswith("v") then has_prefix_v = true end if semver.compare(version, version_latest) >= 0 then version_latest = nil break end end if version_latest then if has_prefix_v and not version_latest:startswith("v") then version_latest = "v" .. version_latest elseif not has_prefix_v and version_latest:startswith("v") then version_latest = version_latest:sub(2) end end end if version_latest then local shasum = shasum_of(package, url, version_latest) if shasum then return version_latest, shasum end end end function _check_version_from_github_tags(package, url) local repourl = url:match("https://github%.com/.-/.-/") if repourl then print("checking version from github tags %s ..", repourl) local version_latest local tags = git.tags(repourl) for _, tag in ipairs(tags) do if _is_valid_version(tag) and (not version_latest or semver.compare(tag, version_latest) > 0) then version_latest = tag end end if version_latest then return _get_version_and_shasum(package, url, version_latest) end end end function _check_version_from_github_releases(package, url) local repourl = url:match("https://github%.com/.-/.-/") if repourl then print("checking version from github releases %s ..", repourl) local list = try {function() return os.iorunv("gh", {"release", "list", "--exclude-drafts", "--exclude-pre-releases", "-R", repourl}) end} if not list then list = os.iorunv("gh", {"release", "list", "-R", repourl}) end if list then local version_latest for _, line in ipairs(list:split("\n")) do local splitinfo = line:split("%s+") local version = splitinfo[#splitinfo - 1] if version and _is_valid_version(version) then version_latest = version break end end if version_latest then return _get_version_and_shasum(package, url, version_latest) end end end end function _version_is_behind_conditions(package) local scriptfile = path.join(package:scriptdir(), "xmake.lua") local file = io.open(scriptfile) for line in file:lines() do local pos = line:find("add_versions", 1, true) or line:find("add_versionfiles", 1, true) if pos and pos > 5 then return true end end file:close() end function main(package) local checkers = { ["https://github%.com/.-/.-/archive/refs/tags/.*"] = _check_version_from_github_tags, ["https://github%.com/.-/.-/releases/download/.*"] = _check_version_from_github_releases } for _, url in ipairs(package:urls()) do for pattern, checker in pairs(checkers) do if url:match(pattern) and not _version_is_behind_conditions(package) then return checker(package, url) end end end end