Skip to content

Instantly share code, notes, and snippets.

@SquidDev
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SquidDev/47dc8dc6c603af58c339 to your computer and use it in GitHub Desktop.
Save SquidDev/47dc8dc6c603af58c339 to your computer and use it in GitHub Desktop.
Installer for SEE
--JSON functions
--Credit goes to http://www.computercraft.info/forums2/index.php?/topic/5854-json-api-v201-for-computercraft/
------------------------------------------------------------------ utils
local controls = {["\n"]="\\n", ["\r"]="\\r", ["\t"]="\\t", ["\b"]="\\b", ["\f"]="\\f", ["\""]="\\\"", ["\\"]="\\\\"}
local whites = {['\n']=true; ['r']=true; ['\t']=true; [' ']=true; [',']=true; [':']=true}
function removeWhite(str)
while whites[str:sub(1, 1)] do
str = str:sub(2)
end
return str
end
------------------------------------------------------------------ decoding
function jsonParseBoolean(str)
if str:sub(1, 4) == "true" then
return true, removeWhite(str:sub(5))
else
return false, removeWhite(str:sub(6))
end
end
function jsonParseNull(str)
return nil, removeWhite(str:sub(5))
end
local numChars = {['e']=true; ['E']=true; ['+']=true; ['-']=true; ['.']=true}
function jsonParseNumber(str)
local i = 1
while numChars[str:sub(i, i)] or tonumber(str:sub(i, i)) do
i = i + 1
end
local val = tonumber(str:sub(1, i - 1))
str = removeWhite(str:sub(i))
return val, str
end
function jsonParseString(str)
local i,j = str:find('^".-[^\\]"')
local s = str:sub(i + 1,j - 1)
for k,v in pairs(controls) do
s = s:gsub(v, k)
end
str = removeWhite(str:sub(j + 1))
return s, str
end
function jsonParseArray(str)
str = removeWhite(str:sub(2))
local val = {}
local i = 1
while str:sub(1, 1) ~= "]" do
local v = nil
v, str = jsonParseValue(str)
val[i] = v
i = i + 1
str = removeWhite(str)
end
str = removeWhite(str:sub(2))
return val, str
end
function jsonParseObject(str)
str = removeWhite(str:sub(2))
local val = {}
while str:sub(1, 1) ~= "}" do
local k, v = nil, nil
k, v, str = jsonParseMember(str)
val[k] = v
str = removeWhite(str)
end
str = removeWhite(str:sub(2))
return val, str
end
function jsonParseMember(str)
local k = nil
k, str = jsonParseValue(str)
local val = nil
val, str = jsonParseValue(str)
return k, val, str
end
function jsonParseValue(str)
local fchar = str:sub(1, 1)
if fchar == "{" then
return jsonParseObject(str)
elseif fchar == "[" then
return jsonParseArray(str)
elseif tonumber(fchar) ~= nil or numChars[fchar] then
return jsonParseNumber(str)
elseif str:sub(1, 4) == "true" or str:sub(1, 5) == "false" then
return jsonParseBoolean(str)
elseif fchar == "\"" then
return jsonParseString(str)
elseif str:sub(1, 4) == "null" then
return jsonParseNull(str)
end
return nil
end
function jsonDecode(str)
str = removeWhite(str)
t = jsonParseValue(str)
return t
end
function downloadJson(url)
local file = http.get(url)
if not file then
return nil
end
return jsonDecode(file.readAll())
end
--Settings
local GitHubRepo = "Yevano/see" -- Change to user/repo
local GitHubBranch = "master" -- Change to needed branch
local installPath = "/see"
--Other settings
local GitHubRef = "refs/heads/"..GitHubBranch
local GitHubRaw = 'https://raw.github.com/'..GitHubRepo..'/'..GitHubBranch..'/'
local args = {...}
--Files to not download
local blacklist = {
'.gitignore',
'README.md'
}
function isBlacklisted(path)
for i, item in ipairs(blacklist) do
if item == path then
return true
end
end
return false
end
--List of failed files
local failed = {}
--Download file/create directory or queue to failed queue
function downloadBlob(v)
if isBlacklisted(v.path) then
return
end
--Make dir if needed
if v.type == 'tree' then
fs.makeDir(installPath..v.path)
else
--Start download
local url = (GitHubRaw..v.path):gsub(' ','%%20')
local f = http.get(url)
--If couldn't download then add to failed
if not f then
table.insert(failed,v)
return
end
--Write file
local h = fs.open(installPath..v.path, 'w')
h.write(f.readAll())
h.close()
end
end
--Fail and prompt for retry
local function fail(err)
printError(err)
while true do
write("Retry installation? (y/n): ")
local response = read()
if string.lower(response):gsub("%s", "") == "y" then
return true
elseif string.lower(response):gsub("%s", "") == "n" then
return false
end
print("Invalid input.")
end
end
--Get install directory
while true do
if #args == 1 then
installPath = args[1]
else
write("Choose an install path: ")
installPath = "/" .. shell.resolve(read())
end
local configHandle = fs.open("/.see", "w")
configHandle.write('install_dir = "' .. installPath .. '/see"')
configHandle.close()
local suc, err = pcall(fs.makeDir, installPath)
if not suc then
if not fail("Could not create installation directory.") then error("Exiting") end
else
break
end
end
installPath = installPath .. '/'
local tree = {}
local latestSha = ''
--Get latest commit
while true do
--Get sha for specific branch
local refs = downloadJson('https://api.github.com/repos/'..GitHubRepo..'/git/refs')
if refs == nil then
if not fail("Could not fetch branches") then error("Exiting") end
else
for i, v in ipairs(refs) do
if v.ref == GitHubRef then
latestSha = v.object.sha
break
end
end
break
end
end
--Get tree
while true do
--Download file list
tree = downloadJson('https://api.github.com/repos/'..GitHubRepo..'/git/trees/'..latestSha..'?recursive=1').tree
if tree == nil then
if not fail("Could not fetch tree") then error("Exiting") end
else
break
end
end
--Prepare file download
local downloads = {}
for i, v in ipairs(tree) do
table.insert(downloads, function()downloadBlob(v)end)
end
while true do
parallel.waitForAll(unpack(downloads))
if #failed > 0 then
if not fail("Not all files downloaded. Retry?") then error("Exiting") end
downloads = {}
for i, v in ipairs(failed) do
print("Retrying "..v.path)
table.insert(downloads, function()downloadBlob(v)end)
end
failed = {}
else
break
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment