This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Grim Reaper's profile picture

GitHub Repository Mapper

Started by Grim Reaper, 08 July 2013 - 10:51 PM
Grim Reaper #1
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:

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
Pastebin link.
Galactica4 #2
Posted 14 July 2013 - 02:03 AM
Quite usefull, yes quite very usefull
Zudo #3
Posted 14 July 2013 - 02:06 AM
This looks good!