diff --git a/sys/apis/git.lua b/sys/apis/git.lua index ca4a870..77c398c 100644 --- a/sys/apis/git.lua +++ b/sys/apis/git.lua @@ -1,40 +1,52 @@ local json = require('json') 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 FILE_URL = 'https://raw.githubusercontent.com/%s/%s/%s/%s' local git = { } +local fs = _G.fs local os = _G.os if not _G.GIT then _G.GIT = { } end -function git.list(repository, cache) +function git.list(repository) local t = Util.split(repository, '(.-)/') - local user = t[1] - local repo = t[2] - local branch = t[3] or 'master' + local user = table.remove(t, 1) + local repo = table.remove(t, 1) + local branch = table.remove(t, 1) or 'master' + local path - local dataUrl = string.format(TREE_URL, user, repo, branch) -if _G.GIT[dataUrl] then - _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') + if not Util.empty(t) then + path = table.concat(t, '/') .. '/' end - local data = json.decode(contents) -Util.writeTable('.git/' .. dataUrl, { day = os.day(), data = data }) + local cacheKey = table.concat({ user, repo, branch }, '-') + 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 error("Out of API calls, try again later") end @@ -43,15 +55,26 @@ Util.writeTable('.git/' .. dataUrl, { day = os.day(), data = data }) error("Invalid repository") 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 if v.type == "blob" then v.path = v.path:gsub("%s","%%20") - list[v.path] = { - url = string.format(FILE_URL, user, repo, branch, v.path), - size = v.size, - } + if not path then + list[v.path] = { + url = string.format(FILE_URL, user, repo, branch, v.path), + 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 diff --git a/sys/apis/packages.lua b/sys/apis/packages.lua index 7fdc982..ba671c5 100644 --- a/sys/apis/packages.lua +++ b/sys/apis/packages.lua @@ -34,8 +34,7 @@ function Packages:isInstalled(package) end function Packages:getManifest(package) --- local fname = 'packages/' .. package .. '/.package' - local fname = 'usr/milo/.package' + local fname = 'packages/' .. package .. '/.package' if fs.exists(fname) then return Util.readTable(fname) end diff --git a/sys/apis/util.lua b/sys/apis/util.lua index 9fe0111..54a992c 100644 --- a/sys/apis/util.lua +++ b/sys/apis/util.lua @@ -507,7 +507,7 @@ function Util.matches(str, pattern) return t end -function Util.startsWidth(s, match) +function Util.startsWith(s, match) return string.sub(s, 1, #match) == match end diff --git a/sys/apps/Overview.lua b/sys/apps/Overview.lua index 30fb9fd..fb0bbc0 100644 --- a/sys/apps/Overview.lua +++ b/sys/apps/Overview.lua @@ -82,7 +82,7 @@ local function loadApplications() 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 diff --git a/sys/apps/Package.lua b/sys/apps/Package.lua index 48b87f9..d30a77d 100644 --- a/sys/apps/Package.lua +++ b/sys/apps/Package.lua @@ -1,9 +1,11 @@ _G.requireInjector(_ENV) +local Git = require('git') local Packages = require('packages') local Util = require('util') -local fs = _G.fs +local fs = _G.fs +local term = _G.term local args = { ... } local action = table.remove(args, 1) @@ -16,6 +18,47 @@ if action == 'list' then for k in pairs(Packages:list()) do Util.print('[%s] %s', Packages:isInstalled(k) and 'x' or ' ', k) 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 if action == 'install' then @@ -23,14 +66,30 @@ if action == 'install' then if Packages:isInstalled(name) then error('Package is already installed') end - local manifest = Packages:getManifest(name) or error('Invalid package') - local packageDir = 'packages/' .. name - local method = args[2] or 'remote' - 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 + install(name) + print('installation complete') + return 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]') diff --git a/sys/extensions/6.packages.lua b/sys/extensions/6.packages.lua index fbf3ed7..8fb598a 100644 --- a/sys/extensions/6.packages.lua +++ b/sys/extensions/6.packages.lua @@ -25,7 +25,7 @@ end -- dependency graph -- 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) if fs.exists(fs.combine(packageDir, '.install')) then local install = Util.readTable(fs.combine(packageDir, '.install')) diff --git a/sys/packageList.lua b/sys/packageList.lua index 07c0821..99ddd82 100644 --- a/sys/packageList.lua +++ b/sys/packageList.lua @@ -1,5 +1,13 @@ { - [ 'opus-neural' ] = 'file://packages/opus-neural/.package', - [ 'opus-miners' ] = 'file://packages/opus-miners/.package', - [ 'opus-milo' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/milo/.package', + [ 'core' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/core/.package', + [ 'builder' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/builder/.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', } \ No newline at end of file