Xylem_Gaming

GitDown

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