Guest User

github downloader

a guest
May 25th, 2019
15
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.28 KB | None | 0 0
  1. local internet=require("internet")
  2. local text=require("text")
  3. local filesystem=require("filesystem")
  4. local unicode=require("unicode")
  5. local term=require("term")
  6. local event=require("event")
  7. local keyboard=require("keyboard")
  8.  
  9.  
  10. local repo,target
  11.  
  12. local args={...}
  13.  
  14. if #args<1 or #args>2 then
  15. print("Usage: gitrepo <repo> [<targetdir>]]\nrepo should be the owner/repo, ex, \"OpenPrograms/Gopher-Programs\"\ntargetdir is an optional local path to download to, default will be /tmp/<repo>/")
  16. return
  17. end
  18.  
  19. repo=args[1]
  20. if not repo:match("^[%w-.]*/[%w-.]*$") then
  21. print('"'..args[1]..'" does not look like a valid repo identifier.\nShould be <owner>/<reponame>')
  22. return
  23. end
  24.  
  25. target=args[2]
  26. target=target and ("/"..target:match("^/?(.-)/?$").."/") or "/tmp/"..repo
  27. if filesystem.exists(target) then
  28. if not filesystem.isDirectory(target) then
  29. print("target directory already exists and is not a directory.")
  30. return
  31. end
  32. if filesystem.get(target).isReadOnly() then
  33. print("target directory is read-only.")
  34. return
  35. end
  36. else
  37. if not filesystem.makeDirectory(target) then
  38. print("target directory is read-only")
  39. return
  40. end
  41. end
  42.  
  43.  
  44.  
  45. -- this isn't acually used, but it is tested and works on decoding the base64 encoded data that github
  46. --sends for some queries, leaving it in here for possible future/related use, might be able to pull
  47. --and display difs and things like that?
  48. local symb="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  49.  
  50. function decode64(text)
  51. local val,bits=0,0
  52. local output=""
  53. for ch in text:gmatch(".") do
  54. if symb:find(ch) then
  55. --print("ch "..ch.."-> "..(symb:find(ch)-1))
  56. val=bit32.lshift(val,6)+symb:find(ch)-1
  57. else
  58. print(ch.."?")
  59. return
  60. end
  61. bits=bits+6
  62. --print("bits : "..bits)
  63. --print(string.format("val : 0x%04x",val))
  64. if bits>=8 then
  65. local och=unicode.char(bit32.rshift(val,bits-8))
  66. --print("os<<"..och)
  67. --print("& with "..(2^(bits-8)-1))
  68. val=bit32.band(val,2^(bits-8)-1)
  69. bits=bits-8
  70. --print(string.format("val : 0x%04x",val))
  71. output=output..och
  72. end
  73. end
  74. return output
  75. end
  76.  
  77.  
  78.  
  79. local function gitContents(repo,dir)
  80. print("fetching contents for "..repo..dir)
  81. local url="https://api.github.com/repos/"..repo.."/contents"..dir
  82. local result,response=pcall(internet.request,url)
  83. local raw=""
  84. local files={}
  85. local directories={}
  86.  
  87. if result then
  88. for chunk in response do
  89. raw=raw..chunk
  90. end
  91. else
  92. error("you've been cut off. Serves you right.")
  93. end
  94.  
  95. response=nil
  96. raw=raw:gsub("%[","{"):gsub("%]","}"):gsub("(\".-\"):(.-[,{}])",function(a,b) return "["..a.."]="..b end)
  97. local t=load("return "..raw)()
  98.  
  99. for i=1,#t do
  100. if t[i].type=="dir" then
  101. table.insert(directories,dir.."/"..t[i].name)
  102.  
  103. local subfiles,subdirs=gitContents(repo,dir.."/"..t[i].name)
  104. for i=1,#subfiles do
  105. table.insert(files,subfiles[i])
  106. end
  107. for i=1,#subdirs do
  108. table.insert(directories,subdirs[i])
  109. end
  110. else
  111. files[#files+1]=dir.."/"..t[i].name
  112. end
  113. end
  114.  
  115. return files, directories
  116. end
  117.  
  118. local files,dirs=gitContents(repo,"")
  119.  
  120. for i=1,#dirs do
  121. print("making dir "..target..dirs[i])
  122. if filesystem.exists(target..dirs[i]) then
  123. if not filesystem.isDirectory(target..dirs[i]) then
  124. print("error: directory "..target..dirs[i].." blocked by file with the same name")
  125. return
  126. end
  127. else
  128. filesystem.makeDirectory(target..dirs[i])
  129. end
  130. end
  131.  
  132. local replaceMode="ask"
  133. for i=1,#files do
  134. local replace=nil
  135. if filesystem.exists(target..files[i]) then
  136. if filesystem.isDirectory(target..files[i]) then
  137. print("Error: file "..target..files[i].." blocked by directory with same name!")
  138. return
  139. end
  140. if replaceMode=="always" then
  141. replace=true
  142. elseif replaceMode=="never" then
  143. replace=false
  144. else
  145. print("\nFile "..target..files[i].." already exists.\nReplace with new version?")
  146. local response=""
  147. while replace==nil do
  148. term.write("yes,no,always,skip all[ynAS]: ")
  149. local char
  150. repeat
  151. _,_,char=event.pull("key_down")
  152. until not keyboard.isControl(char)
  153. char=unicode.char(char)
  154. print(char)
  155. if char=="A" then
  156. replaceMode="always"
  157. replace=true
  158. char="y"
  159. elseif char=="S" then
  160. replaceMode="never"
  161. replace=false
  162. char="n"
  163. elseif char:lower()=="y" then
  164. replace=true
  165. elseif char:lower()=="n" then
  166. replace=false
  167. else
  168. print("invalid response.")
  169. end
  170. end
  171. end
  172. if replace then
  173. filesystem.remove(target..files[i])
  174. end
  175. end
  176. if replace~=false then
  177. print("downloading "..files[i])
  178. local url="https://raw.github.com/"..repo.."/master"..files[i]
  179. local result,response=pcall(internet.request,url)
  180. if result then
  181. local raw=""
  182. for chunk in response do
  183. raw=raw..chunk
  184. end
  185. print("writing to "..target..files[i])
  186. local file=io.open(target..files[i],"w")
  187. file:write(raw)
  188. file:close()
  189.  
  190. else
  191. print("failed, skipping")
  192. end
  193. end
  194. end
Add Comment
Please, Sign In to add comment