This commit is contained in:
p2vman 2025-04-26 16:14:03 +03:00
commit d46c11b3a8
3 changed files with 271 additions and 0 deletions

12
ckg.min.lua Normal file
View File

@ -0,0 +1,12 @@
local a={}local b="/ckg"local c=fs.combine(b,"cache")local d=fs.combine(c,"repos")local e=fs.combine(b,"config.txt")local f={"https://example.com/repo/packages.json"}local function g()if not fs.exists(e)then return{repos=f}end;local h=fs.open(e,"r")local i=textutils.unserialize(h.readAll())h.close()return i end;local function j(i)local h=fs.open(e,"w")h.write(textutils.serialize(i))h.close()end;local function k(i)if not fs.exists(d)then fs.makeDir(d)end;local l={}for m,n in ipairs(i.repos)do local o=fs.combine(d,"repo_"..m..".json")if fs.exists(o)then local h=fs.open(o,"r")local p=textutils.unserializeJSON(h.readAll())h.close()for q,r in pairs(p)do l[q]=r end else if http.checkURL(n)then print("Fetching index from "..n)local s=".pkg_tmp_repo.json"if fs.exists(s)then fs.delete(s)end;shell.run("wget",n,s)local h=fs.open(s,"r")local p=textutils.unserializeJSON(h.readAll())h.close()fs.delete(s)local t=fs.open(o,"w")t.write(textutils.serializeJSON(p))t.close()for q,r in pairs(p)do l[q]=r end else print("Warning: cannot reach repo "..n)end end end;return l end;local function u(v,w,x)for y,z in ipairs(w)do local n=v.."/"..z;local A=fs.combine(x,z)local B=fs.getDir(A)if not fs.exists(B)then fs.makeDir(B)end;if fs.exists(A)then fs.delete(A)end;shell.run("wget",n,A)end end;local function C(q,D,E)if E[q]then return end;local F=D[q]if not F then error("Package not found: "..q)end;if F.dependencies then for y,G in ipairs(F.dependencies)do C(G,D,E)end end;local x=fs.combine(b,q)if fs.exists(x)then print("Already installed: "..q)E[q]=true;return end;if not fs.exists(c)then fs.makeDir(c)end;local H=fs.combine(c,q)if fs.exists(H)then print("Installing "..q.." from cache...")fs.copy(H,x)else print("Downloading "..q.."...")fs.makeDir(H)u(F.base_url,F.files,H)fs.copy(H,x)end;print("Installed "..q)E[q]=true end;function CKG.install(q)local i=g()local D=k(i)C(q,D,{})end;function CKG.fetch(q)local i=g()local D=k(i)local F=D[q]if not F then error("Package not found: "..q)end;if not fs.exists(c)then fs.makeDir(c)end;local H=fs.combine(c,q)if fs.exists(H)then fs.delete(H)end;fs.makeDir(H)u(F.base_url,F.files,H)print("Fetched "..q.." to cache")end;function CKG.remove(q)local x=fs.combine(b,q)if fs.exists(x)then fs.delete(x)print("Removed "..q)else print("Package not installed: "..q)end end;function CKG.list()if not fs.exists(b)then print("No packages installed.")return end;local D=fs.list(b)for y,F in ipairs(D)do if F~="cache"and F~="config.txt"then print(F)end end end;function CKG.add_repo(n)local i=g()table.insert(i.repos,n)j(i)print("Repository added: "..n)end;function CKG.list_repos()local i=g()for y,n in ipairs(i.repos)do print(n)end end;function CKG.clear_repos()j({repos=f})print("Repositories reset to default")end;function CKG.clear_cache()if fs.exists(c)then fs.delete(c)print("Cache cleared")else print("Cache is already empty")end end;function CKG.update()if fs.exists(d)then fs.delete(d)end;fs.makeDir(d)local i=g()for m,n in ipairs(i.repos)do if http.checkURL(n)then print("Updating index from "..n)local s=".pkg_tmp_repo.json"if fs.exists(s)then fs.delete(s)end;shell.run("wget",n,s)local h=fs.open(s,"r")local p=textutils.unserializeJSON(h.readAll())h.close()fs.delete(s)local o=fs.combine(d,"repo_"..m..".json")local t=fs.open(o,"w")t.write(textutils.serializeJSON(p))t.close()else print("Warning: cannot reach repo "..n)end end;print("Repository indexes updated!")end;local I={...}local J=I[1]if J=="install"then CKG.install(I[2])elseif J=="remove"then CKG.remove(I[2])elseif J=="list"then CKG.list()elseif J=="fetch"then CKG.fetch(I[2])elseif J=="clear-cache"then CKG.clear_cache()elseif J=="add-repo"then CKG.add_repo(I[2])elseif J=="list-repos"then CKG.list_repos()elseif J=="clear-repos"then CKG.clear_repos()elseif J=="update"then CKG.update()else print([[
Usage:
ckg install <name> Install a package
ckg remove <name> Remove a package
ckg list List installed packages
ckg fetch <name> Download package to cache
ckg clear-cache Clear downloaded packages cache
ckg add-repo <url> Add a new repository
ckg list-repos List repositories
ckg clear-repos Reset repositories to default
ckg update Refresh package indexes
]])end

3
packages.json Normal file
View File

@ -0,0 +1,3 @@
{
}

256
src/ckg.lua Normal file
View File

@ -0,0 +1,256 @@
--[[
My ComputerCraft Package Manager
Supports multiple repositories, dependency resolution, index and package caching.
]]
local PKG = {}
local INSTALL_DIR = "/ckg"
local CACHE_DIR = fs.combine(INSTALL_DIR, "cache")
local REPO_CACHE_DIR = fs.combine(CACHE_DIR, "repos")
local CONFIG_FILE = fs.combine(INSTALL_DIR, "config.txt")
local DEFAULT_REPOS = {
"https://example.com/repo/packages.json"
}
local function load_config()
if not fs.exists(CONFIG_FILE) then
return { repos = DEFAULT_REPOS }
end
local f = fs.open(CONFIG_FILE, "r")
local cfg = textutils.unserialize(f.readAll())
f.close()
return cfg
end
local function save_config(cfg)
local f = fs.open(CONFIG_FILE, "w")
f.write(textutils.serialize(cfg))
f.close()
end
local function fetch_package_lists(cfg)
if not fs.exists(REPO_CACHE_DIR) then fs.makeDir(REPO_CACHE_DIR) end
local all = {}
for i, url in ipairs(cfg.repos) do
local cached_file = fs.combine(REPO_CACHE_DIR, "repo_" .. i .. ".json")
if fs.exists(cached_file) then
local f = fs.open(cached_file, "r")
local data = textutils.unserializeJSON(f.readAll())
f.close()
for name, info in pairs(data) do
all[name] = info
end
else
if http.checkURL(url) then
print("Fetching index from " .. url)
local tmp = ".pkg_tmp_repo.json"
if fs.exists(tmp) then fs.delete(tmp) end
shell.run("wget", url, tmp)
local f = fs.open(tmp, "r")
local data = textutils.unserializeJSON(f.readAll())
f.close()
fs.delete(tmp)
local cache = fs.open(cached_file, "w")
cache.write(textutils.serializeJSON(data))
cache.close()
for name, info in pairs(data) do
all[name] = info
end
else
print("Warning: cannot reach repo " .. url)
end
end
end
return all
end
local function install_files(base_url, files, install_path)
for _, file in ipairs(files) do
local url = base_url .. "/" .. file
local path = fs.combine(install_path, file)
local dir = fs.getDir(path)
if not fs.exists(dir) then fs.makeDir(dir) end
if fs.exists(path) then fs.delete(path) end
shell.run("wget", url, path)
end
end
local function install_single(name, list, installed)
if installed[name] then return end
local pkg = list[name]
if not pkg then
error("Package not found: " .. name)
end
if pkg.dependencies then
for _, dep in ipairs(pkg.dependencies) do
install_single(dep, list, installed)
end
end
local install_path = fs.combine(INSTALL_DIR, name)
if fs.exists(install_path) then
print("Already installed: " .. name)
installed[name] = true
return
end
if not fs.exists(CACHE_DIR) then fs.makeDir(CACHE_DIR) end
local cache_path = fs.combine(CACHE_DIR, name)
if fs.exists(cache_path) then
print("Installing " .. name .. " from cache...")
fs.copy(cache_path, install_path)
else
print("Downloading " .. name .. "...")
fs.makeDir(cache_path)
install_files(pkg.base_url, pkg.files, cache_path)
fs.copy(cache_path, install_path)
end
print("Installed " .. name)
installed[name] = true
end
function CKG.install(name)
local cfg = load_config()
local list = fetch_package_lists(cfg)
install_single(name, list, {})
end
function CKG.fetch(name)
local cfg = load_config()
local list = fetch_package_lists(cfg)
local pkg = list[name]
if not pkg then
error("Package not found: " .. name)
end
if not fs.exists(CACHE_DIR) then fs.makeDir(CACHE_DIR) end
local cache_path = fs.combine(CACHE_DIR, name)
if fs.exists(cache_path) then fs.delete(cache_path) end
fs.makeDir(cache_path)
install_files(pkg.base_url, pkg.files, cache_path)
print("Fetched " .. name .. " to cache")
end
function CKG.remove(name)
local install_path = fs.combine(INSTALL_DIR, name)
if fs.exists(install_path) then
fs.delete(install_path)
print("Removed " .. name)
else
print("Package not installed: " .. name)
end
end
function CKG.list()
if not fs.exists(INSTALL_DIR) then
print("No packages installed.")
return
end
local list = fs.list(INSTALL_DIR)
for _, pkg in ipairs(list) do
if pkg ~= "cache" and pkg ~= "config.txt" then
print(pkg)
end
end
end
function CKG.add_repo(url)
local cfg = load_config()
table.insert(cfg.repos, url)
save_config(cfg)
print("Repository added: " .. url)
end
function CKG.list_repos()
local cfg = load_config()
for _, url in ipairs(cfg.repos) do
print(url)
end
end
function CKG.clear_repos()
save_config({ repos = DEFAULT_REPOS })
print("Repositories reset to default")
end
function CKG.clear_cache()
if fs.exists(CACHE_DIR) then
fs.delete(CACHE_DIR)
print("Cache cleared")
else
print("Cache is already empty")
end
end
function CKG.update()
if fs.exists(REPO_CACHE_DIR) then fs.delete(REPO_CACHE_DIR) end
fs.makeDir(REPO_CACHE_DIR)
local cfg = load_config()
for i, url in ipairs(cfg.repos) do
if http.checkURL(url) then
print("Updating index from " .. url)
local tmp = ".pkg_tmp_repo.json"
if fs.exists(tmp) then fs.delete(tmp) end
shell.run("wget", url, tmp)
local f = fs.open(tmp, "r")
local data = textutils.unserializeJSON(f.readAll())
f.close()
fs.delete(tmp)
local cached_file = fs.combine(REPO_CACHE_DIR, "repo_" .. i .. ".json")
local cache = fs.open(cached_file, "w")
cache.write(textutils.serializeJSON(data))
cache.close()
else
print("Warning: cannot reach repo " .. url)
end
end
print("Repository indexes updated!")
end
-- CLI interface
local args = { ... }
local cmd = args[1]
if cmd == "install" then
CKG.install(args[2])
elseif cmd == "remove" then
CKG.remove(args[2])
elseif cmd == "list" then
CKG.list()
elseif cmd == "fetch" then
CKG.fetch(args[2])
elseif cmd == "clear-cache" then
CKG.clear_cache()
elseif cmd == "add-repo" then
CKG.add_repo(args[2])
elseif cmd == "list-repos" then
CKG.list_repos()
elseif cmd == "clear-repos" then
CKG.clear_repos()
elseif cmd == "update" then
CKG.update()
else
print([[
Usage:
ckg install <name> Install a package
ckg remove <name> Remove a package
ckg list List installed packages
ckg fetch <name> Download package to cache
ckg clear-cache Clear downloaded packages cache
ckg add-repo <url> Add a new repository
ckg list-repos List repositories
ckg clear-repos Reset repositories to default
ckg update Refresh package indexes
]])
end