Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require("json")
- github = {baseApiUrl = "https://api.github.com/repos", baseRawDataUrl = "https://raw.githubusercontent.com"}
- github.writeState = function(owner, repoName, branchName, commitId)
- assert(branchName ~= nil, "Branch name must not be nil")
- local state = {owner=owner, repoName=repoName, branchName=branchName, commitId=commitId}
- local f = io.open(string.format("%s/.checkout", repoName), "w")
- f:write(textutils.serialize(state))
- f:flush()
- f:close()
- end
- github.loadState = function()
- local f = io.open(shell.dir() .. "/.checkout")
- if (f == nil) then
- print("WARNING: Unable to find state file .checkout")
- return
- end
- local state = textutils.unserialize(f:read("*a") or "")
- f:close()
- if (not state) then
- return
- end
- return state.owner, state.repoName, state.branchName, state.commitId
- end
- github.checkoutRepo = function(owner, repoName, branchName)
- print (string.format("Checking out into directory %s", repoName))
- assert(owner ~= nil and repoName ~= nil, "owner and repoName must not be nil")
- if (branchName == nil) then
- repoData = github.getRepo(owner, repoName)
- branchName = repoData.default_branch
- end
- branchData = github.getBranch(owner, repoName, branchName)
- treeData = github.getTreeForBranch(branchData, true)
- github.checkoutTree(owner, repoName, branchName, treeData)
- github.writeState(owner, repoName, branchName, branchData.commit.sha)
- end
- github.updateRepo = function()
- local owner, repoName, branchName, baseCommitId = github.loadState()
- assert(owner ~= nil, "Owner is nil, current directory probably not a github clone")
- assert(repoName ~= nil, "repoName is nil, current directory probably not a github clone")
- assert(branchName ~= nil, "branchName is nil, current directory probably not a github clone")
- assert(baseCommitId ~= nil, "baseCommitId is nil, current directory probably not a github clone")
- local branchData = github.getBranch(owner, repoName, branchName)
- local headCommitId = branchData.commit.sha
- if (headCommitId == baseCommitId) then
- print("Already up to date")
- return
- end
- local compareData = github.compareCommits(owner, repoName, baseCommitId, headCommitId)
- for _, file in ipairs(compareData.files) do
- github.checkoutFileForUrl(file.raw_url, ".", file.filename)
- end
- github.writeState(owner, repoName, branchName, headCommitId)
- end
- github.getRepo = function(owner, repoName)
- return json.parse(http.get(string.format("%s/%s/%s", github.baseApiUrl, owner, repoName)).readAll())
- end
- github.getBranch = function(owner, repoName, branchName)
- return json.parse(http.get(string.format("%s/%s/%s/branches/%s", github.baseApiUrl, owner, repoName, branchName)).readAll())
- end
- github.getTreeForBranch = function(branchData, recursive)
- treeUrl = string.format("%s?recursive=%s", branchData.commit.commit.tree.url, tostring(recursive == true))
- return json.parse(http.get(treeUrl).readAll())
- end
- github.compareCommits = function(owner, repoName, baseCommitId, headCommitId)
- return json.parse(http.get(string.format("%s/%s/%s/compare/%s...%s", github.baseApiUrl, owner, repoName, baseCommitId, headCommitId)).readAll())
- end
- github.checkoutTree = function(owner, repoName, branchName, treeData)
- for i, item in pairs(treeData.tree) do
- if (item.type == "tree") then
- fs.makeDir(string.format("%s/%s", repoName, item.path))
- elseif (item.type == "blob") then
- github.checkoutFile(owner, repoName, branchName, item.path)
- else
- assert(false, string.format("Unsupported item type %s", item.type))
- end
- end
- end
- github.checkoutFile = function(owner, repoName, branchName, path)
- fileUrl = string.format("\"%s/%s/%s/%s/%s\"", github.baseRawDataUrl, owner, repoName, branchName, http.encodeUrlPart(path))
- github.checkoutFileForUrl(fileUrl, repoName, path)
- end
- github.checkoutFileForUrl = function(fileUrl, directoryName, path)
- localFilePath = string.format("/%s/%s/%s", shell.dir(), directoryName, path)
- local directoryName = fs.getDir(localFilePath)
- if (fs.exists(localFilePath)) then
- fs.delete(localFilePath)
- elseif (not fs.exists(directoryName)) then
- fs.makeDir(directoryName)
- end
- shell.run("wget", fileUrl, string.format("\"%s\"", localFilePath))
- end
- http.encodeUrlPart = function(url)
- local encodeOne = function(chr)
- return string.format("%%%02X", string.byte(chr, 1))
- end
- return string.gsub(url, "[ <>#%%{}|\\^~]", encodeOne)
- end
- local isScript = function ()
- return string.find(arg[0], "github") or (debug and (debug.getinfo(1).short_src == arg[0] or debug.getinfo(1).short_src == string.format("%s.lua", arg[0])))
- end
- if (isScript()) then
- local usage = function()
- print("Expected usage:")
- print(" github clone <owner> <repo> [branch]")
- print(" github update")
- print(" E.g. github clone DataDink ComputerCraft - Checks out DataDink's ComputerCraft repo into a folder called ComputerCraft")
- print(" github update - Checks out updated files in current directory")
- end
- local owner, repo, branch = nil, nil, nil
- if (#arg < 1) then
- usage()
- return
- end
- local method = table.remove(arg, 1)
- if (method == "clone") then
- if (#arg < 2) then
- usage()
- return
- end
- if (#arg >= 2) then
- owner = arg[1]
- repo = arg[2]
- end
- if (#arg >= 3) then
- branch = arg[3]
- end
- github.checkoutRepo(owner, repo, branch)
- elseif (method == "update") then
- github.updateRepo()
- else
- usage()
- return
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment