LUAdev

Updater

Apr 29th, 2014
337
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.42 KB | None | 0 0
  1. -- Argument documentation:
  2. -- Note, everything automatically gets added to the list of auto updating
  3. -- Include a -m hook anywhere in the arguments, preferrably on the end of the original argument. This hook will make sure it only downloads it and places it in said file/folder
  4.  
  5. -- updater git <user/repo> <branch> <folder>
  6. -- Example: updater git EngineerCoding/Miscellaneous-Lua-Projects master /.MiscLuaProjects
  7.  
  8. -- updater gitfile <user/repo/file> <branch> <file>
  9. -- Example: updater gitfile EngineerCoding/Miscellaneous-Lua-Projects/primes.lua master /primeGenerator
  10.  
  11. -- updater pastebin <code> <file>
  12. -- Example: updater pastebin ee8xhTUK updater ( the updater is added by default :) )
  13.  
  14. --[[ The .update file structure:
  15. [pastebin]
  16. code file
  17. [git]
  18. user/repo branch folder
  19. [gitfile]
  20. user/repo/file branch file
  21. --]]
  22.  
  23. local tArgs = { ... }
  24.  
  25. if not http then
  26.     error( "HTTP must be enabled in the config!", 0 )
  27. end
  28.  
  29. -- Util functions
  30. local function loadJSON( sJSON )
  31.     if type( sJSON ) ~= "string" then
  32.         error( "String expected, got " .. type( sJSON ), 2 )
  33.     end
  34.    
  35.     sJSON = sJSON:gsub( "\"(%a+)\":%s*", "%1 = " )
  36.     sJSON = sJSON:gsub( "%[", "{" )
  37.     sJSON = sJSON:gsub( "%]", "}" )
  38.     -- Load the table
  39.     local func, err = loadstring( "return " .. sJSON, "JSON" )
  40.     if func then
  41.         local tJSON = func()
  42.         if type( tJSON ) == "table" and not tJSON.message then
  43.             return tJSON
  44.         end
  45.     end
  46.     error( "sJSON wasn't a JSON file", 2 )
  47. end
  48.  
  49. local function httpWrapper( sUrl )
  50.     if type( sUrl ) ~= "string" then
  51.         error( "String expected, got " .. type( sUrl ), 2 )
  52.     end
  53.    
  54.     for i = 1, 3 do
  55.         http.request( sUrl )
  56.         while true do
  57.             local e = { os.pullEvent() }
  58.             if e[ 1 ] == "http_success" then
  59.                 return e[ 3 ], e[ 2 ]
  60.             elseif e[ 1 ] == "http_failure" then
  61.                 break
  62.             end
  63.         end
  64.     end
  65. end
  66.  
  67. -- All objects
  68. local parseObjects = {
  69.     git = {
  70.         params = 4,
  71.         pattern = "^git%s(.-)/(.-)%s(.-)%s(.-)$",
  72.         pattern_file = "%1/%2 %3 %4",
  73.         pattern_func = function( sUser, sProject, sBranch, sFolder )
  74.             -- Get the file tree
  75.             local httpHandle = httpWrapper( string.format( "https://api.github.com/repos/%s/%s/git/trees/%s?recursive=1", sUser, sProject, sBranch ) )
  76.             if httpHandle then
  77.                 local sContent = httpHandle.readAll()
  78.                 httpHandle.close()
  79.                
  80.                 local parsedJSON = loadJSON( sContent )
  81.                 if parsedJSON then
  82.                     -- Download the necessary files
  83.                     local files = {}
  84.                     for _, treeObject in next, parsedJSON.tree do
  85.                         if treeObject.type == "blob" then                      
  86.                             local file_httpHandle = httpWrapper( string.format( "https://raw.github.com/%s/%s/%s/%s", sUser, sProject, sBranch, treeObject.path:gsub( "[%s]", "%%20" ) ) )
  87.                             if file_httpHandle then
  88.                                 files[ treeObject.path ] = file_httpHandle.readAll()
  89.                                 file_httpHandle.close()
  90.                             else
  91.                                 print( "Couldn't download all necessary files for the repo, no files changed!" )
  92.                                 return
  93.                             end
  94.                         end
  95.                     end
  96.                    
  97.                     if fs.exists( sFolder ) then
  98.                         fs.delete( sFolder )
  99.                     end
  100.                    
  101.                     -- Create all directories
  102.                     for index, treeObject in next, parsedJSON.tree do
  103.                         if treeObject.type == "tree" then
  104.                             fs.makeDir( fs.combine( sFolder, treeObject.path ) )
  105.                         end
  106.                     end
  107.                    
  108.                     -- Change the files
  109.                     for filePath, fileContent in next, files do
  110.                         local fileHandle = fs.open( fs.combine( sFolder, filePath ), "w" )
  111.                         fileHandle.write( fileContent )
  112.                         fileHandle.close()
  113.                     end
  114.                 else
  115.                     print( "Couldn't retrieve file list" )
  116.                 end
  117.             else
  118.                 print( "Couldn't retrieve file list" )
  119.             end
  120.         end,
  121.     },
  122.     gitfile = {
  123.         params = 4,
  124.         pattern = "^gitfile%s(.-)/(.-)/(.-)%s(.-)%s(.-)$",
  125.         pattern_file = "%1/%2/%3 %4 %5",
  126.         pattern_func = function( sUser, sProject, sPath, sBranch, sFile )
  127.             -- Get the file tree
  128.             local httpHandle = httpWrapper( string.format( "https://api.github.com/repos/%s/%s/git/trees/%s?recursive=1", sUser, sProject, sBranch ) )
  129.             if httpHandle then
  130.                 local sJSON = httpHandle.readAll()
  131.                 httpHandle.close()
  132.                
  133.                 local tJSON = loadJSON( sJSON )
  134.                 if tJSON then
  135.                     -- Check if the file is in the repository
  136.                     local isFile = false
  137.                     for _, treeObject in next, tJSON.tree do
  138.                         if treeObject.path == sPath then
  139.                             isFile = ( treeObject.type == "blob" )
  140.                             break
  141.                         end
  142.                     end
  143.                    
  144.                     if isFile then
  145.                         -- Download the file
  146.                         local file_httpHandle = httpWrapper( string.format( "https://raw.github.com/%s/%s/%s/%s", sUser, sProject, sBranch, sPath:gsub( "[%s]", "%%20" ) ) )
  147.                         if file_httpHandle then
  148.                             if fs.exists( sFile ) then
  149.                                 fs.delete( sFile )
  150.                             end
  151.                            
  152.                             local fileHandle = fs.open( sFile , "w" )
  153.                             fileHandle.write( file_httpHandle.readAll() )
  154.                             file_httpHandle.close()
  155.                             fileHandle.close()
  156.                         else
  157.                             print( "Couldn't get file content" )
  158.                         end
  159.                     end
  160.                 end
  161.             else
  162.                 print( "Couldn't retrieve file list" )
  163.             end
  164.         end
  165.     },
  166.     pastebin = {
  167.         params = 3,
  168.         pattern = "^pastebin%s(.-)%s(.-)$",
  169.         pattern_file = "%1 %2",
  170.         pattern_func = function( sCode, sFile )
  171.             local httpHandle = httpWrapper( "http://pastebin.com/raw.php?i=" .. sCode )
  172.             if httpHandle then
  173.                 local fileHandle = fs.open( sFile, "w" )
  174.                 fileHandle.write( httpHandle.readAll() )
  175.                 httpHandle.close()
  176.                 fileHandle.close()
  177.             else
  178.                 print( "Couldn't retrieve file contents" )
  179.             end
  180.         end
  181.     },
  182. }
  183.  
  184. -- Parse the arguments
  185. local manual = false
  186.  
  187. -- First check for hooks like -m
  188. local removeIndices = {}
  189. local removeIndices_mt = {
  190.     __call = function()
  191.         for _, index in next, removeIndices do
  192.             table.remove( tArgs, index )
  193.         end
  194.         removeIndices = setmetatable( {}, getmetatable( removeIndices ) )
  195.     end
  196. }
  197. setmetatable( removeIndices, removeIndices_mt )
  198.  
  199. if #tArgs > 0 then
  200.     for index, argument in next, tArgs do
  201.         if argument:lower() == "-m" then
  202.             manual = true
  203.             table.insert( removeIndices, index )
  204.         end
  205.     end
  206. end
  207.  
  208. -- Remove the indices which contain -m
  209. removeIndices()
  210.  
  211. -- Master table which holds all modules
  212. local modules = setmetatable( {}, {
  213.     __index = function( t, k )
  214.         local raw = rawget( t, k )
  215.         if not raw then
  216.             local pointer = {}
  217.             t[ k ] = pointer
  218.             return pointer
  219.         end
  220.         return raw
  221.     end
  222. })
  223.  
  224. -- Check all parseObjects ( with the arguments from the command prompt )
  225. local function tryParse()
  226.     if #tArgs > 0 then
  227.         local cmdLine = ""
  228.         local count = 0
  229.         for index, arg in next, tArgs do
  230.             count = count + 1
  231.             cmdLine = cmdLine .. arg .. " "
  232.             table.insert( removeIndices, index )
  233.             for objectName, parseObject in next, parseObjects do
  234.                 if string.match( cmdLine, parseObject.pattern ) and count == parseObject.params then
  235.                     return objectName, parseObject, cmdLine:sub( 1, cmdLine:len() - 1 )
  236.                 end
  237.             end
  238.         end
  239.     end
  240. end
  241.  
  242. for objectName, parseObject, cmdLine in tryParse do
  243.     if not manual then
  244.         local sFileObject = string.gsub( cmdLine, parseObject.pattern, parseObject.pattern_file )
  245.         table.insert( modules[ objectName ], sFileObject )
  246.     else
  247.         string.gsub( cmdLine, parseObject.pattern, parseObject.pattern_func )
  248.     end
  249.     removeIndices()
  250. end
  251.  
  252. -- Get modules from the .update file
  253. if fs.exists( "/.update" ) then
  254.     -- Read the file contents
  255.     local fileLines = {}
  256.     local fileHandle = fs.open( "/.update", "r" )
  257.     for line in fileHandle.readLine do
  258.         table.insert( fileLines, line )
  259.     end
  260.     fileHandle.close()
  261.    
  262.     -- Parse the file contents
  263.     local currentModule = nil
  264.     for _, sLine in next, fileLines do
  265.         -- Try to get the module
  266.         local skip = false
  267.         if string.match( sLine, "%[.-%]" ) then
  268.             currentModule = string.gsub( sLine, "%[(.-)%]", "%1" )
  269.             skip = true
  270.         end
  271.        
  272.         if currentModule and parseObjects[ currentModule ] and sLine ~= "" and not skip then
  273.             table.insert( modules[ currentModule ], sLine )
  274.         end
  275.     end
  276.    
  277.     -- Delete the file, it's getting remade anyway
  278.     fs.delete( "/.update" )
  279. end
  280.  
  281. -- Write all modules to the .update file
  282. local fileHandle = fs.open( "/.update", "a" )
  283. for moduleName, tObjects in next, modules do
  284.     fileHandle.writeLine( string.format( "[%s]", moduleName ) )
  285.     for _, sObject in next, tObjects do
  286.         fileHandle.writeLine( sObject )
  287.     end
  288. end
  289. fileHandle.close()
  290.  
  291. -- Finally, update all files
  292. for moduleName, tObjects in next, modules do
  293.     for _, sObject in next, tObjects do
  294.         local object = parseObjects[ moduleName ]
  295.         string.gsub( string.format( "%s %s", moduleName, sObject ), object.pattern, object.pattern_func )
  296.     end
  297. end
Add Comment
Please, Sign In to add comment