Skip to content

Instantly share code, notes, and snippets.

@SwadicalRag
Last active May 14, 2023 23:30
Show Gist options
  • Save SwadicalRag/906dc2b3cd162559891cfde78f2144fe to your computer and use it in GitHub Desktop.
Save SwadicalRag/906dc2b3cd162559891cfde78f2144fe to your computer and use it in GitHub Desktop.
Load gmod addons from github repositories
local function FetchSync(url)
local this = coroutine.running()
http.Fetch(url,function(...)
local suc,err = coroutine.resume(this,...)
if not suc then error(err) end
end,function(...)
-- local suc,err = coroutine.resume(this,...)
-- if not suc then error(err) end
end)
return coroutine.yield()
end
local function getDir(author,repo,dir)
return util.JSONToTable(FetchSync("https://api.github.com/repos/"..author.."/"..repo.."/contents/"..dir))
end
local function getFile(author,repo,dir,branch)
local data,size,headers,code = FetchSync("https://rawgit.com/"..author.."/"..repo.."/"..(branch or "master").."/"..dir)
return (code ~= 404 and data) or false
end
local function includeRepoInternal(author,repo,getFileOverrides,runExtra)
local getEnv
local cDir = {""}
local function compileFileInternal(path,...)
path = "lua/"..path
local contents
if getFileOverrides[path] then
contents = getFileOverrides[path]
else
contents = getFile(author,repo,path)
if not contents then return false end
end
-- print("LOAD",path)
local fn = CompileString(contents,path)
if type(fn) == "function" then
debug.setfenv(fn,getEnv())
-- local oFn = fn
-- fn = function(...)
-- return coroutine.wrap(oFn)(...)
-- end
end
return fn
end
local pathlookup = {}
local function compileFile(path)
local fn = compileFileInternal(cDir[#cDir]..path)
if not fn then
fn = compileFileInternal(path)
if not fn then
error(path.." not found!")
else
pathlookup[fn] = path
end
else
pathlookup[fn] = cDir[#cDir]..path
end
return fn
end
local function runFile(path,...)
local fn = compileFile(path,...)
-- print("RUN",path)
if type(fn) == "function" then
if pathlookup[fn] then path = pathlookup[fn] end
cDir[#cDir + 1] = path:match("^(.-/)[^/]+$") or ""
local errMsg
local ret = {xpcall(fn,function(err)
cDir[#cDir] = nil
errMsg = err
end,...)}
if not table.remove(ret,1) then error(errMsg) end
return unpack(ret)
else
error(fn)
end
end
getEnv = function()
return setmetatable({
include = runFile,
CompileFile = compileFile
},{
__index = _G,
__newindex = _G
})
end
local function runFolder(path)
local data = getDir(author,repo,path)
for i,fileData in ipairs(data) do
if fileData.type == "file" then
local contents = FetchSync(fileData.download_url)
-- print("RUN",fileData.path)
local fn = CompileString(contents,fileData.path)
if type(fn) == "function" then
debug.setfenv(fn,getEnv())
cDir[#cDir + 1] = fileData.path:match("^(.-/)[^/]+$") or ""
local errMsg
local suc = xpcall(fn,function(err)
cDir[#cDir] = nil
errMsg = err
end)
if not suc then error(errMsg) end
else
error(fn)
end
end
end
end
runFolder("lua/autorun/")
if CLIENT then
runFolder("lua/autorun/client/")
elseif SERVER then
runFolder("lua/autorun/server/")
end
for i,path in ipairs(runExtra or {}) do runFile(path) end
end
function includeRepo(...)
return coroutine.wrap(includeRepoInternal)(...)
end
local coroutine,debug,xpcall = me.wew'coroutine',me.wew'debug',me.wew'xpcall'
local function setfenv(fn, env)
if type(fn) ~= "function" then return print("WARN: non-function passed into setfenv()") end
local i = 1
while true do
local name = debug.getupvalue(fn, i)
if name == "_ENV" then
debug.upvaluejoin(fn, i, (function()
return env
end), 1)
break
elseif not name then
break
end
i = i + 1
end
return fn
end
local function FetchSync(url)
local this = coroutine.running()
http.Fetch(url,function(...)
local suc,err = coroutine.resume(this,...)
if not suc then error(err) end
end,function(...)
-- local suc,err = coroutine.resume(this,...)
-- if not suc then error(err) end
end)
return coroutine.yield()
end
local function getDir(author,repo,dir)
local _,c = FetchSync("https://api.github.com/repos/"..author.."/"..repo.."/contents/"..dir)
return json.decode(c)
end
local function getFile(author,repo,dir,branch)
local code,data = FetchSync("https://cdn.rawgit.com/"..author.."/"..repo.."/"..(branch or "master").."/"..dir)
return (code ~= 404 and data) or false
end
local function includeRepoInternal(author,repo)
local getEnv
local cDir = {""}
local function compileFileInternal(path,...)
path = "lua/"..path
local contents = getFile(author,repo,path)
if not contents then return false end
-- print("LOAD",path)
local fn = load(contents,path)
if type(fn) == "function" then
setfenv(fn,getEnv())
-- local oFn = fn
-- fn = function(...)
-- return coroutine.wrap(oFn)(...)
-- end
end
return fn
end
local pathlookup = {}
local function compileFile(path)
local fn = compileFileInternal(cDir[#cDir]..path)
if not fn then
fn = compileFileInternal(path)
if not fn then
print("WARN: "..path.." not found!")
else
pathlookup[fn] = path
end
else
pathlookup[fn] = cDir[#cDir]..path
end
return fn
end
local function runFile(path,...)
local fn = compileFile(path,...)
-- print("RUN",path)
if type(fn) == "function" then
if pathlookup[fn] then path = pathlookup[fn] end
cDir[#cDir + 1] = path:match("^(.-/)[^/]+$") or ""
local errMsg
local ret = {xpcall(fn,function(err)
cDir[#cDir] = nil
errMsg = err
end,...)}
if not table.remove(ret,1) then error(errMsg) end
return unpack(ret)
else
error(fn)
end
end
getEnv = function()
return setmetatable({
include = runFile,
CompileFile = compileFile,
setfenv = setfenv,
unpack = table.unpack,
coroutine = coroutine,
debug = debug,
file = {
Exists = function(path,type)
local thing = getFile(author,repo,"lua/"..path)
if thing then return true else return false end
end
}
},{
__index = _G,
__newindex = _G
})
end
local function runFolder(path)
local data = getDir(author,repo,path)
for i,fileData in ipairs(data) do
if fileData.type == "file" then
local _,contents = FetchSync(fileData.download_url)
-- print("RUN",fileData.path)
local fn = load(contents,fileData.path)
if type(fn) == "function" then
setfenv(fn,getEnv())
cDir[#cDir + 1] = fileData.path:match("^(.-/)[^/]+$") or ""
local errMsg
local suc = xpcall(coroutine.wrap(fn),function(err)
cDir[#cDir] = nil
errMsg = err
end)
if not suc then error(errMsg) end
else
error(fn)
end
end
end
end
local function init()
runFolder("lua/autorun/")
if CLIENT then
runFolder("lua/autorun/client/")
elseif SERVER then
runFolder("lua/autorun/server/")
end
end
return runFile,init
end
function includeRepo(...)
return coroutine.wrap(includeRepoInternal)(...)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment