diff --git a/Justfile b/Justfile index 61c36cc..81e4f63 100644 --- a/Justfile +++ b/Justfile @@ -178,7 +178,7 @@ test *args: rom_arg=(--rom /Applications/CraftOS-PC.app/Contents/Resources) fi repo='{{justfile_directory()}}' - mount_arg=(--mount-ro "/apis=$repo/apis" --mount-ro "/programs=$repo/programs" --mount-ro "/startup=$repo/startup" --mount-ro "/tests=$repo/tests") + mount_arg=(--mount-ro "/trapos=$repo" --mount-ro "/apis=$repo/apis" --mount-ro "/programs=$repo/programs" --mount-ro "/startup=$repo/startup" --mount-ro "/tests=$repo/tests") tmp="$(mktemp)" data_dir="$(mktemp -d)" output_path="$data_dir/computer/0/trapos-test-output" diff --git a/install-ccpm.lua b/install-ccpm.lua index 10b364a..541e807 100644 --- a/install-ccpm.lua +++ b/install-ccpm.lua @@ -1,4 +1,4 @@ -local _VERSION = '5.0.0'; +local _VERSION = '5.0.1'; local REPO_BASE = 'https://raw.githubusercontent.com/guillaumearm/cc-libs/'; local LOCAL_STATE_DIR = '/trapos'; @@ -62,6 +62,18 @@ local function fetchDescriptor(branch, pkg) return fetchJson(REPO_BASE .. branch .. '/packages/' .. pkg .. '/ccpm.json'); end +local function ensureProgramsPath() + local current = shell.path(); + for entry in string.gmatch(current, '[^:]+') do + if entry == '/programs' then return; end + end + if current == '' then + shell.setPath('/programs'); + return; + end + shell.setPath(current .. ':/programs'); +end + -- Resolve a list of package names + their dependencies into install order -- (deps first). Returns an ordered list of descriptors or nil, err. local function resolvePackages(branch, names) @@ -229,12 +241,15 @@ writeJsonFile(LOCAL_MANIFEST_PATH, { writeJsonFile(LOCAL_LOCK_PATH, { packages = lockPackages }); seedCcpmConfig(branch); +ensureProgramsPath(); print(); print('=> ccpm installed (branch: ' .. branch .. ')'); print('=> Default registry: ' .. DEFAULT_REGISTRY_NAME); print('=> Run: ccpm update'); print('=> Run: ccpm install trapos'); -shell.execute('/startup/servers.lua'); +if fs.exists('/startup/servers.lua') then + shell.execute('/startup/servers.lua'); +end shell.setDir(previousDir); diff --git a/tests/install-ccpm.lua b/tests/install-ccpm.lua new file mode 100644 index 0000000..c9e056f --- /dev/null +++ b/tests/install-ccpm.lua @@ -0,0 +1,120 @@ +local createLibTest = require('/apis/libtest'); + +local testlib = createLibTest({ ... }); + +local function parentDir(path) + return path:match('^(.*)/[^/]+$'); +end + +local function sandboxPath(root, path) + if path:sub(1, 1) == '/' then + return root .. path; + end + return root .. '/' .. path; +end + +local function fakeFs(root) + return { + exists = function(path) + return fs.exists(sandboxPath(root, path)); + end, + makeDir = function(path) + fs.makeDir(sandboxPath(root, path)); + end, + open = function(path, mode) + return fs.open(sandboxPath(root, path), mode); + end, + delete = function(path) + fs.delete(sandboxPath(root, path)); + end, + }; +end + +local function fakeHttp(routes) + return { + get = function(url) + local body = routes[url]; + if not body then return nil; end + return { + readAll = function() return body; end, + close = function() end, + }; + end, + }; +end + +testlib.test('programs path resolves the ccpm command', function() + local previous = shell.path(); + shell.setPath('/rom/programs:/programs'); + local resolved = shell.resolveProgram('ccpm'); + shell.setPath(previous); + testlib.assertEquals(resolved, 'programs/ccpm.lua'); +end); + +testlib.test('fresh beta bootstrap leaves ccpm runnable without tos-boot', function() + local root = '/install-ccpm-test/fresh-beta'; + fs.delete(root); + fs.makeDir(root); + + local base = 'https://raw.githubusercontent.com/guillaumearm/cc-libs/next/'; + local routes = { + [base .. 'manifest.json'] = textutils.serializeJSON({ name = 'TrapOS', version = 'test' }), + [base .. 'packages/tos-core/ccpm.json'] = textutils.serializeJSON({ + name = 'tos-core', + version = '1', + dependencies = {}, + files = { 'apis/libccpm.lua', 'programs/ccpm.lua' }, + }), + [base .. 'apis/libccpm.lua'] = 'libccpm-body', + [base .. 'programs/ccpm.lua'] = 'ccpm-body', + }; + local calls = { + executes = {}, + path = '/rom/programs', + dir = '/', + }; + local fsApi = fakeFs(root); + local env = setmetatable({ + fs = fsApi, + http = fakeHttp(routes), + print = function() end, + read = function() return 'yes'; end, + write = function() end, + shell = { + dir = function() return calls.dir; end, + setDir = function(path) calls.dir = path; end, + path = function() return calls.path; end, + setPath = function(path) calls.path = path; end, + execute = function(program, url, target) + calls.executes[#calls.executes + 1] = { program = program, url = url, target = target }; + if program ~= 'wget' then return true; end + local body = routes[url]; + if not body then return false; end + local dir = parentDir(target); + if dir then fsApi.makeDir(dir); end + local f = fsApi.open(target, 'w'); + f.write(body); + f.close(); + return true; + end, + }, + }, { __index = _G }); + + local chunk, loadErr = loadfile('/trapos/install-ccpm.lua', 't', env); + if not chunk then error(loadErr, 0); end + local ok, err = pcall(chunk, '--beta'); + if not ok then error(err, 0); end + + testlib.assertTrue(fs.exists(root .. '/programs/ccpm.lua')); + testlib.assertTrue(string.find(calls.path, '/programs', 1, true)); + for _, call in ipairs(calls.executes) do + testlib.assertTrue(call.program ~= '/startup/servers.lua'); + end + + local f = fs.open(root .. '/trapos/ccpm.json', 'r'); + local config = textutils.unserializeJSON(f.readAll()); + f.close(); + testlib.assertEquals(config.registries[1].branch, 'next'); +end); + +testlib.run();