Skip to content

Instantly share code, notes, and snippets.

@mrkskwsnck
Created September 29, 2017 10:08
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 mrkskwsnck/46b08dddfe7da376a22c317a343ee8d0 to your computer and use it in GitHub Desktop.
Save mrkskwsnck/46b08dddfe7da376a22c317a343ee8d0 to your computer and use it in GitHub Desktop.
Iterate over all user's GitHub repositories and update them locally
#!/usr/bin/env lua
--[[
Dependencies via Luarocks:
* luasocket
* luasec
* luajson
* luafilesystem
Environment variables to find locally installed rocks:
LUA_PATH_5_3="$HOME/.luarocks/share/lua/5.3/?.lua;;"
LUA_CPATH_5_3="$HOME/.luarocks/lib/lua/5.3/?.so;;"
--]]
----[[ CONFIGURATION
local userName = "GITHUB_USERNAME"
local accessToken = "GITHUB_ACCESS_TOKEN"
--]]
function updateRepo (r)
local success
local t = lfs.attributes(r.name)
if not t then
-- Directory does not exist
io.write(string.format("Cloning %s ...", r.name))
io.flush()
local gitCmd = string.format("git clone --quiet %s", r.ssh_url)
success = assert(os.execute(gitCmd))
else
-- Directory exists
io.write(string.format("Fetching %s ...", r.name))
io.flush()
local cwd = lfs.currentdir()
lfs.chdir(r.name)
local gitCmd = "git fetch --all --quiet"
success = assert(os.execute(gitCmd))
lfs.chdir(cwd)
end
if success then
io.write(" done.\n")
else
io.write(" failed!\n")
end
end
-- GET REPOSITORIES AND CREATE TASKS
function getRepos (userName, accessToken)
local reposUri = "https://api.github.com/users/" .. userName .. "/repos"
local responseTable = {}
local body, code = assert(https.request {
url = reposUri,
headers = {
["Authorization"] = "token " .. accessToken
},
sink = ltn12.sink.table(responseTable)
})
-- Exiting upon GET failure
if code ~= 200 then
io.stderr:write(string.format("Service returned HTTP status code %i\n", code))
os.exit(false)
end
local t = json.decode(table.concat(responseTable))
-- Create task for each repository
for _, v in pairs(t) do
table.insert(tasks, coroutine.create(function () updateRepo(v) end))
end
end
-- DISPATCH TASKS AND UPDATE REPOSITORIES
function dispatch ()
local i = 1
while true do
-- Pre-check of tasks iterator
if tasks[i] == nil then
if tasks[1] == nil then
break
else
i = 1 -- Restart loop
end
end
local res = assert(coroutine.resume(tasks[i]))
if not res or coroutine.status(tasks[i]) == "dead" then -- Task ended
table.remove(tasks, i)
else
-- Goto next iteration
i = i + 1
end
end
end
-- Main
https = require("ssl.https")
local json = require("json")
local lfs = require("lfs")
tasks = {} -- Consist of coroutines per repository
getRepos(userName, accessToken)
io.write(string.format("Updating repositories in: '%s'\n", lfs.currentdir()))
dispatch()
-- End of Main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment