Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --CCPT - ComputerCraft Packaging Tool
- ------
- if not http then
- error("HTTP API MUST be enabled to use this program")
- end
- --Pseudo enums
- local validator = {ok = 0, installed = 1, file_conflict = 2}
- ---Pre-definitions
- local install = nil
- local remove = nil
- ---UTILITIES
- List = {}
- function List.new ()
- return {first = 0, last = -1}
- end
- function List.pushleft (list, value)
- local first = list.first - 1
- list.first = first
- list[first] = value
- end
- function List.pushright (list, value)
- local last = list.last + 1
- list.last = last
- list[last] = value
- end
- function List.popleft (list)
- local first = list.first
- if first > list.last then return nil end
- local value = list[first]
- list[first] = nil
- list.first = first + 1
- return value
- end
- function List.popright (list)
- local last = list.last
- if list.first > last then return nil end
- local value = list[last]
- list[last] = nil
- list.last = last - 1
- return value
- end
- local function CGetS(file,name)
- local _cfg = fs.open(file,"r")
- if not _cfg then
- error("Could not open configuration file: "..file)
- end
- local x = true;
- while x do
- local line = _cfg.readLine()
- if line == nil then
- x = false;
- else
- local side = false
- local prop = ""
- local val = ""
- for a=1,#line do
- if line:sub(a,a) == '=' then
- side = true
- elseif side then
- val = val .. line:sub(a,a)
- else
- prop = prop .. line:sub(a,a)
- end
- end
- if prop == name then
- _cfg.close()
- return val
- end
- end
- end
- _cfg.close()
- end
- local function CGetN(file,name)
- return tonumber(CGetS(file,name))
- end
- local function download(file, url)
- local res = http.get(url)
- if res then
- if file ~= nil then
- fs.delete(file)
- fs.makeDir(file)
- fs.delete(file)
- local fhnd = fs.open(file, "w");
- if fhnd then
- fhnd.write(res.readAll())
- fhnd.close()
- return res.readAll()
- else
- res.close()
- error("Could not open "..file.." for writing")
- end
- else
- return res.readAll()
- end
- else
- print("WARNING:Download failed for: "..url)
- end
- res.close()
- end
- function split(text,splitter)
- local rt = {}
- local act = ""
- for x=1,#text do
- if text:sub(x,x+#splitter-1) == splitter then
- rt[#rt+1]=act
- act=""
- else
- act = act .. text:sub(x,x)
- end
- end
- if act ~= "" then
- rt[#rt+1] = act
- end
- return rt;
- end
- ---Intarnal functions
- local function update_list()
- --local sync = CGetS("/etc/ccpt/config","master")
- --if sync then
- --download("/etc/ccpt/list",sync)
- local run = true
- local exec = List.new()
- local num = 0
- local sources = fs.open("/etc/ccpt/sources","r")
- if not sources then
- error("Could not open base file: /etc/ccpt/list")
- end
- local x = true;
- while x do
- local line = sources.readLine()
- if line == nil then
- x = false;
- else
- print("List:"..line)
- List.pushright(exec,download(nil,line))
- end
- end
- fs.delete("/etc/ccpt/list")
- fs.makeDir("/etc/ccpt/list")
- fs.delete("/etc/ccpt/list")
- local fhnd = fs.open("/etc/ccpt/list", "w");
- if fhnd then
- while run do
- local proc = List.popright(exec)
- if proc then
- local tline = split(proc,"\n")
- for k,val in pairs(tline) do
- local row = split(val,";")
- if row[1] == "p" then
- fhnd.writeLine(val)
- num = num + 1
- elseif row[1] == "s" then
- print("List:"..row[2])
- local dl = download(nil,row[2])
- if dl then
- List.pushright(exec,dl)
- end
- end
- end
- else
- run = false
- end
- end
- fhnd.close()
- else
- error("Could not open "..file.." for writing")
- end
- print("Packages defined: "..tostring(num))
- end
- local function register(name,version,header)
- local reg = nil
- if fs.exists("/etc/ccpt/installed") then
- reg = fs.open("/etc/ccpt/installed","a")
- else
- reg = fs.open("/etc/ccpt/installed","w")
- end
- if reg then
- reg.writeLine(name..";"..tostring(version))
- reg.close()
- else
- error("Critical:Could not register installation")
- end
- local freg = nil
- if fs.exists("/etc/ccpt/files") then
- freg = fs.open("/etc/ccpt/files","a")
- else
- freg = fs.open("/etc/ccpt/files","w")
- end
- if freg then+
- local lhead = split(header,"\n")
- local x = 1
- for x = 1, #lhead do
- if split(lhead[x],";")[1] == "f" then
- freg.writeLine(name..";"..split(lhead[x],";")[2])
- elseif split(lhead[x],";")[1] == "u" then
- freg.writeLine(name..";"..split(lhead[x],";")[2])
- end
- end
- freg.close()
- else
- error("Error:Could not register files")
- end
- end
- local function base_find(name)
- local base = fs.open("/etc/ccpt/list","r")
- if not base then
- error("Could not open base file: /etc/ccpt/list")
- end
- local x = true;
- while x do
- local line = base.readLine()
- if line == nil then
- x = false;
- else
- local entry = split(line,";")
- if entry[1] == "p" then
- if entry[2] == name then
- local ret = {name=entry[2],url=entry[4],version=tonumber(entry[3])}
- return ret
- end
- end
- end
- end
- end
- local function validate(pname,header)
- local instbase = fs.open("/etc/ccpt/installed","r")
- if instbase then
- local x = true
- while x do
- local tline = instbase.readLine()
- if tline == nil then
- x = false
- else
- if pname == split(tline,";")[1] then
- return validator.installed
- end
- end
- end
- instbase.close()
- end
- --local filebase = fs.open("/etc/ccpt/files","r")
- if header then
- lhead = split(header,"\n")
- local x = 1
- for x = 1, #lhead do
- if split(lhead[x],";")[1] == "f" then
- if fs.exists(split(lhead[x],";")[2]) then
- print("[info]Conflict: "..split(lhead[x],";")[2])
- return validator.file_conflict
- end
- end
- end
- end
- return validator.ok
- end
- local function download_files(url,header)
- local lhead = split(header,"\n")
- local x = 1
- for x = 1, #lhead do
- if split(lhead[x],";")[1] == "f" then
- download(split(lhead[x],";")[2],url..split(lhead[x],";")[2])
- end
- if split(lhead[x],";")[1] == "u" then
- download(split(lhead[x],";")[2],split(lhead[x],";")[3])
- end
- end
- end
- local function run_scripts(url,header)
- local lhead = split(header,"\n")
- local x = 1
- for x = 1, #lhead do
- if split(lhead[x],";")[1] == "s" then
- download("/tmp/ccptpirs",url..split(lhead[x],";")[2])
- shell.run("/tmp/ccptpirs")
- fs.delete("/tmp/ccptpirs")
- end
- end
- end
- local function dep_register(what,onwhat)
- local reg = nil
- if fs.exists("/etc/ccpt/dtree") then
- reg = fs.open("/etc/ccpt/dtree","a")
- else
- reg = fs.open("/etc/ccpt/dtree","w")
- end
- if reg then
- reg.writeLine(what..";"..onwhat)
- reg.close()
- else
- error("Critical:Could not register dependencies")
- end
- end
- local function dependencies(header,package)
- local lhead = split(header,"\n")
- local x = 1
- for x = 1, #lhead do
- if split(lhead[x],";")[1] == "d" then
- install(split(lhead[x],";")[2])
- dep_register(package,split(lhead[x],";")[2])
- end
- end
- end
- local function filelist(package)
- local freg = fs.open("/etc/ccpt/files","r")
- if freg then
- local ret = {}
- local x = true
- while x do
- local tline = freg.readLine()
- if tline == nil then
- x = false
- else
- row = split(tline,";")
- if row[1] == package then
- ret[#ret+1] = row[2]
- end
- end
- end
- freg.close()
- return ret
- end
- end
- local function get_deps(package)
- local reg = fs.open("/etc/ccpt/dtree","r")
- if reg then
- local ret = {}
- local x = true
- while x do
- local tline = reg.readLine()
- if tline == nil then
- x = false
- else
- local row = split(tline,";")
- if row[1] == package then
- ret[#ret+1] = row[2]
- end
- end
- end
- reg.close()
- return ret
- end
- end
- local function get_refcount(package)
- local reg = fs.open("/etc/ccpt/dtree","r")
- local ret = 0
- if reg then
- local x = true
- while x do
- local tline = reg.readLine()
- if tline == nil then
- x = false
- else
- local row = split(tline,";")
- if row[2] == package then
- ret = ret + 1
- end
- end
- end
- reg.close()
- end
- return ret
- end
- local function get_unused(list)
- local x = 1
- local ret = {}
- if list then
- for x = 1, #list do
- if get_refcount(list[x]) == 0 then
- ret[#ret + 1] = list[x]
- end
- end
- end
- return ret
- end
- local function unregister(package)
- local reg = fs.open("/etc/ccpt/installed","r")
- local newbase = {}
- if reg then
- local x = true
- while x do
- local tline = reg.readLine()
- if tline == nil then
- x = false
- else
- local row = split(tline,";")
- if row[1] ~= package then
- newbase[#newbase+1] = tline
- end
- end
- end
- reg.close()
- end
- fs.delete("/etc/ccpt/installed")
- reg = fs.open("/etc/ccpt/installed","w")
- if reg then
- local x = 1
- for x = 1, #newbase do
- reg.writeLine(newbase[x])
- end
- reg.close()
- else
- error("CRITICAL: Could not open database for writing")
- end
- reg = fs.open("/etc/ccpt/files","r")
- newbase = {}
- if reg then
- local x = true
- while x do
- local tline = reg.readLine()
- if tline == nil then
- x = false
- else
- local row = split(tline,";")
- if row[1] ~= package then
- newbase[#newbase+1] = tline
- end
- end
- end
- reg.close()
- end
- fs.delete("/etc/ccpt/files")
- reg = fs.open("/etc/ccpt/files","w")
- if reg then
- local x = 1
- for x = 1, #newbase do
- reg.writeLine(newbase[x])
- end
- reg.close()
- else
- error("CRITICAL: Could not open file base for writing")
- end
- end
- local function deptree_unregister(package)
- local reg = fs.open("/etc/ccpt/dtree","r")
- local newbase = {}
- if reg then
- local x = true
- while x do
- local tline = reg.readLine()
- if tline == nil then
- x = false
- else
- local row = split(tline,";")
- if row[1] ~= package then
- newbase[#newbase+1] = tline
- end
- end
- end
- reg.close()
- end
- fs.delete("/etc/ccpt/dtree")
- reg = fs.open("/etc/ccpt/dtree","w")
- if reg then
- local x = 1
- for x = 1, #newbase do
- reg.writeLine(newbase[x])
- end
- reg.close()
- else
- error("CRITICAL: Could not dtree database for writing")
- end
- end
- local function get_installed()
- local reg = fs.open("/etc/ccpt/installed","r")
- local ret = {}
- if reg then
- local x = true
- while x do
- local tline = reg.readLine()
- if tline == nil then
- x = false
- else
- local row = split(tline,";")
- ret[#ret + 1] = {name = row[1], version = tonumber(row[2])}
- end
- end
- reg.close()
- end
- return ret
- end
- local function list_upgardable()
- local installed = get_installed()
- local ret = {}
- for k,val in pairs(installed) do
- if val.version ~= base_find(val.name).version then
- ret[#ret + 1] = val.name
- end
- end
- return ret
- end
- install = function (package)
- print("["..package.."]Reading Database")
- local entry = base_find(package)
- if entry then
- print("["..package.."]Downloading package header")
- local header = download(nil, entry.url..entry.name.."/index")
- print("["..package.."]Checking for conflicts")
- local vres = validate(entry.name,header)
- if vres == validator.ok then
- print("["..package.."]Checking dependencies")
- dependencies(header,package)
- print("["..package.."]Downloading files")
- download_files(entry.url..entry.name,header)
- print("["..package.."]Registering")
- register(package,entry.version,header)
- print("["..package.."]Running post-init scripts")
- run_scripts(entry.url..entry.name,header)
- elseif vres == validator.installed then
- print("["..package.."]Package already installed")
- else
- error("["..package.."]File conflict detected!")
- end
- else
- print("["..package.."]Package not found!")
- end
- end
- remove = function (package)
- print("["..package.."]Reading database")
- if validate(package,nil) == validator.installed then
- print("["..package.."]Removing files")
- local list = filelist(package)
- local removed = 0
- if list then
- local x = 1
- for x = 1, #list do
- fs.delete(list[x])
- removed = removed + 1
- end
- end
- print("["..package.."]"..tostring(removed).." files removed")
- print("["..package.."]Removing from database")
- unregister(package)
- print("["..package.."]Removing unused dependencies")
- local deps = get_deps(package)
- deptree_unregister(package)
- local remlist = get_unused(deps)
- for k,val in pairs(remlist) do
- remove(val)
- end
- else
- print("["..package.."]Package not installed")
- end
- end
- local function upgrade()
- print("Updating package list")
- update_list()
- print("Upgrading packages")
- local todo = list_upgardable()
- for k,val in pairs(todo) do
- remove(val)
- install(val)
- end
- print(tostring(#todo).." Packages upgraded")
- end
- ---MAIN CODE
- local argv = {...}
- if argv[1] == "init" then
- if fs.exists("/etc/ccpt") then
- print("ComuterCraftPackagingTool already initated")
- else
- print("Installing directories")
- fs.makeDir("/etc/")
- fs.makeDir("/etc/ccpt")
- fs.makeDir("/bin/")
- fs.makeDir("/usr/")
- fs.makeDir("/tmp/")
- fs.makeDir("/var/")
- fs.makeDir("/var/log")
- fs.makeDir("/opt/")
- fs.makeDir("/usr/bin")
- fs.makeDir("/usr/lib")
- fs.makeDir("/usr/share")
- print("Downloading default configuration")
- download("/etc/ccpt/sources","http://cc.nativehttp.org/fresh/sources")
- download("/etc/ccpt/installed","http://cc.nativehttp.org/fresh/installed")
- download("/etc/ccpt/files","http://cc.nativehttp.org/fresh/files")
- print("Checking for upgrades")
- upgrade()
- end
- elseif argv[1] == "update" then
- print("Updating package list")
- update_list()
- elseif argv[1] == "install" then
- if argv[2] == nil then
- print("Usage: ccpk install [name]")
- else
- install(argv[2])
- end
- elseif argv[1] == "remove" then
- if argv[2] == nil then
- print("Usage: ccpk remove [name]")
- else
- remove(argv[2])
- end
- elseif argv[1] == "upgrade" then
- upgrade()
- else
- print("Usage:")
- print("ccpt init")
- print("ccpt install [name]")
- print("ccpt remove [name]")
- print("ccpt update")
- print("ccpt upgrade")
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement