Files
oc-baserepo/updater.lua

232 lines
6.9 KiB
Lua

local args = {...}
local internet=require("internet")
local text=require("text")
local filesystem=require("filesystem")
local unicode=require("unicode")
local term=require("term")
local event=require("event")
local keyboard=require("keyboard")
local repository = "seesberger/PowerManager"
local targetFilepath = "/usr/PowerManager/"
local helpText = "Usage:\n" .. "updater <nothing> - manual update and install\n".."updater -h - this particular text\n" .. " '' -a - automatic update no install\n" .. " '' -i - automatic update and install"
function manualUpdate()
downloadRepo(repository, targetFilepath, false)
end
function manualInstall()
os.execute(targetFilepath.."installer.lua -m")
end
function automaticUpdate()
downloadRepo(repository, targetFilepath, true)
end
function automaticInstall()
os.execute(targetFilepath.."installer.lua -a")
end
function downloadRepo(repo, target, auto)
if not repo:match("^[%w-.]*/[%w-.]*$") then
print('"'..repo..'" does not look like a valid repo identifier.\nShould be <owner>/<reponame>')
return
end
target=target and ("/"..target:match("^/?(.-)/?$").."/") or "/tmp/"..repo
if filesystem.exists(target) then
if not filesystem.isDirectory(target) then
print("target directory already exists and is not a directory.")
return
end
if filesystem.get(target).isReadOnly() then
print("target directory is read-only.")
return
end
else
if not filesystem.makeDirectory(target) then
print("target directory is read-only")
return
end
end
-- this isn't acually used, but it is tested and works on decoding the base64 encoded data that github
--sends for some queries, leaving it in here for possible future/related use, might be able to pull
--and display difs and things like that?
local symb="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
function decode64(text)
local val,bits=0,0
local output=""
for ch in text:gmatch(".") do
if symb:find(ch) then
--print("ch "..ch.."-> "..(symb:find(ch)-1))
val=bit32.lshift(val,6)+symb:find(ch)-1
else
print(ch.."?")
return
end
bits=bits+6
--print("bits : "..bits)
--print(string.format("val : 0x%04x",val))
if bits>=8 then
local och=unicode.char(bit32.rshift(val,bits-8))
--print("os<<"..och)
--print("& with "..(2^(bits-8)-1))
val=bit32.band(val,2^(bits-8)-1)
bits=bits-8
--print(string.format("val : 0x%04x",val))
output=output..och
end
end
return output
end
local function gitContents(repo, dir)
print("fetching contents for "..repo..dir)
local url="https://api.github.com/repos/"..repo.."/contents"..dir
local result,response=pcall(internet.request,url)
local raw=""
local files={}
local directories={}
if result then
for chunk in response do
raw=raw..chunk
end
else
error("you've been cut off. Serves you right.")
end
response=nil
raw=raw:gsub("%[","{"):gsub("%]","}"):gsub("(\".-\"):(.-[,{}])",function(a,b) return "["..a.."]="..b end)
local t=load("return "..raw)()
for i=1,#t do
if t[i].type=="dir" then
table.insert(directories,dir.."/"..t[i].name)
local subfiles,subdirs=gitContents(repo,dir.."/"..t[i].name)
for i=1,#subfiles do
table.insert(files,subfiles[i])
end
for i=1,#subdirs do
table.insert(directories,subdirs[i])
end
else
files[#files+1]=dir.."/"..t[i].name
end
end
return files, directories
end
local files,dirs=gitContents(repo,"")
for i=1,#dirs do
print("making dir "..target..dirs[i])
if filesystem.exists(target..dirs[i]) then
if not filesystem.isDirectory(target..dirs[i]) then
print("error: directory "..target..dirs[i].." blocked by file with the same name")
return
end
else
filesystem.makeDirectory(target..dirs[i])
end
end
local replaceMode="ask"
if auto then replacemode = "always" end
for i=1,#files do
local replace=nil
if filesystem.exists(target..files[i]) then
if filesystem.isDirectory(target..files[i]) then
print("Error: file "..target..files[i].." blocked by directory with same name!")
return
end
if replaceMode=="always" then
replace=true
elseif replaceMode=="never" then
replace=false
else
print("\nFile "..target..files[i].." already exists.\nReplace with new version?")
local response=""
while replace==nil do
term.write("yes,no,always,skip all[ynAS]: ")
local char
repeat
_,_,char=event.pull("key_down")
until not keyboard.isControl(char)
char=unicode.char(char)
print(char)
if char=="A" then
replaceMode="always"
replace=true
char="y"
elseif char=="S" then
replaceMode="never"
replace=false
char="n"
elseif char:lower()=="y" then
replace=true
elseif char:lower()=="n" then
replace=false
else
print("invalid response.")
end
end
end
if replace then
filesystem.remove(target..files[i])
end
end
if replace~=false then
print("downloading "..files[i])
local url="https://raw.github.com/"..repo.."/master"..files[i]
local result,response=pcall(internet.request,url)
if result then
local raw=""
for chunk in response do
raw=raw..chunk
end
print("writing to "..target..files[i])
local file=io.open(target..files[i],"w")
file:write(raw)
file:close()
else
print("failed, skipping")
end
end
end
end
if #args<1 then
print("No Arguments given. Manual process...")
manualUpdate()
return
end
if args == "-h" then
print(helpText)
return
elseif args == "-a" then
automaticUpdate()
return
elseif args == "-i" then
automaticUpdate()
automaticInstall()
return
else
print('"'..args[1]..'" - Bad argument.')
print(helpText)
return
end