Last active
August 29, 2015 14:01
-
-
Save SquidDev/47dc8dc6c603af58c339 to your computer and use it in GitHub Desktop.
Installer for SEE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--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