Posted 09 July 2013 - 12:51 AM
After deciding to use GitHub for a project that a few other members and I are working on, I thought it might actually be a good idea to learn how to use GitHub :P/>. I read through a couple of tutorials online and learned how to use it without too much frustration and soon noticed that I needed the ability to test the code we were writing. Unfortunately, I couldn't have my repository in the world/saves/computer/x folder and therefore needed some other method of downloading all of the files for testing.
This task of downloading files for testing from the repository was easy to do by hand at first, but as the size of the repository began to grow, the need for some kind of automated tool became blatantly necessary…
And so, I sat down for about an hour and a half and pumped out this API.
Using this API, you can map a GitHub repository into a table whose entries look like this:
The two functions that are available to you in this API are:
and
All of the code given is free to use and modify as long as credit is given where credit is due :)/>.
Code:
Pastebin link.
This task of downloading files for testing from the repository was easy to do by hand at first, but as the size of the repository began to grow, the need for some kind of automated tool became blatantly necessary…
And so, I sat down for about an hour and a half and pumped out this API.
Using this API, you can map a GitHub repository into a table whose entries look like this:
local repository = {
branch = { ... },
fileName = fileName,
...
}
Once you have one of these handy-dandy repository tables, you can sift through the entries and programmatically download any and all files you need for your project to work in-game ;)/>.The two functions that are available to you in this API are:
getRepository (author, repository, branch)
Returns a repository as a table in the format described above. The parameters for this function are the components that the url will need when communicating with GitHub to map the repository.and
printRepository (repository, sleepTime)
Prints the repository given in a format where you can see the trees within the repository. The sleepTime parameters just designates how much time, if any, the function should wait before printing the next item.All of the code given is free to use and modify as long as credit is given where credit is due :)/>.
Code:
Spoiler
--[[
Git API Trystan Cannon
8 June 2013
Contains a slew of local functions and two global functions
for mapping GitHub repositories into tables. Using these
tables, one could browse a GitHub repository or recursively
download an entire repository as a project. This is useful
for those who develop using GitHub rather than uploading
several files to pastebin and creating an installer script.
The global functions which are useable outside of this file are:
- getRepository (author, repository, branch)
* Returns a table mapping of the repository with the given URL components.
* NOTE: The repository represented by the given URL components must be a valid repository on GitHub.
* NOTE: Repository table mappings have entries as follows: t[name] = fileName or branchTable
- printRepository (repository, sleepTime)
* Recursively prints out a repository and shows the different branches of the given repostory.
* NOTE: The repository table given can be any table; the function simply recursively prints out a table's contents.
]]
-- Variables ----------------------------------------------------
local httpBase = "https://github.com/"
local httpFileBase = "https://raw.github.com/"
-- Variables ----------------------------------------------------
-- Encodes the given string to work with the GitHub urls. Basically, all spaces
-- are replaced with %20.
local function urlEncode (_string)
return string.gsub (_string, "%s", "%%20")
end
-- Compiles the given url components into one which will allow for the downloading
-- of the file in the designated repository.
local function compileFileUrl (author, repository, branch, path)
author = urlEncode (author)
repository = urlEncode (repository)
path = urlEncode (path)
return httpFileBase .. author .. '/' .. repository .. '/' .. branch .. '/' .. path
end
-- Compiles the given url components into one which will allow for the downloading
-- of the url page for the given tree in a repository.
local function compileTreeUrl (author, repository, branch, treePath)
author = urlEncode (author)
repository = urlEncode (repository)
treePath = urlEncode (treePath or "")
return httpBase .. author .. '/' .. repository .. "/tree/" .. branch .. '/' .. treePath
end
-- Requests a page and returns all relevant event data.
local function requestPage (url)
local success, _error = pcall (http.request, url)
if success then
local event, url, page = nil
repeat
event, url, page = os.pullEvent()
until event == "http_success" or event == "http_failure"
local pageContents = nil
if event == "http_success" then
pageContents = page.readAll()
page.close()
end
return event == "http_success", url, pageContents
end
return false
end
-- Returns every file or folder/tree contained within in a folder/tree. This is not done recursively,
-- so it is only surface level.
local function parseTreePage (page)
local contents = {}
local pattern = '<td class="content">\n%s*<a href="(.-)"'
for match in string.gmatch (page, pattern) do
contents[#contents + 1] = string.gsub (match, "%%20", " ")
end
return contents
end
-- Takes a table of items in a tree in the repository and removes all extraneous text. This leaves
-- all items in the table just as their paths in the branch.
local function trimItemsInTree (itemsInTree, branch)
for index = 1, #itemsInTree do
itemsInTree[index] = itemsInTree[index]:match (branch .. "/(.+)")
end
end
-- Returns all of the items in a given tree.
local function getItemsInTree (author, repository, branch, treePath)
local success, url, pageContents = requestPage (compileTreeUrl (author, repository, branch, treePath))
if success then
local items = parseTreePage (pageContents)
trimItemsInTree (items, branch)
return items
end
return {}
end
-- Checks if the given path is a tree or not.
-- NOTE: The given path must be a valid path in the repository.
local function isPathTree (author, repository, branch, path)
local _, _, pageContents = requestPage (compileTreeUrl (author, repository, branch, path))
return #parseTreePage (pageContents) ~= 0
end
-- Compiles the given url components into one which will allow for downloading
-- of a raw file from github.
local function compileFileUrl (author, repository, branch, filePath)
author = urlEncode (author)
repository = urlEncode (repository)
filePath = urlEncode (filePath)
return httpFileBase .. author .. '/' .. repository .. '/' .. branch .. '/' .. filePath
end
-- Returns the contents of the file at the path designated by the given url components in the repository.
local function getFileContents (author, repository, branch, path)
local success, url, pageContents = requestPage (compileFileUrl (author, repository, branch, path))
if success then
return pageContents
end
end
-- Returns a table of all of the items in the given repository.
-- When calling this from another script, use "" as the path.
function getRepository (author, repository, branch, path, map)
path = path or ""
local map = map or {}
if isPathTree (author, repository, branch, path) then
map[fs.getName (path)] = {}
local itemsInTree = getItemsInTree (author, repository, branch, path)
for _, itemPath in pairs (itemsInTree) do
getRepository (author, repository, branch, itemPath, map[fs.getName (path)])
end
else
map[fs.getName (path)] = fs.getName (path)
end
return map
end
-- Prints out the given repository table recursively with the designated number of seconds to sleep between each print.
function printRepository (repository, sleepTime, indent)
indent = indent or ""
for name, item in pairs (repository) do
sleep (sleepTime or 0)
print (indent .. name)
if type (item) == "table" then
printRepository (item, sleepTime, indent .. ' ')
end
end
end