mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-19 04:06:10 +02:00
Merge pull request #1446 from 1Jamie/feat/launcher-fixes-and-patch-notes
This commit is contained in:
@@ -979,7 +979,7 @@ function LauncherView._updateControl(imp)
|
||||
end
|
||||
-- idle / uptodate / error: offer a manual check, with no glow.
|
||||
return status, Strings("Check for updates"),
|
||||
function() pcall(imp.Check.start) end, false
|
||||
function() pcall(imp.Check.start, true) end, false
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------ game panel
|
||||
|
||||
@@ -155,11 +155,12 @@ local function drain()
|
||||
end
|
||||
|
||||
-- Begin (or, on a prior error, retry) an async check. Safe to call every frame:
|
||||
-- once a check is in flight or has reached a terminal state it is a no-op.
|
||||
function Check.start()
|
||||
-- once a check is in flight or has reached a terminal state it is a no-op unless
|
||||
-- force=true is passed (e.g. from an explicit button press).
|
||||
function Check.start(force)
|
||||
drain()
|
||||
if cache.status == "checking" or cache.status == "downloading" then return end
|
||||
if requested and cache.status ~= "error" and cache.status ~= "idle" then return end
|
||||
if not force and requested and cache.status ~= "error" and cache.status ~= "idle" then return end
|
||||
if not ensureWorker() then
|
||||
cache = { status = "error", error = "background threads unavailable" }
|
||||
return
|
||||
|
||||
@@ -16,6 +16,10 @@ PatchNotes.FILES = {
|
||||
"assets/PATCH_NOTES.md",
|
||||
}
|
||||
|
||||
PatchNotes.CACHE_FILES = {
|
||||
"updates/notes_cache.json",
|
||||
}
|
||||
|
||||
PatchNotes.REPO_FILES = {
|
||||
"mobile/ios/app-repo.json",
|
||||
}
|
||||
@@ -48,6 +52,29 @@ local function readPath(path)
|
||||
return nonempty(text) and text or nil
|
||||
end
|
||||
|
||||
function PatchNotes.fromCache(engine)
|
||||
for _, path in ipairs(PatchNotes.CACHE_FILES) do
|
||||
local text = readPath(path)
|
||||
if text then
|
||||
local ok, doc = pcall(Json.decode, text)
|
||||
if ok and type(doc) == "table" then
|
||||
if engine and engine ~= "0.0.0-dev" then
|
||||
if doc[engine] and nonempty(doc[engine]) then
|
||||
return doc[engine], engine
|
||||
end
|
||||
else
|
||||
for ver, notes in pairs(doc) do
|
||||
if nonempty(notes) then
|
||||
return notes, ver
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
function PatchNotes.fromFile()
|
||||
for _, path in ipairs(PatchNotes.FILES) do
|
||||
local text = readPath(path)
|
||||
@@ -88,6 +115,7 @@ function PatchNotes.fromRepo(engine)
|
||||
return row.notes, row.version
|
||||
end
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
return list[1].notes, list[1].version
|
||||
end
|
||||
@@ -96,17 +124,24 @@ function PatchNotes.fromRepo(engine)
|
||||
end
|
||||
|
||||
function PatchNotes.body(Check)
|
||||
local notes, ver = PatchNotes.fromCheck(Check)
|
||||
if notes then return notes, ver end
|
||||
notes = PatchNotes.fromFile()
|
||||
if notes then return notes, ver end
|
||||
local Version = require("src.core.Version")
|
||||
local engine = (Version and Version.engine) or "?"
|
||||
|
||||
local notes, ver = PatchNotes.fromCheck(Check)
|
||||
if notes and (engine == "0.0.0-dev" or ver == engine or ver == nil) then
|
||||
return notes, ver or engine
|
||||
end
|
||||
|
||||
notes, ver = PatchNotes.fromCache(engine)
|
||||
if notes then return notes, ver end
|
||||
|
||||
notes = PatchNotes.fromFile()
|
||||
if notes then return notes, engine end
|
||||
|
||||
notes, ver = PatchNotes.fromRepo(engine)
|
||||
if notes then return notes, ver end
|
||||
return "No patch notes loaded yet for gen1recomp v" .. engine .. ".\n\n"
|
||||
.. "They appear here after the launcher checks GitHub for the latest "
|
||||
.. "release.", engine
|
||||
|
||||
return "Unable to fetch patch notes.", engine
|
||||
end
|
||||
|
||||
return PatchNotes
|
||||
|
||||
@@ -151,6 +151,28 @@ local function gatePasses(rel)
|
||||
return not (info.minShell and info.minShell > shell)
|
||||
end
|
||||
|
||||
local function cacheNotes(ver, notes)
|
||||
if not (ver and type(notes) == "string" and notes ~= "" and Json) then return end
|
||||
if not (love and love.filesystem) then return end
|
||||
pcall(function()
|
||||
love.filesystem.createDirectory("updates")
|
||||
local cachePath = "updates/notes_cache.json"
|
||||
local existing = {}
|
||||
if love.filesystem.getInfo and love.filesystem.getInfo(cachePath) then
|
||||
local text = love.filesystem.read(cachePath)
|
||||
if text then
|
||||
local ok, doc = pcall(Json.decode, text)
|
||||
if ok and type(doc) == "table" then existing = doc end
|
||||
end
|
||||
end
|
||||
existing[ver] = notes
|
||||
local ok, encoded = pcall(Json.encode, existing)
|
||||
if ok and encoded then
|
||||
love.filesystem.write(cachePath, encoded)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- check
|
||||
-- ---------------------------------------------------------------------------
|
||||
@@ -177,6 +199,9 @@ local function doCheck()
|
||||
return
|
||||
end
|
||||
pending = rel
|
||||
if rel.version and type(rel.notes) == "string" and rel.notes ~= "" then
|
||||
cacheNotes(rel.version, rel.notes)
|
||||
end
|
||||
|
||||
-- Unstamped dev build: the working tree always looks "newer", so never
|
||||
-- pester the developer with an update (contract item, Check design).
|
||||
|
||||
+203
-279
File diff suppressed because it is too large
Load Diff
@@ -68,6 +68,12 @@ do
|
||||
"stashed notes name a release version")
|
||||
end
|
||||
|
||||
do
|
||||
local notes, ver = PatchNotes.fromRepo("999.999.999")
|
||||
eq(notes, nil, "fromRepo returns nil when a specific engine version is missing")
|
||||
eq(ver, nil, "fromRepo version is nil when missing")
|
||||
end
|
||||
|
||||
do
|
||||
local f = assert(io.open("mobile/ios/app-repo.json", "rb"))
|
||||
local list = PatchNotes.parseRepo(f:read("*a"))
|
||||
@@ -78,6 +84,15 @@ do
|
||||
eq(notes, list[2].notes, "fromRepo returns that version's notes")
|
||||
end
|
||||
|
||||
do
|
||||
local oldVersion = package.loaded["src.core.Version"]
|
||||
package.loaded["src.core.Version"] = { engine = "999.999.999" }
|
||||
local body, ver = PatchNotes.body(nil)
|
||||
eq(body, "Unable to fetch patch notes.", "returns Unable to fetch patch notes when version is uncached and unlisted")
|
||||
eq(ver, "999.999.999", "returns the requested engine version")
|
||||
package.loaded["src.core.Version"] = oldVersion
|
||||
end
|
||||
|
||||
imp._appPatchNotes = true
|
||||
local modal = drawAndCapture(imp)
|
||||
check(modal:find("Patch notes", 1, true) ~= nil, "the modal titles itself")
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
-- Source file LuaJIT limits gate.
|
||||
-- Verifies that every game engine source file compiles cleanly under
|
||||
-- LuaJIT without exceeding LuaJIT's strict 200 local variables per-scope limit,
|
||||
-- 60 upvalue limit, or bytecode compiler limits.
|
||||
-- luajit tests/engine/luajit_source_limits_test.lua
|
||||
|
||||
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||||
|
||||
local T = require("tests.harness")
|
||||
local check, eq = T.check, T.eq
|
||||
|
||||
-- Find all .lua files in a directory recursively.
|
||||
local function findLuaFiles(dir, out)
|
||||
out = out or {}
|
||||
local p = io.popen("find " .. dir .. " -type f -name '*.lua'")
|
||||
if p then
|
||||
for line in p:lines() do
|
||||
out[#out + 1] = line
|
||||
end
|
||||
p:close()
|
||||
end
|
||||
table.sort(out)
|
||||
return out
|
||||
end
|
||||
|
||||
local files = findLuaFiles("src")
|
||||
findLuaFiles("tools/save-editor", files)
|
||||
files[#files + 1] = "main.lua"
|
||||
files[#files + 1] = "conf.lua"
|
||||
|
||||
check(#files > 50, "discovered project source files (found " .. tostring(#files) .. ")")
|
||||
|
||||
for _, path in ipairs(files) do
|
||||
local f = assert(io.open(path, "rb"), "could not open " .. path)
|
||||
local source = f:read("*a")
|
||||
f:close()
|
||||
|
||||
-- Compile through LuaJIT loadstring: detects 'main function has more than 200 local variables'
|
||||
-- or 'function has more than 200 local variables' across any function scope in the file.
|
||||
local chunk, err = loadstring(source, "@" .. path)
|
||||
check(chunk ~= nil, path .. " compiles under LuaJIT: " .. tostring(err))
|
||||
end
|
||||
|
||||
-- Meta-test: prove that exceeding 200 locals fails the gate
|
||||
do
|
||||
local overflowLocals = {}
|
||||
for i = 1, 201 do overflowLocals[i] = "v" .. i end
|
||||
local badCode = "local " .. table.concat(overflowLocals, ", ")
|
||||
local chunk, err = loadstring(badCode, "@overflow_test.lua")
|
||||
check(chunk == nil, "LuaJIT strictly rejects chunks exceeding 200 locals")
|
||||
check(tostring(err):find("200 local variables", 1, true) ~= nil, "error message specifies 200 local variable limit")
|
||||
end
|
||||
|
||||
T.finish("luajit_source_limits")
|
||||
Reference in New Issue
Block a user