mirror of
https://github.com/kepler155c/opus
synced 2024-12-25 16:10:26 +00:00
package manager
This commit is contained in:
parent
67be1e0f2f
commit
99b2fa1b0b
@ -1,40 +1,52 @@
|
|||||||
local json = require('json')
|
local json = require('json')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
-- Limit queries to once per minecraft day
|
||||||
|
-- TODO: will not work if time is stopped
|
||||||
|
|
||||||
local TREE_URL = 'https://api.github.com/repos/%s/%s/git/trees/%s?recursive=1'
|
local TREE_URL = 'https://api.github.com/repos/%s/%s/git/trees/%s?recursive=1'
|
||||||
local FILE_URL = 'https://raw.githubusercontent.com/%s/%s/%s/%s'
|
local FILE_URL = 'https://raw.githubusercontent.com/%s/%s/%s/%s'
|
||||||
local git = { }
|
local git = { }
|
||||||
|
|
||||||
|
local fs = _G.fs
|
||||||
local os = _G.os
|
local os = _G.os
|
||||||
|
|
||||||
if not _G.GIT then
|
if not _G.GIT then
|
||||||
_G.GIT = { }
|
_G.GIT = { }
|
||||||
end
|
end
|
||||||
|
|
||||||
function git.list(repository, cache)
|
function git.list(repository)
|
||||||
local t = Util.split(repository, '(.-)/')
|
local t = Util.split(repository, '(.-)/')
|
||||||
|
|
||||||
local user = t[1]
|
local user = table.remove(t, 1)
|
||||||
local repo = t[2]
|
local repo = table.remove(t, 1)
|
||||||
local branch = t[3] or 'master'
|
local branch = table.remove(t, 1) or 'master'
|
||||||
|
local path
|
||||||
|
|
||||||
local dataUrl = string.format(TREE_URL, user, repo, branch)
|
if not Util.empty(t) then
|
||||||
if _G.GIT[dataUrl] then
|
path = table.concat(t, '/') .. '/'
|
||||||
_G.GIT[dataUrl].count = _G.GIT[dataUrl].count + 1
|
|
||||||
else
|
|
||||||
_G.GIT[dataUrl] = {
|
|
||||||
count = 1
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local contents = Util.download(dataUrl)
|
|
||||||
|
|
||||||
if not contents then
|
|
||||||
error('Invalid repository')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local data = json.decode(contents)
|
local cacheKey = table.concat({ user, repo, branch }, '-')
|
||||||
Util.writeTable('.git/' .. dataUrl, { day = os.day(), data = data })
|
local fname = fs.combine('.git', cacheKey)
|
||||||
|
|
||||||
|
local function getContents()
|
||||||
|
if fs.exists(fname) then
|
||||||
|
local contents = Util.readTable(fname)
|
||||||
|
if contents and contents.data == os.day() then
|
||||||
|
return contents.data
|
||||||
|
end
|
||||||
|
fs.delete(fname)
|
||||||
|
end
|
||||||
|
local dataUrl = string.format(TREE_URL, user, repo, branch)
|
||||||
|
local contents = Util.download(dataUrl)
|
||||||
|
if contents then
|
||||||
|
return json.decode(contents)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local data = getContents() or error('Invalid repository')
|
||||||
|
|
||||||
if data.message and data.message:find("API rate limit exceeded") then
|
if data.message and data.message:find("API rate limit exceeded") then
|
||||||
error("Out of API calls, try again later")
|
error("Out of API calls, try again later")
|
||||||
end
|
end
|
||||||
@ -43,15 +55,26 @@ Util.writeTable('.git/' .. dataUrl, { day = os.day(), data = data })
|
|||||||
error("Invalid repository")
|
error("Invalid repository")
|
||||||
end
|
end
|
||||||
|
|
||||||
local list = { }
|
if not fs.exists(fname) then
|
||||||
|
Util.writeTable('.git/' .. cacheKey, { day = os.day(), data = data })
|
||||||
|
end
|
||||||
|
|
||||||
|
local list = { }
|
||||||
for _,v in pairs(data.tree) do
|
for _,v in pairs(data.tree) do
|
||||||
if v.type == "blob" then
|
if v.type == "blob" then
|
||||||
v.path = v.path:gsub("%s","%%20")
|
v.path = v.path:gsub("%s","%%20")
|
||||||
|
if not path then
|
||||||
list[v.path] = {
|
list[v.path] = {
|
||||||
url = string.format(FILE_URL, user, repo, branch, v.path),
|
url = string.format(FILE_URL, user, repo, branch, v.path),
|
||||||
size = v.size,
|
size = v.size,
|
||||||
}
|
}
|
||||||
|
elseif Util.startsWith(v.path, path) then
|
||||||
|
local p = string.sub(v.path, #path)
|
||||||
|
list[p] = {
|
||||||
|
url = string.format(FILE_URL, user, repo, branch, path .. p),
|
||||||
|
size = v.size,
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -34,8 +34,7 @@ function Packages:isInstalled(package)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Packages:getManifest(package)
|
function Packages:getManifest(package)
|
||||||
-- local fname = 'packages/' .. package .. '/.package'
|
local fname = 'packages/' .. package .. '/.package'
|
||||||
local fname = 'usr/milo/.package'
|
|
||||||
if fs.exists(fname) then
|
if fs.exists(fname) then
|
||||||
return Util.readTable(fname)
|
return Util.readTable(fname)
|
||||||
end
|
end
|
||||||
|
@ -507,7 +507,7 @@ function Util.matches(str, pattern)
|
|||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
function Util.startsWidth(s, match)
|
function Util.startsWith(s, match)
|
||||||
return string.sub(s, 1, #match) == match
|
return string.sub(s, 1, #match) == match
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ local function loadApplications()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return true -- Util.startsWidth(a.run, 'http') or shell.resolveProgram(a.run)
|
return true -- Util.startsWith(a.run, 'http') or shell.resolveProgram(a.run)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
_G.requireInjector(_ENV)
|
_G.requireInjector(_ENV)
|
||||||
|
|
||||||
|
local Git = require('git')
|
||||||
local Packages = require('packages')
|
local Packages = require('packages')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
local fs = _G.fs
|
local fs = _G.fs
|
||||||
|
local term = _G.term
|
||||||
|
|
||||||
local args = { ... }
|
local args = { ... }
|
||||||
local action = table.remove(args, 1)
|
local action = table.remove(args, 1)
|
||||||
@ -16,6 +18,47 @@ if action == 'list' then
|
|||||||
for k in pairs(Packages:list()) do
|
for k in pairs(Packages:list()) do
|
||||||
Util.print('[%s] %s', Packages:isInstalled(k) and 'x' or ' ', k)
|
Util.print('[%s] %s', Packages:isInstalled(k) and 'x' or ' ', k)
|
||||||
end
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local function progress(max)
|
||||||
|
-- modified from: https://pastebin.com/W5ZkVYSi (apemanzilla)
|
||||||
|
local _, y = term.getCursorPos()
|
||||||
|
local wide, _ = term.getSize()
|
||||||
|
term.setCursorPos(1, y)
|
||||||
|
term.write("[")
|
||||||
|
term.setCursorPos(wide - 6, y)
|
||||||
|
term.write("]")
|
||||||
|
local done = 0
|
||||||
|
return function()
|
||||||
|
done = done + 1
|
||||||
|
local value = done / max
|
||||||
|
term.setCursorPos(2,y)
|
||||||
|
term.write(("="):rep(math.floor(value * (wide - 8))))
|
||||||
|
local percent = math.floor(value * 100) .. "%"
|
||||||
|
term.setCursorPos(wide - percent:len(),y)
|
||||||
|
term.write(percent)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function install(name)
|
||||||
|
local manifest = Packages:getManifest(name) or error('Invalid package')
|
||||||
|
local packageDir = fs.combine('packages', name)
|
||||||
|
local method = args[2] or 'local'
|
||||||
|
if method == 'remote' then
|
||||||
|
Util.writeTable(packageDir .. '/.install', {
|
||||||
|
mount = string.format('%s gitfs %s', packageDir, manifest.repository),
|
||||||
|
})
|
||||||
|
Util.writeTable(fs.combine(packageDir, '.package'), manifest)
|
||||||
|
else
|
||||||
|
local list = Git.list(manifest.repository)
|
||||||
|
local showProgress = progress(Util.size(list))
|
||||||
|
for path, entry in pairs(list) do
|
||||||
|
Util.download(entry.url, fs.combine(packageDir, path))
|
||||||
|
showProgress()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if action == 'install' then
|
if action == 'install' then
|
||||||
@ -23,14 +66,30 @@ if action == 'install' then
|
|||||||
if Packages:isInstalled(name) then
|
if Packages:isInstalled(name) then
|
||||||
error('Package is already installed')
|
error('Package is already installed')
|
||||||
end
|
end
|
||||||
local manifest = Packages:getManifest(name) or error('Invalid package')
|
install(name)
|
||||||
local packageDir = 'packages/' .. name
|
print('installation complete')
|
||||||
local method = args[2] or 'remote'
|
return
|
||||||
if method == 'remote' then
|
|
||||||
Util.writeTable(packageDir .. '/.install', {
|
|
||||||
mount = string.format('%s gitfs %s', packageDir, manifest.repository),
|
|
||||||
})
|
|
||||||
Util.writeTable(fs.combine(packageDir, '.package'), manifest)
|
|
||||||
print('success')
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if action == 'update' then
|
||||||
|
local name = args[1] or Syntax('Invalid package')
|
||||||
|
if not Packages:isInstalled(name) then
|
||||||
|
error('Package is not installed')
|
||||||
|
end
|
||||||
|
install(name)
|
||||||
|
print('update complete')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if action == 'uninstall' then
|
||||||
|
local name = args[1] or Syntax('Invalid package')
|
||||||
|
if not Packages:isInstalled(name) then
|
||||||
|
error('Package is not installed')
|
||||||
|
end
|
||||||
|
local packageDir = fs.combine('packages', name)
|
||||||
|
fs.delete(packageDir)
|
||||||
|
print('removed: ' .. packageDir)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
error('Syntax: Package [list | install [name] ... | update [name] | uninstall [name]')
|
||||||
|
@ -25,7 +25,7 @@ end
|
|||||||
-- dependency graph
|
-- dependency graph
|
||||||
-- https://github.com/mpeterv/depgraph/blob/master/src/depgraph/init.lua
|
-- https://github.com/mpeterv/depgraph/blob/master/src/depgraph/init.lua
|
||||||
|
|
||||||
for name, package in pairs(Packages:installed()) do
|
for name in pairs(Packages:installed()) do
|
||||||
local packageDir = fs.combine('packages', name)
|
local packageDir = fs.combine('packages', name)
|
||||||
if fs.exists(fs.combine(packageDir, '.install')) then
|
if fs.exists(fs.combine(packageDir, '.install')) then
|
||||||
local install = Util.readTable(fs.combine(packageDir, '.install'))
|
local install = Util.readTable(fs.combine(packageDir, '.install'))
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
{
|
{
|
||||||
[ 'opus-neural' ] = 'file://packages/opus-neural/.package',
|
[ 'core' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/core/.package',
|
||||||
[ 'opus-miners' ] = 'file://packages/opus-miners/.package',
|
[ 'builder' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/builder/.package',
|
||||||
[ 'opus-milo' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/milo/.package',
|
[ 'farms' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/farms/.package',
|
||||||
|
[ 'forestry' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/forestry/.package',
|
||||||
|
[ 'glasses' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/glasses/.package',
|
||||||
|
[ 'milo' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/milo/.package',
|
||||||
|
[ 'miners' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/miners/.package',
|
||||||
|
[ 'neural' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/neural/.package',
|
||||||
|
[ 'pickup' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/pickup/.package',
|
||||||
|
[ 'recipeBook' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/recipeBook/.package',
|
||||||
|
[ 'storage' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/storage/.package',
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user