|
|
@ -1,6 +1,7 @@ |
|
|
|
--[[ |
|
|
|
OpenPrograms package manager, browser and downloader, for easy access to many programs |
|
|
|
Author: Vexatos |
|
|
|
Sothr Package Manager, browser and downloader, for easy access to many programs |
|
|
|
Author: Vexatos, WarrickSothr |
|
|
|
Forked and modified from: https://github.com/Wuerfel21/OpenComputers/blob/master/src/main/resources/assets/opencomputers/loot/OPPM/oppm.lua |
|
|
|
]] |
|
|
|
local component = require("component") |
|
|
|
local event = require("event") |
|
|
@ -20,7 +21,8 @@ if not component.isAvailable("internet") then |
|
|
|
end |
|
|
|
local internet = require("internet") |
|
|
|
|
|
|
|
local repoLocationConfig="https://raw.githubusercontent.com/OpenPrograms/openprograms.github.io/master/repos.cfg" |
|
|
|
--local repoLocationConfig="https://raw.githubusercontent.com/OpenPrograms/openprograms.github.io/master/repos.cfg" |
|
|
|
local repoLocationConfig = "https://sothr.com/download/oc/releases/repos.cfg" |
|
|
|
|
|
|
|
local args, options = shell.parse(...) |
|
|
|
|
|
|
@ -46,7 +48,7 @@ local function getContent(url) |
|
|
|
return nil |
|
|
|
end |
|
|
|
for chunk in response do |
|
|
|
sContent = sContent..chunk |
|
|
|
sContent = sContent .. chunk |
|
|
|
end |
|
|
|
return sContent |
|
|
|
end |
|
|
@ -60,8 +62,16 @@ local function getRepos() |
|
|
|
return serial.unserialize(sRepos) |
|
|
|
end |
|
|
|
|
|
|
|
local function getPackages(repo) |
|
|
|
local success, sPackages = pcall(getContent,"https://raw.githubusercontent.com/"..repo.."/master/programs.cfg") |
|
|
|
local function getPackages(src) |
|
|
|
local success, sPackages = pcall(getContent, src .. "/programs.cfg") |
|
|
|
if not success or not sPackages then |
|
|
|
return -1 |
|
|
|
end |
|
|
|
return serial.unserialize(sPackages) |
|
|
|
end |
|
|
|
|
|
|
|
local function getGithubPackages(repo) |
|
|
|
local success, sPackages = pcall(getContent, "https://raw.githubusercontent.com/" .. repo .. "/master/programs.cfg") |
|
|
|
if not success or not sPackages then |
|
|
|
return -1 |
|
|
|
end |
|
|
@ -69,20 +79,20 @@ local function getPackages(repo) |
|
|
|
end |
|
|
|
|
|
|
|
--For sorting table values by alphabet |
|
|
|
local function compare(a,b) |
|
|
|
for i=1,math.min(#a,#b) do |
|
|
|
if a:sub(i,i)~=b:sub(i,i) then |
|
|
|
return a:sub(i,i) < b:sub(i,i) |
|
|
|
local function compare(a, b) |
|
|
|
for i = 1, math.min(#a, #b) do |
|
|
|
if a:sub(i, i) ~= b:sub(i, i) then |
|
|
|
return a:sub(i, i) < b:sub(i, i) |
|
|
|
end |
|
|
|
end |
|
|
|
return #a < #b |
|
|
|
end |
|
|
|
|
|
|
|
local function downloadFile(url,path,force) |
|
|
|
local function downloadFile(url, path, force) |
|
|
|
if options.f or force then |
|
|
|
wget("-fq",url,path) |
|
|
|
wget("-fq", url, path) |
|
|
|
else |
|
|
|
wget("-q",url,path) |
|
|
|
wget("-q", url, path) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
@ -91,32 +101,32 @@ local function readFromFile(fNum) |
|
|
|
if fNum == 1 then |
|
|
|
path = "/etc/opdata.svd" |
|
|
|
elseif fNum == 2 then |
|
|
|
path = "/etc/oppm.cfg" |
|
|
|
path = "/etc/spm.cfg" |
|
|
|
if not fs.exists(path) then |
|
|
|
local tProcess = process.running() |
|
|
|
path = fs.concat(fs.path(shell.resolve(tProcess)),"/etc/oppm.cfg") |
|
|
|
path = fs.concat(fs.path(shell.resolve(tProcess)), "/etc/spm.cfg") |
|
|
|
end |
|
|
|
end |
|
|
|
if not fs.exists(fs.path(path)) then |
|
|
|
fs.makeDirectory(fs.path(path)) |
|
|
|
end |
|
|
|
if not fs.exists(path) then |
|
|
|
return {-1} |
|
|
|
return { -1 } |
|
|
|
end |
|
|
|
local file,msg = io.open(path,"rb") |
|
|
|
local file, msg = io.open(path, "rb") |
|
|
|
if not file then |
|
|
|
io.stderr:write("Error while trying to read file at "..path..": "..msg) |
|
|
|
io.stderr:write("Error while trying to read file at " .. path .. ": " .. msg) |
|
|
|
return |
|
|
|
end |
|
|
|
local sPacks = file:read("*a") |
|
|
|
file:close() |
|
|
|
return serial.unserialize(sPacks) or {-1} |
|
|
|
return serial.unserialize(sPacks) or { -1 } |
|
|
|
end |
|
|
|
|
|
|
|
local function saveToFile(tPacks) |
|
|
|
local file,msg = io.open("/etc/opdata.svd","wb") |
|
|
|
local file, msg = io.open("/etc/opdata.svd", "wb") |
|
|
|
if not file then |
|
|
|
io.stderr:write("Error while trying to save package names: "..msg) |
|
|
|
io.stderr:write("Error while trying to save package names: " .. msg) |
|
|
|
return |
|
|
|
end |
|
|
|
local sPacks = serial.serialize(tPacks) |
|
|
@ -133,35 +143,42 @@ local function listPackages(filter) |
|
|
|
print("Receiving Package list...") |
|
|
|
if not options.i then |
|
|
|
local success, repos = pcall(getRepos) |
|
|
|
if not success or repos==-1 then |
|
|
|
if not success or repos == -1 then |
|
|
|
io.stderr:write("Unable to connect to the Internet.\n") |
|
|
|
return |
|
|
|
elseif repos==nil then |
|
|
|
elseif repos == nil then |
|
|
|
print("Error while trying to receive repository list") |
|
|
|
return |
|
|
|
end |
|
|
|
for _,j in pairs(repos) do |
|
|
|
if j.repo then |
|
|
|
print("Checking Repository "..j.repo) |
|
|
|
local lPacks = getPackages(j.repo) |
|
|
|
if lPacks==nil then |
|
|
|
io.stderr:write("Error while trying to receive package list for " .. j.repo.."\n") |
|
|
|
return |
|
|
|
elseif type(lPacks) == "table" then |
|
|
|
for k in pairs(lPacks) do |
|
|
|
if not k.hidden then |
|
|
|
table.insert(packages,k) |
|
|
|
end |
|
|
|
for _, j in pairs(repos) do |
|
|
|
local lPacks |
|
|
|
local target |
|
|
|
if j.src then |
|
|
|
print("Checking Repository " .. j.src) |
|
|
|
lPacks = getPackages(j.src) |
|
|
|
target = j.src |
|
|
|
elseif j.repo then |
|
|
|
print("Checking Repository " .. j.repo) |
|
|
|
lPacks = getGithubPackages(j.repo) |
|
|
|
target = j.repo |
|
|
|
end |
|
|
|
if lPacks == nil then |
|
|
|
io.stderr:write("Error while trying to receive package list for " .. target .. "\n") |
|
|
|
return |
|
|
|
elseif type(lPacks) == "table" then |
|
|
|
for k in pairs(lPacks) do |
|
|
|
if not k.hidden then |
|
|
|
table.insert(packages, k) |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
local lRepos = readFromFile(2) |
|
|
|
if lRepos then |
|
|
|
for _,j in pairs(lRepos.repos) do |
|
|
|
for _, j in pairs(lRepos.repos) do |
|
|
|
for k in pairs(j) do |
|
|
|
if not k.hidden then |
|
|
|
table.insert(packages,k) |
|
|
|
table.insert(packages, k) |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
@ -170,42 +187,42 @@ local function listPackages(filter) |
|
|
|
local lPacks = {} |
|
|
|
local tPacks = readFromFile(1) |
|
|
|
for i in pairs(tPacks) do |
|
|
|
table.insert(lPacks,i) |
|
|
|
table.insert(lPacks, i) |
|
|
|
end |
|
|
|
packages = lPacks |
|
|
|
end |
|
|
|
if filter then |
|
|
|
local lPacks = {} |
|
|
|
for i,j in ipairs(packages) do |
|
|
|
if (#j>=#filter) and string.find(j,filter,1,true)~=nil then |
|
|
|
table.insert(lPacks,j) |
|
|
|
for i, j in ipairs(packages) do |
|
|
|
if (#j >= #filter) and string.find(j, filter, 1, true) ~= nil then |
|
|
|
table.insert(lPacks, j) |
|
|
|
end |
|
|
|
end |
|
|
|
packages = lPacks |
|
|
|
end |
|
|
|
table.sort(packages,compare) |
|
|
|
table.sort(packages, compare) |
|
|
|
return packages |
|
|
|
end |
|
|
|
|
|
|
|
local function printPackages(tPacks) |
|
|
|
if tPacks==nil or not tPacks[1] then |
|
|
|
if tPacks == nil or not tPacks[1] then |
|
|
|
print("No package matching specified filter found.") |
|
|
|
return |
|
|
|
end |
|
|
|
term.clear() |
|
|
|
local xRes,yRes = gpu.getResolution() |
|
|
|
local xRes, yRes = gpu.getResolution() |
|
|
|
print("--OpenPrograms Package list--") |
|
|
|
local xCur,yCur = term.getCursor() |
|
|
|
for _,j in ipairs(tPacks) do |
|
|
|
term.write(j.."\n") |
|
|
|
yCur = yCur+1 |
|
|
|
if yCur>yRes-1 then |
|
|
|
local xCur, yCur = term.getCursor() |
|
|
|
for _, j in ipairs(tPacks) do |
|
|
|
term.write(j .. "\n") |
|
|
|
yCur = yCur + 1 |
|
|
|
if yCur > yRes - 1 then |
|
|
|
term.write("[Press any key to continue]") |
|
|
|
local event = event.pull("key_down") |
|
|
|
if event then |
|
|
|
term.clear() |
|
|
|
print("--OpenPrograms Package list--") |
|
|
|
xCur,yCur = term.getCursor() |
|
|
|
xCur, yCur = term.getCursor() |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
@ -213,30 +230,36 @@ end |
|
|
|
|
|
|
|
local function getInformation(pack) |
|
|
|
local success, repos = pcall(getRepos) |
|
|
|
if not success or repos==-1 then |
|
|
|
if not success or repos == -1 then |
|
|
|
io.stderr:write("Unable to connect to the Internet.\n") |
|
|
|
return |
|
|
|
end |
|
|
|
for _,j in pairs(repos) do |
|
|
|
if j.repo then |
|
|
|
local lPacks = getPackages(j.repo) |
|
|
|
if lPacks==nil then |
|
|
|
io.stderr:write("Error while trying to receive package list for "..j.repo.."\n") |
|
|
|
elseif type(lPacks) == "table" then |
|
|
|
for k in pairs(lPacks) do |
|
|
|
if k==pack then |
|
|
|
return lPacks[k],j.repo |
|
|
|
end |
|
|
|
for _, j in pairs(repos) do |
|
|
|
local lPacks |
|
|
|
local target |
|
|
|
if j.src then |
|
|
|
lPacks = getPackages(j.src) |
|
|
|
target = j.src |
|
|
|
elseif j.repo then |
|
|
|
lPacks = getGithubPackages(j.repo) |
|
|
|
target = "https://raw.githubusercontent.com/" .. j.repo |
|
|
|
end |
|
|
|
if lPacks == nil then |
|
|
|
io.stderr:write("Error while trying to receive package list for " .. target .. "\n") |
|
|
|
elseif type(lPacks) == "table" then |
|
|
|
for k in pairs(lPacks) do |
|
|
|
if k == pack then |
|
|
|
return lPacks[k], target |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
local lRepos = readFromFile(2) |
|
|
|
if lRepos then |
|
|
|
for i,j in pairs(lRepos.repos) do |
|
|
|
for i, j in pairs(lRepos.repos) do |
|
|
|
for k in pairs(j) do |
|
|
|
if k==pack then |
|
|
|
return j[k],i |
|
|
|
if k == pack then |
|
|
|
return j[k], i |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
@ -256,21 +279,21 @@ local function provideInfo(pack) |
|
|
|
return |
|
|
|
end |
|
|
|
local done = false |
|
|
|
print("--Information about package '"..pack.."'--") |
|
|
|
print("--Information about package '" .. pack .. "'--") |
|
|
|
if info.name then |
|
|
|
print("Name: "..info.name) |
|
|
|
print("Name: " .. info.name) |
|
|
|
done = true |
|
|
|
end |
|
|
|
if info.description then |
|
|
|
print("Description: "..info.description) |
|
|
|
print("Description: " .. info.description) |
|
|
|
done = true |
|
|
|
end |
|
|
|
if info.authors then |
|
|
|
print("Authors: "..info.authors) |
|
|
|
print("Authors: " .. info.authors) |
|
|
|
done = true |
|
|
|
end |
|
|
|
if info.note then |
|
|
|
print("Note: "..info.note) |
|
|
|
print("Note: " .. info.note) |
|
|
|
done = true |
|
|
|
end |
|
|
|
if not done then |
|
|
@ -278,7 +301,7 @@ local function provideInfo(pack) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
local function installPackage(pack,path,update) |
|
|
|
local function installPackage(pack, path, update) |
|
|
|
update = update or false |
|
|
|
if not pack then |
|
|
|
printUsage() |
|
|
@ -287,10 +310,10 @@ local function installPackage(pack,path,update) |
|
|
|
if not path and not update then |
|
|
|
local lConfig = readFromFile(2) |
|
|
|
path = lConfig.path or "/usr" |
|
|
|
print("Installing package to "..path.."...") |
|
|
|
print("Installing package to " .. path .. "...") |
|
|
|
elseif not update then |
|
|
|
path = shell.resolve(path) |
|
|
|
print("Installing package to "..path.."...") |
|
|
|
print("Installing package to " .. path .. "...") |
|
|
|
end |
|
|
|
pack = string.lower(pack) |
|
|
|
|
|
|
@ -298,22 +321,22 @@ local function installPackage(pack,path,update) |
|
|
|
if not tPacks then |
|
|
|
io.stderr:write("Error while trying to read local package names") |
|
|
|
return |
|
|
|
elseif tPacks[1]==-1 then |
|
|
|
table.remove(tPacks,1) |
|
|
|
elseif tPacks[1] == -1 then |
|
|
|
table.remove(tPacks, 1) |
|
|
|
end |
|
|
|
|
|
|
|
local info,repo = getInformation(pack) |
|
|
|
local info, repo = getInformation(pack) |
|
|
|
if not info then |
|
|
|
print("Package does not exist") |
|
|
|
return |
|
|
|
end |
|
|
|
if update then |
|
|
|
print("Updating package "..pack) |
|
|
|
print("Updating package " .. pack) |
|
|
|
path = nil |
|
|
|
for i,j in pairs(info.files) do |
|
|
|
for k,v in pairs(tPacks[pack]) do |
|
|
|
if k==i then |
|
|
|
path = string.gsub(fs.path(v),j.."/?$","/") |
|
|
|
for i, j in pairs(info.files) do |
|
|
|
for k, v in pairs(tPacks[pack]) do |
|
|
|
if k == i then |
|
|
|
path = string.gsub(fs.path(v), j .. "/?$", "/") |
|
|
|
break |
|
|
|
end |
|
|
|
end |
|
|
@ -321,12 +344,12 @@ local function installPackage(pack,path,update) |
|
|
|
break |
|
|
|
end |
|
|
|
end |
|
|
|
path = shell.resolve(string.gsub(path,"^/?","/"),nil) |
|
|
|
path = shell.resolve(string.gsub(path, "^/?", "/"), nil) |
|
|
|
end |
|
|
|
if not update and fs.exists(path) then |
|
|
|
if not fs.isDirectory(path) then |
|
|
|
if options.f then |
|
|
|
path = fs.concat(fs.path(path),pack) |
|
|
|
path = fs.concat(fs.path(path), pack) |
|
|
|
fs.makeDirectory(path) |
|
|
|
else |
|
|
|
print("Path points to a file, needs to be a directory.") |
|
|
@ -351,63 +374,63 @@ local function installPackage(pack,path,update) |
|
|
|
end |
|
|
|
if update then |
|
|
|
term.write("Removing old files...") |
|
|
|
for i,j in pairs(tPacks[pack]) do |
|
|
|
for i, j in pairs(tPacks[pack]) do |
|
|
|
fs.remove(j) |
|
|
|
end |
|
|
|
term.write("Done.\n") |
|
|
|
end |
|
|
|
tPacks[pack] = {} |
|
|
|
term.write("Installing Files...") |
|
|
|
for i,j in pairs(info.files) do |
|
|
|
for i, j in pairs(info.files) do |
|
|
|
local nPath |
|
|
|
if string.find(j,"^//") then |
|
|
|
local lPath = string.sub(j,2) |
|
|
|
if string.find(j, "^//") then |
|
|
|
local lPath = string.sub(j, 2) |
|
|
|
if not fs.exists(lPath) then |
|
|
|
fs.makeDirectory(lPath) |
|
|
|
end |
|
|
|
nPath = fs.concat(lPath,string.gsub(i,".+(/.-)$","%1"),nil) |
|
|
|
nPath = fs.concat(lPath, string.gsub(i, ".+(/.-)$", "%1"), nil) |
|
|
|
else |
|
|
|
local lPath = fs.concat(path,j) |
|
|
|
local lPath = fs.concat(path, j) |
|
|
|
if not fs.exists(lPath) then |
|
|
|
fs.makeDirectory(lPath) |
|
|
|
end |
|
|
|
nPath = fs.concat(path,j,string.gsub(i,".+(/.-)$","%1"),nil) |
|
|
|
nPath = fs.concat(path, j, string.gsub(i, ".+(/.-)$", "%1"), nil) |
|
|
|
end |
|
|
|
local success = pcall(downloadFile,"https://raw.githubusercontent.com/"..repo.."/"..i,nPath) |
|
|
|
local success = pcall(downloadFile, "https://raw.githubusercontent.com/" .. repo .. "/" .. i, nPath) |
|
|
|
if success then |
|
|
|
tPacks[pack][i] = nPath |
|
|
|
end |
|
|
|
end |
|
|
|
if info.dependencies then |
|
|
|
term.write("Done.\nInstalling Dependencies...") |
|
|
|
for i,j in pairs(info.dependencies) do |
|
|
|
for i, j in pairs(info.dependencies) do |
|
|
|
local nPath |
|
|
|
if string.find(j,"^//") then |
|
|
|
nPath = string.sub(j,2) |
|
|
|
if string.find(j, "^//") then |
|
|
|
nPath = string.sub(j, 2) |
|
|
|
else |
|
|
|
nPath = fs.concat(path,j,string.gsub(i,".+(/.-)$","%1"),nil) |
|
|
|
nPath = fs.concat(path, j, string.gsub(i, ".+(/.-)$", "%1"), nil) |
|
|
|
end |
|
|
|
if string.lower(string.sub(i,1,4))=="http" then |
|
|
|
local success = pcall(downloadFile,i,nPath) |
|
|
|
if string.lower(string.sub(i, 1, 4)) == "http" then |
|
|
|
local success = pcall(downloadFile, i, nPath) |
|
|
|
if success then |
|
|
|
tPacks[pack][i] = nPath |
|
|
|
end |
|
|
|
else |
|
|
|
local depInfo = getInformation(string.lower(i)) |
|
|
|
if not depInfo then |
|
|
|
term.write("\nDependency package "..i.." does not exist.") |
|
|
|
term.write("\nDependency package " .. i .. " does not exist.") |
|
|
|
end |
|
|
|
installPackage(string.lower(i),fs.concat(path,j)) |
|
|
|
installPackage(string.lower(i), fs.concat(path, j)) |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
term.write("Done.\n") |
|
|
|
saveToFile(tPacks) |
|
|
|
print("Successfully installed package "..pack) |
|
|
|
print("Successfully installed package " .. pack) |
|
|
|
end |
|
|
|
|
|
|
|
local function uninstallPackage(pack) |
|
|
|
local info,repo = getInformation(pack) |
|
|
|
local info, repo = getInformation(pack) |
|
|
|
if not info then |
|
|
|
print("Package does not exist") |
|
|
|
return |
|
|
@ -416,8 +439,8 @@ local function uninstallPackage(pack) |
|
|
|
if not tFiles then |
|
|
|
io.stderr:write("Error while trying to read package names") |
|
|
|
return |
|
|
|
elseif tFiles[1]==-1 then |
|
|
|
table.remove(tFiles,1) |
|
|
|
elseif tFiles[1] == -1 then |
|
|
|
table.remove(tFiles, 1) |
|
|
|
end |
|
|
|
if not tFiles[pack] then |
|
|
|
print("Package has not been installed.") |
|
|
@ -425,36 +448,36 @@ local function uninstallPackage(pack) |
|
|
|
return |
|
|
|
end |
|
|
|
term.write("Removing package files...") |
|
|
|
for i,j in pairs(tFiles[pack]) do |
|
|
|
for i, j in pairs(tFiles[pack]) do |
|
|
|
fs.remove(j) |
|
|
|
end |
|
|
|
term.write("Done\nRemoving references...") |
|
|
|
tFiles[pack]=nil |
|
|
|
tFiles[pack] = nil |
|
|
|
saveToFile(tFiles) |
|
|
|
term.write("Done.\n") |
|
|
|
print("Successfully uninstalled package "..pack) |
|
|
|
print("Successfully uninstalled package " .. pack) |
|
|
|
end |
|
|
|
|
|
|
|
local function updatePackage(pack) |
|
|
|
if pack=="all" then |
|
|
|
if pack == "all" then |
|
|
|
print("Updating everything...") |
|
|
|
local tFiles = readFromFile(1) |
|
|
|
if not tFiles then |
|
|
|
io.stderr:write("Error while trying to read package names") |
|
|
|
return |
|
|
|
elseif tFiles[1]==-1 then |
|
|
|
table.remove(tFiles,1) |
|
|
|
elseif tFiles[1] == -1 then |
|
|
|
table.remove(tFiles, 1) |
|
|
|
end |
|
|
|
local done = false |
|
|
|
for i in pairs(tFiles) do |
|
|
|
installPackage(i,nil,true) |
|
|
|
installPackage(i, nil, true) |
|
|
|
done = true |
|
|
|
end |
|
|
|
if not done then |
|
|
|
print("No package has been installed so far.") |
|
|
|
end |
|
|
|
else |
|
|
|
installPackage(args[2],nil,true) |
|
|
|
installPackage(args[2], nil, true) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
@ -464,7 +487,7 @@ if args[1] == "list" then |
|
|
|
elseif args[1] == "info" then |
|
|
|
provideInfo(args[2]) |
|
|
|
elseif args[1] == "install" then |
|
|
|
installPackage(args[2],args[3],false) |
|
|
|
installPackage(args[2], args[3], false) |
|
|
|
elseif args[1] == "update" then |
|
|
|
updatePackage(args[2]) |
|
|
|
elseif args[1] == "uninstall" then |