Mirosta

CC Github

Nov 26th, 2020 (edited)
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.38 KB | None | 0 0
  1. require("json")
  2.  
  3. github = {baseApiUrl = "https://api.github.com/repos", baseRawDataUrl = "https://raw.githubusercontent.com"}
  4.  
  5. github.writeState = function(owner, repoName, branchName, commitId)
  6.     assert(branchName ~= nil, "Branch name must not be nil")
  7.     local state = {owner=owner, repoName=repoName, branchName=branchName, commitId=commitId}
  8.     local f = io.open(string.format("%s/.checkout", repoName), "w")
  9.     f:write(textutils.serialize(state))
  10.     f:flush()
  11.     f:close()
  12. end
  13.  
  14. github.loadState = function()
  15.     local f = io.open(shell.dir() .. "/.checkout")
  16.     if (f == nil) then
  17.         print("WARNING: Unable to find state file .checkout")
  18.         return
  19.     end
  20.     local state = textutils.unserialize(f:read("*a") or "")
  21.     f:close()
  22.     if (not state) then
  23.         return
  24.     end
  25.     return state.owner, state.repoName, state.branchName, state.commitId
  26. end
  27.  
  28. github.checkoutRepo = function(owner, repoName, branchName)
  29.     print (string.format("Checking out into directory %s", repoName))
  30.     assert(owner ~= nil and repoName ~= nil, "owner and repoName must not be nil")
  31.     if (branchName == nil) then
  32.         repoData = github.getRepo(owner, repoName)
  33.         branchName = repoData.default_branch
  34.     end
  35.     branchData = github.getBranch(owner, repoName, branchName)
  36.     treeData = github.getTreeForBranch(branchData, true)
  37.     github.checkoutTree(owner, repoName, branchName, treeData)
  38.     github.writeState(owner, repoName, branchName, branchData.commit.sha)
  39. end
  40.  
  41. github.updateRepo = function()
  42.     local owner, repoName, branchName, baseCommitId = github.loadState()
  43.     assert(owner ~= nil, "Owner is nil, current directory probably not a github clone")
  44.     assert(repoName ~= nil, "repoName is nil, current directory probably not a github clone")
  45.     assert(branchName ~= nil, "branchName is nil, current directory probably not a github clone")
  46.     assert(baseCommitId ~= nil, "baseCommitId is nil, current directory probably not a github clone")
  47.  
  48.     local branchData = github.getBranch(owner, repoName, branchName)
  49.     local headCommitId = branchData.commit.sha
  50.     if (headCommitId == baseCommitId) then
  51.         print("Already up to date")
  52.         return
  53.     end
  54.     local compareData = github.compareCommits(owner, repoName, baseCommitId, headCommitId)
  55.     for _, file in ipairs(compareData.files) do
  56.         github.checkoutFileForUrl(file.raw_url, ".", file.filename)
  57.     end
  58.     github.writeState(owner, repoName, branchName, headCommitId)
  59. end
  60.  
  61. github.getRepo = function(owner, repoName)
  62.     return json.parse(http.get(string.format("%s/%s/%s", github.baseApiUrl, owner, repoName)).readAll())
  63. end
  64.  
  65. github.getBranch = function(owner, repoName, branchName)
  66.     return json.parse(http.get(string.format("%s/%s/%s/branches/%s", github.baseApiUrl, owner, repoName, branchName)).readAll())
  67. end
  68.  
  69. github.getTreeForBranch = function(branchData, recursive)
  70.     treeUrl = string.format("%s?recursive=%s", branchData.commit.commit.tree.url, tostring(recursive == true))
  71.     return json.parse(http.get(treeUrl).readAll())
  72. end
  73.  
  74. github.compareCommits = function(owner, repoName, baseCommitId, headCommitId)
  75.     return json.parse(http.get(string.format("%s/%s/%s/compare/%s...%s", github.baseApiUrl, owner, repoName, baseCommitId, headCommitId)).readAll())
  76. end
  77.  
  78. github.checkoutTree = function(owner, repoName, branchName, treeData)
  79.     for i, item in pairs(treeData.tree) do
  80.         if (item.type == "tree") then
  81.             fs.makeDir(string.format("%s/%s", repoName, item.path))
  82.         elseif (item.type == "blob") then
  83.             github.checkoutFile(owner, repoName, branchName, item.path)
  84.         else
  85.             assert(false, string.format("Unsupported item type %s", item.type))
  86.         end
  87.     end
  88. end
  89.  
  90. github.checkoutFile = function(owner, repoName, branchName, path)
  91.     fileUrl = string.format("\"%s/%s/%s/%s/%s\"", github.baseRawDataUrl, owner, repoName, branchName, http.encodeUrlPart(path))
  92.     github.checkoutFileForUrl(fileUrl, repoName, path)
  93. end
  94.  
  95. github.checkoutFileForUrl = function(fileUrl, directoryName, path)
  96.     localFilePath = string.format("/%s/%s/%s", shell.dir(), directoryName, path)
  97.     local directoryName = fs.getDir(localFilePath)
  98.     if (fs.exists(localFilePath)) then
  99.         fs.delete(localFilePath)
  100.     elseif (not fs.exists(directoryName)) then
  101.         fs.makeDir(directoryName)
  102.     end
  103.     shell.run("wget", fileUrl, string.format("\"%s\"", localFilePath))
  104. end
  105.  
  106. http.encodeUrlPart = function(url)
  107.     local encodeOne = function(chr)
  108.         return string.format("%%%02X", string.byte(chr, 1))
  109.     end
  110.     return string.gsub(url, "[ <>#%%{}|\\^~]", encodeOne)
  111. end
  112.  
  113. local isScript = function ()
  114.     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])))
  115. end
  116.  
  117.  
  118. if (isScript()) then
  119.     local usage = function()
  120.         print("Expected usage:")
  121.         print("  github clone <owner> <repo> [branch]")
  122.         print("  github update")
  123.         print("  E.g. github clone DataDink ComputerCraft - Checks out DataDink's ComputerCraft repo into a folder called ComputerCraft")
  124.         print("       github update - Checks out updated files in current directory")
  125.     end
  126.  
  127.     local owner, repo, branch = nil, nil, nil
  128.  
  129.     if (#arg < 1) then
  130.         usage()
  131.         return
  132.     end
  133.     local method = table.remove(arg, 1)
  134.     if (method == "clone") then
  135.         if (#arg < 2) then
  136.             usage()
  137.             return
  138.         end
  139.         if (#arg >= 2) then
  140.             owner = arg[1]
  141.             repo = arg[2]
  142.         end
  143.         if (#arg >= 3) then
  144.             branch = arg[3]
  145.         end
  146.         github.checkoutRepo(owner, repo, branch)
  147.     elseif (method == "update") then
  148.         github.updateRepo()
  149.     else
  150.         usage()
  151.         return
  152.     end
  153. end
  154.  
Advertisement
Add Comment
Please, Sign In to add comment