Adding update mechanism
This commit is contained in:
13
Launch.lua
13
Launch.lua
@@ -14,8 +14,19 @@ SetMainObject(launch)
|
||||
|
||||
function launch:OnInit()
|
||||
ConPrintf("Loading main script...")
|
||||
local mainFile = io.open("Modules/Main.lua")
|
||||
if mainFile then
|
||||
mainFile:close()
|
||||
else
|
||||
if LoadModule("Update", "CHECK") then
|
||||
Exit("Failed to install.")
|
||||
else
|
||||
Restart()
|
||||
end
|
||||
return
|
||||
end
|
||||
local errMsg
|
||||
errMsg, self.main = PLoadModule("Modules/main", self)
|
||||
errMsg, self.main = PLoadModule("Modules/Main", self)
|
||||
if errMsg then
|
||||
self:ShowErrMsg("Error loading main script: %s", errMsg)
|
||||
elseif not self.main then
|
||||
|
||||
@@ -5,12 +5,18 @@
|
||||
-- Installation bootstrap
|
||||
--
|
||||
|
||||
local basicFiles = {
|
||||
["Launch.lua"] = "https://raw.githubusercontent.com/Openarl/PathOfBuilding/master/Launch.lua",
|
||||
["Update.lua"] = "https://raw.githubusercontent.com/Openarl/PathOfBuilding/master/Update.lua",
|
||||
}
|
||||
local curl = require("lcurl")
|
||||
local outFile = io.open("Launch.lua", "wb")
|
||||
local easy = curl.easy()
|
||||
easy:setopt_url("https://raw.githubusercontent.com/Openarl/PathOfBuilding/master/Launch.lua")
|
||||
easy:setopt_writefunction(outFile)
|
||||
easy:perform()
|
||||
easy:close()
|
||||
outFile:close()
|
||||
for name, url in pairs(basicFiles) do
|
||||
local outFile = io.open(name, "wb")
|
||||
local easy = curl.easy()
|
||||
easy:setopt_url(url)
|
||||
easy:setopt_writefunction(outFile)
|
||||
easy:perform()
|
||||
easy:close()
|
||||
outFile:close()
|
||||
end
|
||||
Restart()
|
||||
@@ -7,6 +7,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Launch.lua = Launch.lua
|
||||
LaunchInstall.lua = LaunchInstall.lua
|
||||
Update.lua = Update.lua
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gem DB", "Gem DB", "{EE9D06F5-7310-4567-AB18-6923BCF0A2A1}"
|
||||
|
||||
218
Update.lua
Normal file
218
Update.lua
Normal file
@@ -0,0 +1,218 @@
|
||||
#@
|
||||
-- Path of Building
|
||||
--
|
||||
-- Module: Update
|
||||
-- Checks for and applies updates
|
||||
--
|
||||
local mode = ...
|
||||
|
||||
local xml = require("xml")
|
||||
local sha1 = require("sha1")
|
||||
local curl = require("lcurl")
|
||||
local lzip = require("lzip")
|
||||
|
||||
local function downloadFile(url, outName)
|
||||
local outFile = io.open(outName, "wb")
|
||||
local easy = curl.easy()
|
||||
easy:setopt_url(url)
|
||||
easy:setopt_writefunction(outFile)
|
||||
easy:perform()
|
||||
local code = easy:getinfo(curl.INFO_RESPONSE_CODE)
|
||||
easy:close()
|
||||
outFile:close()
|
||||
if code ~= 200 then
|
||||
ConPrintf("Download failed (code %d)", code)
|
||||
os.remove(outName)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
if mode == "CHECK" then
|
||||
ConPrintf("Checking for update...")
|
||||
|
||||
-- Load and process local manifest
|
||||
local localVer
|
||||
local localPlatform
|
||||
local localFiles = { }
|
||||
local localManXML = xml.LoadXMLFile("manifest.xml")
|
||||
local localSource
|
||||
if localManXML and localManXML[1].elem == "PoBVersion" then
|
||||
for _, node in ipairs(localManXML[1]) do
|
||||
if type(node) == "table" then
|
||||
if node.elem == "Version" then
|
||||
localVer = node.attrib.number
|
||||
localPlatform = node.attrib.platform
|
||||
elseif node.elem == "Source" then
|
||||
if node.attrib.part == "program" then
|
||||
localSource = node.attrib.url
|
||||
end
|
||||
elseif node.elem == "File" then
|
||||
localFiles[node.attrib.name] = { sha1 = node.attrib.sha1, part = node.attrib.part, platform = node.attrib.platform }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not localVer or not localSource or not next(localFiles) then
|
||||
ConPrintf("Update failed: invalid local manifest")
|
||||
return true
|
||||
end
|
||||
|
||||
-- Download and process remote manifest
|
||||
local remoteVer
|
||||
local remoteFiles = { }
|
||||
local remoteManText = ""
|
||||
local remoteSources = { }
|
||||
local easy = curl.easy()
|
||||
easy:setopt_url(localSource.."manifest.xml")
|
||||
easy:setopt_writefunction(function(data)
|
||||
remoteManText = remoteManText..data
|
||||
return true
|
||||
end)
|
||||
easy:perform()
|
||||
easy:close()
|
||||
local remoteManXML = xml.ParseXML(remoteManText)
|
||||
if remoteManXML and remoteManXML[1].elem == "PoBVersion" then
|
||||
for _, node in ipairs(remoteManXML[1]) do
|
||||
if type(node) == "table" then
|
||||
if node.elem == "Version" then
|
||||
remoteVer = node.attrib.number
|
||||
elseif node.elem == "Source" then
|
||||
if not remoteSources[node.attrib.part] then
|
||||
remoteSources[node.attrib.part] = { }
|
||||
end
|
||||
remoteSources[node.attrib.part][node.attrib.platform or "any"] = node.attrib.url
|
||||
elseif node.elem == "File" then
|
||||
if not node.attrib.platform or node.attrib.platform == localPlatform then
|
||||
remoteFiles[node.attrib.name] = { sha1 = node.attrib.sha1, part = node.attrib.part, platform = node.attrib.platform }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not remoteVer or not next(remoteSources) or not next(remoteFiles) then
|
||||
ConPrintf("Update failed: invalid remote manifest")
|
||||
return true
|
||||
end
|
||||
|
||||
-- Build lists of files to be updated or deleted
|
||||
local updateFiles = { }
|
||||
for name, data in pairs(remoteFiles) do
|
||||
data.name = name
|
||||
if not localFiles[name] or localFiles[name].sha1 ~= data.sha1 then
|
||||
table.insert(updateFiles, data)
|
||||
elseif localFiles[name] then
|
||||
local file = io.open(name, "rb")
|
||||
if not file then
|
||||
ConPrintf("Warning: '%s' doesn't exist, it will be re-downloaded", data.name)
|
||||
table.insert(updateFiles, data)
|
||||
else
|
||||
local content = file:read("*a")
|
||||
file:close()
|
||||
if data.sha1 ~= sha1(content) then
|
||||
ConPrintf("Warning: Integrity check on '%s' failed, it will be replaced", data.name)
|
||||
table.insert(updateFiles, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local deleteFiles = { }
|
||||
for name, data in pairs(localFiles) do
|
||||
data.name = name
|
||||
if not remoteFiles[name] then
|
||||
table.insert(deleteFiles, data)
|
||||
end
|
||||
end
|
||||
|
||||
if #updateFiles == 0 and #deleteFiles == 0 then
|
||||
ConPrintf("Update failed: nothing to update")
|
||||
return
|
||||
end
|
||||
|
||||
MakeDir("Update")
|
||||
ConPrintf("Downloading update...")
|
||||
|
||||
-- Download files that need updating
|
||||
local failedFile = false
|
||||
local zipFiles = { }
|
||||
for _, data in ipairs(updateFiles) do
|
||||
local partSources = remoteSources[data.part]
|
||||
local source = partSources[localPlatform] or partSources["any"]
|
||||
local fileName = "Update/"..data.name:gsub("[\\/]","{slash}")
|
||||
data.updateFileName = fileName
|
||||
local zipName = source:match("/([^/]+%.zip)$")
|
||||
if zipName then
|
||||
if not zipFiles[zipName] then
|
||||
ConPrintf("Downloading %s...", zipName)
|
||||
local zipFileName = "Update/"..zipName
|
||||
downloadFile(source, zipFileName)
|
||||
zipFiles[zipName] = lzip.open(zipFileName)
|
||||
end
|
||||
local zip = zipFiles[zipName]
|
||||
if zip then
|
||||
local zippedFile = zip:OpenFile(data.name)
|
||||
if zippedFile then
|
||||
local file = io.open(fileName, "wb")
|
||||
file:write(zippedFile:Read("*a"))
|
||||
file:close()
|
||||
zippedFile:close()
|
||||
else
|
||||
ConPrintf("Couldn't extract '%s' from '%s' (extract failed)", data.name, zipName)
|
||||
failedFile = true
|
||||
end
|
||||
else
|
||||
ConPrintf("Couldn't extract '%s' from '%s' (zip open failed)", data.name, zipName)
|
||||
failedFile = true
|
||||
end
|
||||
elseif source == "" then
|
||||
ConPrintf("File '%s' has no source", data.name)
|
||||
failedFile = true
|
||||
else
|
||||
ConPrintf("Downloading %s...", data.name)
|
||||
if downloadFile(source..data.name, fileName) then
|
||||
failedFile = true
|
||||
end
|
||||
end
|
||||
end
|
||||
for name, zip in pairs(zipFiles) do
|
||||
zip:Close()
|
||||
os.remove(name)
|
||||
end
|
||||
if failedFile then
|
||||
ConPrintf("Update failed: failed to get all required files")
|
||||
return true
|
||||
end
|
||||
|
||||
-- Create new manifest
|
||||
localManXML = { elem = "PoBVersion" }
|
||||
table.insert(localManXML, { elem = "Version", attrib = { number = remoteVer, platform = localPlatform } })
|
||||
for part, platforms in pairs(remoteSources) do
|
||||
for platform, url in pairs(platforms) do
|
||||
table.insert(localManXML, { elem = "Source", attrib = { part = part, platform = platform ~= "any" and platform, url = url } })
|
||||
end
|
||||
end
|
||||
for name, data in pairs(remoteFiles) do
|
||||
table.insert(localManXML, { elem = "File", attrib = { name = data.name, sha1 = data.sha1, part = data.part, platform = data.platform } })
|
||||
end
|
||||
xml.SaveXMLFile(localManXML, "Update/manifest.xml")
|
||||
|
||||
-- Build list of operations to apply the update
|
||||
local ops = { }
|
||||
for _, data in pairs(updateFiles) do
|
||||
table.insert(ops, 'copy "'..data.updateFileName..'" "'..data.name..'"')
|
||||
table.insert(ops, 'delete "'..data.updateFileName..'"')
|
||||
end
|
||||
for _, data in pairs(deleteFiles) do
|
||||
table.insert(ops, 'delete "'..data.name..'"')
|
||||
end
|
||||
table.insert(ops, 'copy "Update/manifest.xml" "manifest.xml"')
|
||||
table.insert(ops, 'delete "manifest.xml"')
|
||||
|
||||
-- Write operations file
|
||||
local opFile = io.open("Update/opFile.txt", "w")
|
||||
opFile:write(table.concat(ops, "\n"))
|
||||
opFile:close()
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
<Version number="0.1.0"/>
|
||||
<Source part="program" url="https://raw.githubusercontent.com/Openarl/PathOfBuilding/master/"/>
|
||||
<Source url="" part="runtime" platform="win32"/>
|
||||
<File sha1="9ec3158f522f0b679c7b544f0fca3f9643169b5d" name="Launch.lua" part="program"/>
|
||||
<File sha1="9076ebeba45897415ec7218227dfe755a9f46772" name="Launch.lua" part="program"/>
|
||||
<File sha1="bc07808d147b2e79f9424e23a74f9b80c12c037a" name="Update.lua" part="program"/>
|
||||
<File sha1="434890f159cb67a73b0489e07471a101582e7168" name="Classes/ButtonControl.lua" part="program"/>
|
||||
<File sha1="991b3deecb4ae60eee54e5b81d4e10a67da80dc7" name="Classes/DropDownControl.lua" part="program"/>
|
||||
<File sha1="1571a47a5549a9ae38407b88012fda39f7ad1ce0" name="Classes/EditControl.lua" part="program"/>
|
||||
@@ -48,10 +49,10 @@
|
||||
<File sha1="e7ee7e5b6388facb7bf568517ecc401590757df7" name="Assets/ring.png" part="program"/>
|
||||
<File platform="win32" sha1="f545caeb86d355698eaff4d665b3af7f17154fb9" name="PathOfBuilding.exe" part="runtime"/>
|
||||
<File platform="win32" sha1="914d42ca1836c5152a5f60aad23020a86bcb46d9" name="lua51.dll" part="runtime"/>
|
||||
<File platform="win32" sha1="273c678ccc57ad229f173c5a9e607467a0204e85" name="SimpleGraphic.dll" part="runtime"/>
|
||||
<File platform="win32" sha1="02a3faa603efa313e17397257be29de0762b2779" name="SimpleGraphic.dll" part="runtime"/>
|
||||
<File platform="win32" sha1="887fd08cb3c2989a9d88adc9717d3ec00ab97462" name="libcurl.dll" part="runtime"/>
|
||||
<File platform="win32" sha1="607918daf9cbaecee0090e9cec8d0e221338678e" name="lcurl.dll" part="runtime"/>
|
||||
<File platform="win32" sha1="13dee45c24c936aa83ca7d9c66833108841c1c04" name="lzip.dll" part="runtime"/>
|
||||
<File platform="win32" sha1="abd8665bff90094fea7d9f116f2a084430410d94" name="lzip.dll" part="runtime"/>
|
||||
<File sha1="74cc6c47e7cda18211e57b9e062368eab3c26bab" name="DLSG/Fonts/Bitstream Vera Sans Mono.10.tga" part="runtime"/>
|
||||
<File sha1="1977206f0efc5035834ecbf93ca7d046010d8aab" name="DLSG/Fonts/Bitstream Vera Sans Mono.12.tga" part="runtime"/>
|
||||
<File sha1="93a4309dc814914be7d2dee708e3821494f145a2" name="DLSG/Fonts/Bitstream Vera Sans Mono.14.tga" part="runtime"/>
|
||||
@@ -86,4 +87,5 @@
|
||||
<File sha1="16cbc26080996d9da827df42cb0844a25518eeb3" name="lua/dkjson.lua" part="runtime"/>
|
||||
<File sha1="31e325cd40a9c0234c6265689cf70b97ef676f20" name="lua/sha1.lua" part="runtime"/>
|
||||
<File sha1="859e09104842f91a4aaa9a4d9fadf667535877e2" name="lua/xml.lua" part="runtime"/>
|
||||
<File sha1="694ba648276e1308c7bc769389352a6c5e5e6408" name="lua/simplegraphic/editfield.lua" part="runtime"/>
|
||||
</PoBVersion>
|
||||
|
||||
Reference in New Issue
Block a user