Advertisement
magik6000

ccpt - ComputerCraft Packaging Tool

Nov 24th, 2013
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.47 KB | None | 0 0
  1. --CCPT - ComputerCraft Packaging Tool
  2. --Made By magik6k
  3. --do whatever you want, there is only one tule(stolen from zlib license):
  4. --
  5. --1. The origin of this software must not be misrepresented; you must not
  6. --claim that you wrote the original software. If you use this software
  7. --in a product, an acknowledgment in the product documentation would be
  8. --appreciated but is not required.
  9. ------
  10. --Of course you can modify the program, then, if you want, you can add your
  11. --name to Credits section below
  12. ------
  13. --Credits:
  14. --
  15.  
  16. if not http then
  17. error("HTTP API MUST be enabled to use this program")
  18. end
  19.  
  20. --Pseudo enums
  21.  
  22. local validator = {ok = 0, installed = 1, file_conflict = 2}
  23.  
  24. ---Pre-definitions
  25.  
  26. local install = nil
  27. local remove = nil
  28.  
  29. ---UTILITIES
  30.  
  31. List = {}
  32. function List.new ()
  33.     return {first = 0, last = -1}
  34. end
  35.  
  36. function List.pushleft (list, value)
  37.     local first = list.first - 1
  38.     list.first = first
  39.     list[first] = value
  40. end
  41.  
  42. function List.pushright (list, value)
  43.     local last = list.last + 1
  44.     list.last = last
  45.     list[last] = value
  46. end
  47.  
  48. function List.popleft (list)
  49.     local first = list.first
  50.     if first > list.last then return nil end
  51.     local value = list[first]
  52.     list[first] = nil
  53.     list.first = first + 1
  54.     return value
  55. end
  56.  
  57. function List.popright (list)
  58.     local last = list.last
  59.     if list.first > last then return nil end
  60.     local value = list[last]
  61.     list[last] = nil
  62.     list.last = last - 1
  63.     return value
  64. end
  65.  
  66. local function CGetS(file,name)
  67.     local _cfg = fs.open(file,"r")
  68.    
  69.     if not _cfg then
  70.         error("Could not open configuration file: "..file)
  71.     end
  72.    
  73.     local x = true;
  74.      
  75.     while x do
  76.         local line = _cfg.readLine()
  77.         if line == nil then
  78.             x = false;
  79.         else
  80.          
  81.             local side = false
  82.             local prop = ""
  83.             local val = ""
  84.             for a=1,#line do
  85.                 if line:sub(a,a) == '=' then
  86.                     side = true
  87.                 elseif side then
  88.                     val =  val .. line:sub(a,a)
  89.                 else
  90.                     prop = prop .. line:sub(a,a)
  91.                 end
  92.             end
  93.            
  94.             if prop == name then
  95.                 _cfg.close()
  96.                 return val
  97.             end        
  98.         end  
  99.     end
  100.     _cfg.close()   
  101. end
  102.  
  103. local function CGetN(file,name)
  104.     return tonumber(CGetS(file,name))
  105. end
  106.  
  107. local function download(file, url)
  108.     local res = http.get(url)
  109.     if res then
  110.         if file ~= nil then
  111.             fs.delete(file)
  112.             fs.makeDir(file)
  113.             fs.delete(file)
  114.             local fhnd = fs.open(file, "w");
  115.             if fhnd then
  116.                 fhnd.write(res.readAll())
  117.                 fhnd.close()
  118.                 return res.readAll()
  119.             else
  120.                 res.close()
  121.                 error("Could not open "..file.." for writing")
  122.             end
  123.         else
  124.             return res.readAll()
  125.         end
  126.     else
  127.         print("WARNING:Download failed for: "..url)
  128.     end
  129.     res.close()
  130. end
  131.  
  132. function split(text,splitter)
  133.     local rt = {}
  134.     local act = ""
  135.     for x=1,#text do
  136.         if text:sub(x,x+#splitter-1) == splitter then
  137.             rt[#rt+1]=act
  138.             act=""
  139.         else
  140.             act = act .. text:sub(x,x)
  141.         end
  142.     end
  143.     if act ~= "" then
  144.         rt[#rt+1] = act
  145.     end
  146.     return rt;
  147. end
  148.  
  149. ---Intarnal functions
  150.  
  151. local function update_list()
  152.     --local sync = CGetS("/etc/ccpt/config","master")
  153.     --if sync then
  154.         --download("/etc/ccpt/list",sync)
  155.     local run = true
  156.     local exec = List.new()
  157.     local num = 0
  158.    
  159.     local sources = fs.open("/etc/ccpt/sources","r")
  160.    
  161.     if not sources then
  162.         error("Could not open base file: /etc/ccpt/list")
  163.     end
  164.    
  165.     local x = true;
  166.     while x do
  167.         local line = sources.readLine()
  168.         if line == nil then
  169.             x = false;
  170.         else
  171.             print("List:"..line)
  172.             List.pushright(exec,download(nil,line))
  173.         end
  174.     end
  175.    
  176.    
  177.     fs.delete("/etc/ccpt/list")
  178.     fs.makeDir("/etc/ccpt/list")
  179.     fs.delete("/etc/ccpt/list")
  180.     local fhnd = fs.open("/etc/ccpt/list", "w");
  181.     if fhnd then
  182.         while run do
  183.             local proc = List.popright(exec)
  184.             if proc then
  185.                 local tline = split(proc,"\n")
  186.                 for k,val in pairs(tline) do
  187.                     local row = split(val,";")
  188.                     if row[1] == "p" then
  189.                         fhnd.writeLine(val)
  190.                         num = num + 1
  191.                     elseif row[1] == "s" then
  192.                         print("List:"..row[2])
  193.                         local dl = download(nil,row[2])
  194.                         if dl then
  195.                         List.pushright(exec,dl)
  196.                         end
  197.                     end
  198.                 end
  199.             else
  200.                 run = false
  201.             end
  202.         end
  203.         fhnd.close()
  204.     else
  205.         error("Could not open "..file.." for writing")
  206.     end    
  207.     print("Packages defined: "..tostring(num))
  208. end
  209.  
  210. local function register(name,version,header)
  211.    
  212.     local reg = nil
  213.    
  214.     if fs.exists("/etc/ccpt/installed") then
  215.         reg = fs.open("/etc/ccpt/installed","a")
  216.     else
  217.         reg = fs.open("/etc/ccpt/installed","w")
  218.     end
  219.    
  220.     if reg then
  221.         reg.writeLine(name..";"..tostring(version))
  222.         reg.close()
  223.     else
  224.         error("Critical:Could not register installation")
  225.     end
  226.    
  227.     local freg = nil
  228.    
  229.     if fs.exists("/etc/ccpt/files") then
  230.         freg = fs.open("/etc/ccpt/files","a")
  231.     else
  232.         freg = fs.open("/etc/ccpt/files","w")
  233.     end
  234.    
  235.     if freg then
  236.         local lhead = split(header,"\n")
  237.         local x = 1
  238.         for x = 1, #lhead do
  239.             if split(lhead[x],";")[1] == "f" then
  240.                 freg.writeLine(name..";"..split(lhead[x],";")[2])
  241.             elseif split(lhead[x],";")[1] == "u" then
  242.                 freg.writeLine(name..";"..split(lhead[x],";")[2])
  243.             end
  244.         end
  245.         freg.close()       
  246.     else
  247.         error("Error:Could not register files")
  248.     end
  249.    
  250. end
  251.  
  252. local function base_find(name)
  253.     local base = fs.open("/etc/ccpt/list","r")
  254.    
  255.     if not base then
  256.         error("Could not open base file: /etc/ccpt/list")
  257.     end
  258.    
  259.     local x = true;
  260.     while x do
  261.         local line = base.readLine()
  262.         if line == nil then
  263.             x = false;
  264.         else
  265.             local entry = split(line,";")
  266.             if entry[1] == "p" then
  267.                 if entry[2] == name then
  268.                     local ret = {name=entry[2],url=entry[4],version=tonumber(entry[3])}
  269.                     return ret
  270.                 end
  271.             end
  272.         end
  273.     end
  274. end
  275.  
  276. local function validate(pname,header)
  277.     local instbase = fs.open("/etc/ccpt/installed","r")
  278.     if instbase then
  279.         local x = true
  280.         while x do
  281.             local tline = instbase.readLine()
  282.             if tline == nil then
  283.                 x = false
  284.             else
  285.                 if pname == split(tline,";")[1] then
  286.                     return validator.installed
  287.                 end
  288.             end
  289.         end
  290.         instbase.close()
  291.     end
  292.     --local filebase = fs.open("/etc/ccpt/files","r")
  293.     if header then
  294.         lhead = split(header,"\n")
  295.         local x = 1
  296.         for x = 1, #lhead do
  297.             if split(lhead[x],";")[1] == "f" then
  298.                 if fs.exists(split(lhead[x],";")[2]) then
  299.                     print("[info]Conflict: "..split(lhead[x],";")[2])
  300.                     return validator.file_conflict
  301.                 end
  302.             end
  303.         end
  304.     end
  305.    
  306.     return validator.ok
  307. end
  308.  
  309. local function download_files(url,header)
  310.     local lhead = split(header,"\n")
  311.     local x = 1
  312.     for x = 1, #lhead do
  313.         if split(lhead[x],";")[1] == "f" then
  314.             download(split(lhead[x],";")[2],url..split(lhead[x],";")[2])
  315.         end
  316.         if split(lhead[x],";")[1] == "u" then
  317.             download(split(lhead[x],";")[2],split(lhead[x],";")[3])
  318.         end
  319.     end
  320. end
  321.  
  322. local function run_scripts(url,header)
  323.     local lhead = split(header,"\n")
  324.     local x = 1
  325.     for x = 1, #lhead do
  326.         if split(lhead[x],";")[1] == "s" then
  327.             download("/tmp/ccptpirs",url..split(lhead[x],";")[2])
  328.             shell.run("/tmp/ccptpirs")
  329.             fs.delete("/tmp/ccptpirs")
  330.         end
  331.     end
  332. end
  333.  
  334. local function dep_register(what,onwhat)
  335.     local reg = nil
  336.    
  337.     if fs.exists("/etc/ccpt/dtree") then
  338.         reg = fs.open("/etc/ccpt/dtree","a")
  339.     else
  340.         reg = fs.open("/etc/ccpt/dtree","w")
  341.     end
  342.    
  343.     if reg then
  344.         reg.writeLine(what..";"..onwhat)
  345.         reg.close()
  346.     else
  347.         error("Critical:Could not register dependencies")
  348.     end
  349. end
  350.  
  351. local function dependencies(header,package)
  352.     local lhead = split(header,"\n")
  353.     local x = 1
  354.     for x = 1, #lhead do
  355.         if split(lhead[x],";")[1] == "d" then
  356.             install(split(lhead[x],";")[2])
  357.             dep_register(package,split(lhead[x],";")[2])
  358.         end
  359.     end
  360. end
  361.  
  362. local function filelist(package)
  363.     local freg = fs.open("/etc/ccpt/files","r")
  364.     if freg then
  365.         local ret = {}
  366.         local x = true
  367.         while x do
  368.             local tline = freg.readLine()
  369.             if tline == nil then
  370.                 x = false
  371.             else
  372.                 row = split(tline,";")
  373.                 if row[1] == package then
  374.                     ret[#ret+1] = row[2]
  375.                 end
  376.             end
  377.         end
  378.         freg.close()
  379.         return ret
  380.     end
  381. end
  382.  
  383. local function get_deps(package)
  384.     local reg = fs.open("/etc/ccpt/dtree","r")
  385.     if reg then
  386.         local ret = {}
  387.         local x = true
  388.         while x do
  389.             local tline = reg.readLine()
  390.             if tline == nil then
  391.                 x = false
  392.             else
  393.                 local row = split(tline,";")
  394.                 if row[1] == package then
  395.                     ret[#ret+1] = row[2]
  396.                 end
  397.             end
  398.         end
  399.         reg.close()
  400.         return ret
  401.     end
  402. end
  403.  
  404. local function get_refcount(package)
  405.     local reg = fs.open("/etc/ccpt/dtree","r")
  406.     local ret = 0
  407.     if reg then
  408.         local x = true
  409.         while x do
  410.             local tline = reg.readLine()
  411.             if tline == nil then
  412.                 x = false
  413.             else
  414.                 local row = split(tline,";")
  415.                 if row[2] == package then
  416.                     ret = ret + 1
  417.                 end
  418.             end
  419.         end
  420.         reg.close()
  421.     end
  422.     return ret
  423. end
  424.  
  425. local function get_unused(list)
  426.     local x = 1
  427.     local ret = {}
  428.     if list then
  429.         for x = 1, #list do
  430.             if get_refcount(list[x]) == 0 then
  431.                 ret[#ret + 1] = list[x]
  432.             end
  433.         end
  434.     end
  435.     return ret
  436. end
  437.  
  438. local function unregister(package)
  439.     local reg = fs.open("/etc/ccpt/installed","r")
  440.     local newbase = {}
  441.     if reg then
  442.         local x = true
  443.         while x do
  444.             local tline = reg.readLine()
  445.             if tline == nil then
  446.                 x = false
  447.             else
  448.                 local row = split(tline,";")
  449.                 if row[1] ~= package then
  450.                     newbase[#newbase+1] = tline
  451.                 end
  452.             end
  453.         end
  454.         reg.close()
  455.     end
  456.     fs.delete("/etc/ccpt/installed")
  457.     reg = fs.open("/etc/ccpt/installed","w")
  458.     if reg then
  459.         local x = 1
  460.         for x = 1, #newbase do
  461.             reg.writeLine(newbase[x])
  462.         end
  463.         reg.close()
  464.     else
  465.         error("CRITICAL: Could not open database for writing")
  466.     end
  467.     reg = fs.open("/etc/ccpt/files","r")
  468.     newbase = {}
  469.     if reg then
  470.         local x = true
  471.         while x do
  472.             local tline = reg.readLine()
  473.             if tline == nil then
  474.                 x = false
  475.             else
  476.                 local row = split(tline,";")
  477.                 if row[1] ~= package then
  478.                     newbase[#newbase+1] = tline
  479.                 end
  480.             end
  481.         end
  482.         reg.close()
  483.     end
  484.     fs.delete("/etc/ccpt/files")
  485.     reg = fs.open("/etc/ccpt/files","w")
  486.     if reg then
  487.         local x = 1
  488.         for x = 1, #newbase do
  489.             reg.writeLine(newbase[x])
  490.         end
  491.         reg.close()
  492.     else
  493.         error("CRITICAL: Could not open file base for writing")
  494.     end
  495. end
  496.  
  497. local function deptree_unregister(package)
  498.     local reg = fs.open("/etc/ccpt/dtree","r")
  499.     local newbase = {}
  500.     if reg then
  501.         local x = true
  502.         while x do
  503.             local tline = reg.readLine()
  504.             if tline == nil then
  505.                 x = false
  506.             else
  507.                 local row = split(tline,";")
  508.                 if row[1] ~= package then
  509.                     newbase[#newbase+1] = tline
  510.                 end
  511.             end
  512.         end
  513.         reg.close()
  514.     end
  515.     fs.delete("/etc/ccpt/dtree")
  516.     reg = fs.open("/etc/ccpt/dtree","w")
  517.     if reg then
  518.         local x = 1
  519.         for x = 1, #newbase do
  520.             reg.writeLine(newbase[x])
  521.         end
  522.         reg.close()
  523.     else
  524.         error("CRITICAL: Could not dtree database for writing")
  525.     end
  526. end
  527.  
  528. local function get_installed()
  529.     local reg = fs.open("/etc/ccpt/installed","r")
  530.     local ret = {}
  531.     if reg then
  532.         local x = true
  533.         while x do
  534.             local tline = reg.readLine()
  535.             if tline == nil then
  536.                 x = false
  537.             else
  538.                 local row = split(tline,";")
  539.                 ret[#ret + 1] = {name = row[1], version = tonumber(row[2])}
  540.             end
  541.         end
  542.         reg.close()
  543.     end
  544.     return ret
  545. end
  546.  
  547. local function list_upgardable()
  548.     local installed = get_installed()
  549.     local ret = {}
  550.     for k,val in pairs(installed) do
  551.         if val.version ~= base_find(val.name).version then
  552.             ret[#ret + 1] = val.name
  553.         end
  554.     end
  555.     return ret
  556. end
  557.  
  558. install = function (package)
  559.  
  560.     print("["..package.."]Reading Database")
  561.     local entry = base_find(package)
  562.     if entry then
  563.         print("["..package.."]Downloading package header")
  564.         local header = download(nil, entry.url..entry.name.."/index")
  565.         print("["..package.."]Checking for conflicts")
  566.         local vres = validate(entry.name,header)
  567.         if vres == validator.ok then
  568.             print("["..package.."]Checking dependencies")
  569.             dependencies(header,package)
  570.             print("["..package.."]Downloading files")
  571.             download_files(entry.url..entry.name,header)
  572.             print("["..package.."]Registering")
  573.             register(package,entry.version,header)
  574.             print("["..package.."]Running post-init scripts")
  575.             run_scripts(entry.url..entry.name,header)
  576.         elseif vres == validator.installed then
  577.             print("["..package.."]Package already installed")
  578.         else
  579.             error("["..package.."]File conflict detected!")
  580.         end
  581.     else
  582.         print("["..package.."]Package not found!")
  583.     end
  584. end
  585.  
  586. remove = function (package)
  587.     print("["..package.."]Reading database")
  588.     if validate(package,nil) == validator.installed then
  589.         print("["..package.."]Removing files")
  590.         local list = filelist(package)
  591.         local removed = 0
  592.         if list then
  593.             local x = 1
  594.             for x = 1, #list do
  595.                 fs.delete(list[x])
  596.                 removed = removed + 1
  597.             end
  598.         end
  599.         print("["..package.."]"..tostring(removed).." files removed")
  600.         print("["..package.."]Removing from database")
  601.         unregister(package)
  602.         print("["..package.."]Removing unused dependencies")
  603.         local deps = get_deps(package)
  604.         deptree_unregister(package)
  605.         local remlist = get_unused(deps)
  606.         for k,val in pairs(remlist) do
  607.             remove(val)
  608.         end
  609.     else
  610.         print("["..package.."]Package not installed")
  611.     end
  612. end
  613.  
  614. local function upgrade()
  615.     print("Updating package list")
  616.     update_list()
  617.     print("Upgrading packages")
  618.     local todo = list_upgardable()
  619.     for k,val in pairs(todo) do
  620.         remove(val)
  621.         install(val)
  622.     end
  623.     print(tostring(#todo).." Packages upgraded")
  624. end
  625.  
  626. ---MAIN CODE
  627.  
  628. local argv = {...}
  629. if     argv[1] == "init"   then
  630.     if fs.exists("/etc/ccpt") then
  631.         print("ComuterCraftPackagingTool already initated")
  632.     else
  633.         print("Installing directories")
  634.         fs.makeDir("/etc/")
  635.         fs.makeDir("/etc/ccpt")
  636.         fs.makeDir("/bin/")
  637.         fs.makeDir("/usr/")
  638.         fs.makeDir("/tmp/")
  639.         fs.makeDir("/var/")
  640.         fs.makeDir("/var/log")
  641.         fs.makeDir("/opt/")
  642.         fs.makeDir("/usr/bin")
  643.         fs.makeDir("/usr/lib")
  644.         fs.makeDir("/usr/share")
  645.         print("Downloading default configuration")
  646.         download("/etc/ccpt/sources","http://cc.nativehttp.org/fresh/sources")
  647.         download("/etc/ccpt/installed","http://cc.nativehttp.org/fresh/installed")
  648.         download("/etc/ccpt/files","http://cc.nativehttp.org/fresh/files")
  649.         print("Checking for upgrades")
  650.         upgrade()
  651.     end
  652. elseif argv[1] == "update" then
  653.     print("Updating package list")
  654.     update_list()
  655. elseif argv[1] == "install" then
  656.     if argv[2] == nil then
  657.         print("Usage: ccpt install [name]")
  658.     else
  659.         install(argv[2])
  660.     end
  661. elseif argv[1] == "remove" then
  662.     if argv[2] == nil then
  663.         print("Usage: ccpt remove [name]")
  664.     else
  665.         remove(argv[2])
  666.     end
  667. elseif argv[1] == "upgrade" then
  668.     upgrade()  
  669. else
  670.     print("Usage:")
  671.     print("ccpt init")
  672.     print("ccpt install [name]")
  673.     print("ccpt remove [name]")
  674.     print("ccpt update")
  675.     print("ccpt upgrade")
  676.    
  677. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement