Advertisement
gridcaster

github2

Jun 5th, 2021
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.81 KB | None | 0 0
  1. local github = dofile("apis/github")
  2.  
  3. local selectedAction = select(1, ...)
  4. local passed = { select(2, ...) }
  5.  
  6. local subcommands = {
  7. clone = {
  8. usage = "github clone <user>/<repo> [-b <branchname> | -t <tagname>] [<destination>] [-a <username>]",
  9. flags = {
  10. ['-b'] = 'branch',
  11. ['--branch'] = 'branch',
  12. ['-t'] = 'tag',
  13. ['--tag'] = 'tag',
  14. ['-a'] = 'authed',
  15. ['-auth'] = 'authed'
  16. }
  17. },
  18. auth = {
  19. usage = "github auth <user> [<api token> | -d ]",
  20. flags = {
  21. ['-d'] = 'delete',
  22. ['--delete'] = 'delete'
  23. }
  24. }
  25. }
  26.  
  27. local action = subcommands[selectedAction]
  28. if not action then
  29. for k, v in pairs(subcommands) do
  30. print(v.usage)
  31. print(" ")
  32. end
  33. return
  34. end
  35.  
  36. -- make a bar of the form "[====> ] 50%"
  37. function progressbar(f)
  38. local left = "["
  39. local right = ("]%3d%%"):format(f * 100)
  40.  
  41. local gap = select(1, term.getSize()) - #left - #right
  42. local at = math.floor(f * (gap + 1))
  43. for i = 1, gap do
  44. left = left .. (
  45. i < at and "=" or
  46. i > at and " " or
  47. ">"
  48. )
  49. end
  50. return left .. right
  51. end
  52.  
  53. -- get flag arguments
  54. local function findFlag(arg)
  55. if arg.sub(1,1) == '-' then
  56. if not action.flags[arg] then
  57. return printError(('Unknown flag argument %s'):format(arg))
  58. end
  59. end
  60. return action.flags[arg]
  61. end
  62.  
  63. local args = {}
  64. local flags = {}
  65. local lastFlagged = 0
  66. for k, arg in pairs(passed) do
  67. if k ~= lastFlagged then
  68. local flagName = findFlag(arg)
  69. if flagName then
  70. flags[flagName] = passed[k + 1] or true
  71. lastFlagged = k + 1 or true
  72. else
  73. table.insert(args, arg)
  74. end
  75. end
  76. end
  77.  
  78. if flags.branch and flags.tag then
  79. return printError('--branch and --tag cannot both be specified')
  80. end
  81.  
  82.  
  83. local function hasEnoughSpace(repoSize, freeSpace)
  84. -- The value reported by github underestimates the one reported by CC. This tries
  85. -- to guess when this matters.
  86. local sizeError = 0.2
  87.  
  88. local function warnAndContinue()
  89. write("Repository may be too large to download, attempt anyway? [Y/n]: ")
  90. local validAnswers = { [''] = 'yes', y = 'yes', yes = 'yes', n = 'no', no = 'no' }
  91. local input = io.read()
  92. while not validAnswers[input:lower()] do
  93. print("Please type [y]es or [n]o")
  94. input = io.read()
  95. end
  96. return validAnswers[input:lower()] == 'yes'
  97. end
  98.  
  99. if repoSize > freeSpace then
  100. return false
  101. elseif repoSize * (1 + sizeError) > freeSpace then
  102. return warnAndContinue()
  103. else
  104. return true
  105. end
  106. end
  107.  
  108. local function sizeStr(bytes)
  109. local unit = 1024
  110. if bytes < unit then
  111. return ("%s byte(s)"):format(bytes)
  112. else
  113. local multi = 10^(1)
  114. local KiB = math.floor((bytes/unit) * multi + 0.5) / multi
  115. return ("%s KiB"):format(KiB)
  116. end
  117. end
  118.  
  119. if action == subcommands.clone then
  120. -- parse input
  121. local repo, dest = args[1], args[2]
  122. local treeName = flags.branch or flags.tag or 'master'
  123.  
  124. if not repo then return printError("No repo specified") end
  125.  
  126. user, repo = repo:match('^(.-)/(.+)$')
  127. if not (user and repo) then return printError("Invalid repo name - should be user/repo") end
  128.  
  129. dest = shell.resolve(dest or repo)
  130.  
  131. local auth = nil
  132.  
  133. if flags.authed then
  134. -- if no user is found auth should remain nil.
  135. auth = github.Auth.get(flags.authed)
  136. end
  137.  
  138. if flags.authed and not auth then
  139. return printError("Unknown user! Add one with 'git auth'")
  140. elseif flags.authed and not auth:checkToken() then
  141. return printError("Invalid Token!")
  142. end
  143.  
  144. -- get file listings
  145. local repo = github.repo(user, repo, auth)
  146. print("Discovering files...")
  147. local tree = repo:tree(treeName)
  148.  
  149. -- download the files
  150. local totalSize = tree.size
  151. local freeSpace = fs.getFreeSpace(dest)
  152.  
  153. if not hasEnoughSpace(totalSize, freeSpace) then
  154. local errStr = "Repository is %s, but only %s are free on this computer. Aborting!"
  155. errStr = errStr:format(sizeStr(totalSize), sizeStr(freeSpace))
  156. return printError(errStr)
  157. end
  158.  
  159. print("Downloading:")
  160. local size = 0
  161. tree:cloneTo(dest, function(item)
  162. -- called every time a download completes
  163. if getmetatable(item) == github.Blob then
  164. size = size + item.size
  165. term.clearLine()
  166. print(" "..item:fullPath())
  167. term.write(progressbar(size/totalSize))
  168. term.setCursorPos(1, select(2, term.getCursorPos()))
  169. end
  170. end)
  171. term.scroll(1)
  172. return
  173. end
  174.  
  175. if action == subcommands.auth then
  176. local user, token = args[1], args[2]
  177. if not user then return printError("No user specified.") end
  178.  
  179. if flags.delete then
  180. github.Auth.delete(user)
  181. print(('Deleted github token for user %s'):format(user))
  182. else
  183. if not token then return printError("No token specified.") end
  184. local auth = github.Auth.new('oauth', user, token)
  185. if auth:checkToken() then
  186. auth:save()
  187. print(('Saved github token for user %s'):format(auth.user))
  188. else
  189. return printError("Invalid token!")
  190. end
  191. end
  192.  
  193. return
  194. end
  195.  
  196. print(action.usage)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement