feat(ccpm): default registry to gitea

This commit is contained in:
Guillaume ARM 2026-06-11 06:41:22 +02:00
parent bb585cb9ac
commit 7a92d08ca5
12 changed files with 90 additions and 16 deletions

View File

@ -36,7 +36,7 @@ Use [`docs/README.md`](docs/README.md) as the entrypoint for CC:Tweaked, CraftOS
- `startup/servers.lua` creates the boot eventloop, runs autostart server files (which register handlers and return), then runs the shell and the eventloop in parallel via `parallel.waitForAny`. - `startup/servers.lua` creates the boot eventloop, runs autostart server files (which register handlers and return), then runs the shell and the eventloop in parallel via `parallel.waitForAny`.
- Preserve `periphemu` guards used for CraftOS-PC emulation; see [`docs/craftos_pc_glossary.md`](docs/craftos_pc_glossary.md) for upstream emulator references. - Preserve `periphemu` guards used for CraftOS-PC emulation; see [`docs/craftos_pc_glossary.md`](docs/craftos_pc_glossary.md) for upstream emulator references.
- TrapOS ships as packages, each described by `packages/<name>/ccpm.json` (`name`, `version`, `dependencies`, `files`, `autostart`); `packages/index.json` lists them. Source files stay in place — descriptors only reference them. To ship a new file, add it to the right package's `files` (and `autostart` if it is a server). `packages/trapos/ccpm.json` is the full OS meta-package. See [ADR-0010](docs/adrs/adr-0010-ccpm-package-manager.md). - TrapOS ships as packages, each described by `packages/<name>/ccpm.json` (`name`, `version`, `dependencies`, `files`, `autostart`); `packages/index.json` lists them. Source files stay in place — descriptors only reference them. To ship a new file, add it to the right package's `files` (and `autostart` if it is a server). `packages/trapos/ccpm.json` is the full OS meta-package. See [ADR-0010](docs/adrs/adr-0010-ccpm-package-manager.md).
- `install-ccpm.lua` is the one-time wget bootstrap. It installs only `trapos-core`/`ccpm`, seeds the default `guillaumearm/cc-libs` registry on `master` (or `next` with `--beta`), and tells users to run `ccpm update` then `ccpm install trapos`. - `install-ccpm.lua` is the one-time wget bootstrap. It installs only `trapos-core`/`ccpm`, seeds the default `guillaumearm/cc-libs` registry as a `gitea` registry on `git.trapcloud.fr` tracking `master` (or `next` with `--beta`), and tells users to run `ccpm update` then `ccpm install trapos`. The legacy `github` registry type still resolves but is deprecated.
- `ccpm` (in `trapos-core`) is the package manager: `apis/libccpm.lua` is the testable core (factory with injectable `http`/`stateDir`/`installRoot`), `programs/ccpm.lua` the CLI. State: `/trapos/ccpm.json` (registries), `/trapos/ccpm.lock.json` (installed packages), and `/trapos/ccpm.cache.json` (available packages from `ccpm update`). Never use the word "manifest" in ccpm — it is reserved for the OS manifest. - `ccpm` (in `trapos-core`) is the package manager: `apis/libccpm.lua` is the testable core (factory with injectable `http`/`stateDir`/`installRoot`), `programs/ccpm.lua` the CLI. State: `/trapos/ccpm.json` (registries), `/trapos/ccpm.lock.json` (installed packages), and `/trapos/ccpm.cache.json` (available packages from `ccpm update`). Never use the word "manifest" in ccpm — it is reserved for the OS manifest.
- Add new servers to `startup/servers.lua` as needed. - Add new servers to `startup/servers.lua` as needed.

View File

@ -6,7 +6,7 @@ A small in-game operating system for ComputerCraft / CC:Tweaked, built around a
Install `ccpm` first. This is the only step that needs `wget` with a URL: Install `ccpm` first. This is the only step that needs `wget` with a URL:
``` ```
wget run https://raw.githubusercontent.com/guillaumearm/cc-libs/master/install-ccpm.lua wget run https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/master/install-ccpm.lua
``` ```
Then sync the default registry (`guillaumearm/cc-libs`) and install TrapOS: Then sync the default registry (`guillaumearm/cc-libs`) and install TrapOS:
@ -23,7 +23,7 @@ Install individual packages instead if you want to cherry-pick:
Install `ccpm` from the beta branch (one-time opt-in, asks for confirmation): Install `ccpm` from the beta branch (one-time opt-in, asks for confirmation):
``` ```
wget run https://raw.githubusercontent.com/guillaumearm/cc-libs/next/install-ccpm.lua --beta wget run https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/next/install-ccpm.lua --beta
``` ```
Once `ccpm` is installed from beta, the default registry tracks `next`; `ccpm update` and `ccpm upgrade` keep using that branch. Once `ccpm` is installed from beta, the default registry tracks `next`; `ccpm update` and `ccpm upgrade` keep using that branch.
@ -56,7 +56,7 @@ ccpm install <package> ccpm reinstall <package> ccpm uninstall <package>
ccpm update ccpm upgrade ccpm update ccpm upgrade
ccpm ls ccpm available [term] ccpm search [term] ccpm ls ccpm available [term] ccpm search [term]
ccpm info <package> ccpm info <package>
ccpm registry ls ccpm registry add <name> [--branch <b>] [--type github|http] ccpm registry ls ccpm registry add <name> [--branch <b>] [--type gitea|github|http]
ccpm registry rm <name> ccpm registry rm <name>
``` ```

View File

@ -85,7 +85,7 @@ local function createCcpm(opts)
end end
local registry = { local registry = {
name = name, name = name,
type = registryOpts.type or 'github', type = registryOpts.type or 'gitea',
branch = registryOpts.branch or 'master', branch = registryOpts.branch or 'master',
}; };
cfg.registries[#cfg.registries + 1] = registry; cfg.registries[#cfg.registries + 1] = registry;
@ -176,6 +176,9 @@ local function createCcpm(opts)
if registry.type == 'github' then if registry.type == 'github' then
local branch = registry.branch or 'master'; local branch = registry.branch or 'master';
return 'https://raw.githubusercontent.com/' .. registry.name .. '/' .. branch .. '/'; return 'https://raw.githubusercontent.com/' .. registry.name .. '/' .. branch .. '/';
elseif registry.type == 'gitea' then
local branch = registry.branch or 'master';
return 'https://git.trapcloud.fr/' .. registry.name .. '/raw/branch/' .. branch .. '/';
end end
local base = registry.name; local base = registry.name;
if base:sub(-1) ~= '/' then base = base .. '/'; end if base:sub(-1) ~= '/' then base = base .. '/'; end

View File

@ -53,7 +53,9 @@ To avoid colliding with the OS `manifest.json`, ccpm never uses the word "manife
Local state lives under `/trapos`: Local state lives under `/trapos`:
- `ccpm.json` — ordered registry list `{ registries = { { name, type, branch } } }`. - `ccpm.json` — ordered registry list `{ registries = { { name, type, branch } } }`.
`type` is `github` (resolves to `raw.githubusercontent.com/<name>/<branch>/`) or `type` is `gitea` (resolves to `git.trapcloud.fr/<name>/raw/branch/<branch>/`, the
default seeded by the bootstrap), `github` (resolves to
`raw.githubusercontent.com/<name>/<branch>/`, deprecated but still supported), or
`http`/`https` (the `name` is a base URL). `http`/`https` (the `name` is a base URL).
- `ccpm.lock.json` — installed packages `{ packages = { <name> = { version, registry, - `ccpm.lock.json` — installed packages `{ packages = { <name> = { version, registry,
files, dependencies, autostart } } }`, used by `ls`, `uninstall`, and `reinstall`. files, dependencies, autostart } } }`, used by `ls`, `uninstall`, and `reinstall`.

View File

@ -7,7 +7,7 @@ Follow this order while playing.
On the ComputerCraft computer: On the ComputerCraft computer:
```sh ```sh
wget run https://raw.githubusercontent.com/guillaumearm/cc-libs/next/install-ccpm.lua --beta wget run https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/next/install-ccpm.lua --beta
ccpm update ccpm update
ccpm install trapos ccpm install trapos
``` ```

View File

@ -17,7 +17,7 @@ CC Computer
On a fresh CC computer (beta branch): On a fresh CC computer (beta branch):
``` ```
wget run https://raw.githubusercontent.com/guillaumearm/cc-libs/next/install-ccpm.lua --beta wget run https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/next/install-ccpm.lua --beta
ccpm update ccpm update
ccpm install trapos ccpm install trapos
``` ```

View File

@ -1,6 +1,6 @@
local _VERSION = '5.0.1'; local _VERSION = '5.1.0';
local REPO_BASE = 'https://raw.githubusercontent.com/guillaumearm/cc-libs/'; local REPO_BASE = 'https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/';
local LOCAL_STATE_DIR = '/trapos'; local LOCAL_STATE_DIR = '/trapos';
local LOCAL_MANIFEST_PATH = '/trapos/manifest.json'; local LOCAL_MANIFEST_PATH = '/trapos/manifest.json';
local LOCAL_CONFIG_PATH = '/trapos/ccpm.json'; local LOCAL_CONFIG_PATH = '/trapos/ccpm.json';
@ -113,13 +113,13 @@ local function seedCcpmConfig(branch)
local found = false; local found = false;
for _, r in ipairs(cfg.registries) do for _, r in ipairs(cfg.registries) do
if r.name == DEFAULT_REGISTRY_NAME then if r.name == DEFAULT_REGISTRY_NAME then
r.type = 'github'; r.type = 'gitea';
r.branch = branch; r.branch = branch;
found = true; found = true;
end end
end end
if not found then if not found then
table.insert(cfg.registries, 1, { name = DEFAULT_REGISTRY_NAME, type = 'github', branch = branch }); table.insert(cfg.registries, 1, { name = DEFAULT_REGISTRY_NAME, type = 'gitea', branch = branch });
end end
writeJsonFile(LOCAL_CONFIG_PATH, cfg); writeJsonFile(LOCAL_CONFIG_PATH, cfg);
end end

View File

@ -1,6 +1,6 @@
{ {
"packages": { "packages": {
"trapos-core": "0.4.0", "trapos-core": "0.5.0",
"trapos-test": "0.2.1", "trapos-test": "0.2.1",
"trapos-boot": "0.3.2", "trapos-boot": "0.3.2",
"trapos-net": "0.3.0", "trapos-net": "0.3.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "trapos-core", "name": "trapos-core",
"version": "0.4.0", "version": "0.5.0",
"description": "TrapOS base: package manager, event loop, upgrade and event tools", "description": "TrapOS base: package manager, event loop, upgrade and event tools",
"dependencies": [], "dependencies": [],
"files": [ "files": [

View File

@ -17,7 +17,7 @@ local function printUsage()
print('\t\tccpm search [term]'); print('\t\tccpm search [term]');
print('\t\tccpm info <package>'); print('\t\tccpm info <package>');
print('\t\tccpm registry ls'); print('\t\tccpm registry ls');
print('\t\tccpm registry add <name> [--branch <b>] [--type github|http]'); print('\t\tccpm registry add <name> [--branch <b>] [--type github|gitea|http]');
print('\t\tccpm registry rm <name>'); print('\t\tccpm registry rm <name>');
print('\t\tccpm version'); print('\t\tccpm version');
print('\t\tccpm help'); print('\t\tccpm help');
@ -180,6 +180,8 @@ if command == 'registry' then
for _, r in ipairs(registries) do for _, r in ipairs(registries) do
if r.type == 'github' then if r.type == 'github' then
print(r.name .. ' (github:' .. tostring(r.branch or 'master') .. ')'); print(r.name .. ' (github:' .. tostring(r.branch or 'master') .. ')');
elseif r.type == 'gitea' then
print(r.name .. ' (gitea:' .. tostring(r.branch or 'master') .. ')');
else else
print(r.name .. ' (' .. tostring(r.type or 'http') .. ')'); print(r.name .. ' (' .. tostring(r.type or 'http') .. ')');
end end

View File

@ -33,6 +33,10 @@ local function ghBase(name, branch)
return 'https://raw.githubusercontent.com/' .. name .. '/' .. branch .. '/'; return 'https://raw.githubusercontent.com/' .. name .. '/' .. branch .. '/';
end end
local function giteaBase(name, branch)
return 'https://git.trapcloud.fr/' .. name .. '/raw/branch/' .. branch .. '/';
end
testlib.test('registryBaseUrl resolves a github branch', function() testlib.test('registryBaseUrl resolves a github branch', function()
local ccpm = createCcpm({ stateDir = freshDirs() }); local ccpm = createCcpm({ stateDir = freshDirs() });
testlib.assertEquals( testlib.assertEquals(
@ -41,6 +45,18 @@ testlib.test('registryBaseUrl resolves a github branch', function()
); );
end); end);
testlib.test('registryBaseUrl resolves a gitea branch', function()
local ccpm = createCcpm({ stateDir = freshDirs() });
testlib.assertEquals(
ccpm.registryBaseUrl({ name = 'guillaumearm/cc-libs', type = 'gitea', branch = 'next' }),
'https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/next/'
);
testlib.assertEquals(
ccpm.descriptorUrl({ name = 'guillaumearm/cc-libs', type = 'gitea', branch = 'next' }, 'trapos-net'),
'https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/next/packages/trapos-net/ccpm.json'
);
end);
testlib.test('registry urls resolve an http base', function() testlib.test('registry urls resolve an http base', function()
local ccpm = createCcpm({ stateDir = freshDirs() }); local ccpm = createCcpm({ stateDir = freshDirs() });
testlib.assertEquals( testlib.assertEquals(
@ -128,6 +144,32 @@ testlib.test('install downloads files and records the lock', function()
testlib.assertEquals(lock.packages['trapos-net'].registry, 'me/repo'); testlib.assertEquals(lock.packages['trapos-net'].registry, 'me/repo');
end); end);
testlib.test('install downloads files from a gitea registry', function()
local base = giteaBase('guillaumearm/cc-libs', 'next');
local routes = {
[base .. 'packages/trapos-core/ccpm.json'] = textutils.serializeJSON({ name = 'trapos-core', version = '1', dependencies = {}, files = { 'apis/eventloop.lua' } }),
[base .. 'packages/trapos-net/ccpm.json'] = textutils.serializeJSON({ name = 'trapos-net', version = '1', dependencies = { 'trapos-core' }, files = { 'apis/net.lua' } }),
[base .. 'apis/eventloop.lua'] = 'eventloop-body',
[base .. 'apis/net.lua'] = 'net-body',
};
local sd, root = freshDirs();
local ccpm = createCcpm({ stateDir = sd, installRoot = root, http = fakeHttp(routes) });
ccpm.writeConfig({ registries = { { name = 'guillaumearm/cc-libs', type = 'gitea', branch = 'next' } } });
local ok = ccpm.install('trapos-net', {});
testlib.assertTrue(ok);
testlib.assertTrue(fs.exists(root .. '/apis/net.lua'));
testlib.assertTrue(fs.exists(root .. '/apis/eventloop.lua'));
local f = fs.open(root .. '/apis/net.lua', 'r');
local body = f.readAll();
f.close();
testlib.assertEquals(body, 'net-body');
local lock = ccpm.readLock();
testlib.assertEquals(lock.packages['trapos-net'].registry, 'guillaumearm/cc-libs');
end);
testlib.test('installing trapos writes aggregated os state', function() testlib.test('installing trapos writes aggregated os state', function()
local base = ghBase('me/repo', 'master'); local base = ghBase('me/repo', 'master');
local routes = { local routes = {
@ -171,6 +213,30 @@ testlib.test('registry add and remove round-trip', function()
testlib.assertTrue(not rmOk); testlib.assertTrue(not rmOk);
end); end);
testlib.test('addRegistry defaults to a gitea registry', function()
local ccpm = createCcpm({ stateDir = freshDirs() });
ccpm.writeConfig({ registries = {} });
local ok, registry = ccpm.addRegistry('foo/bar', {});
testlib.assertTrue(ok);
testlib.assertEquals(registry.type, 'gitea');
testlib.assertEquals(registry.branch, 'master');
local regs = ccpm.listRegistries();
testlib.assertEquals(regs[1].type, 'gitea');
-- The default registry must not silently fall back to github.
testlib.assertTrue(regs[1].type ~= 'github');
testlib.assertEquals(
ccpm.registryBaseUrl(regs[1]),
'https://git.trapcloud.fr/foo/bar/raw/branch/master/'
);
-- An explicit type is still honored (github stays supported but opt-in).
testlib.assertTrue(ccpm.addRegistry('legacy/repo', { type = 'github' }));
local legacy = ccpm.listRegistries()[2];
testlib.assertEquals(legacy.type, 'github');
end);
testlib.test('compareVersions treats padded zeros as equal', function() testlib.test('compareVersions treats padded zeros as equal', function()
-- compareVersions is internal; probe via available() status -- compareVersions is internal; probe via available() status
local ccpm = createCcpm({ stateDir = freshDirs() }); local ccpm = createCcpm({ stateDir = freshDirs() });

View File

@ -56,7 +56,7 @@ testlib.test('fresh beta bootstrap leaves ccpm runnable without trapos-boot', fu
fs.delete(root); fs.delete(root);
fs.makeDir(root); fs.makeDir(root);
local base = 'https://raw.githubusercontent.com/guillaumearm/cc-libs/next/'; local base = 'https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/next/';
local routes = { local routes = {
[base .. 'manifest.json'] = textutils.serializeJSON({ name = 'TrapOS', version = 'test' }), [base .. 'manifest.json'] = textutils.serializeJSON({ name = 'TrapOS', version = 'test' }),
[base .. 'packages/trapos-core/ccpm.json'] = textutils.serializeJSON({ [base .. 'packages/trapos-core/ccpm.json'] = textutils.serializeJSON({
@ -115,6 +115,7 @@ testlib.test('fresh beta bootstrap leaves ccpm runnable without trapos-boot', fu
local config = textutils.unserializeJSON(f.readAll()); local config = textutils.unserializeJSON(f.readAll());
f.close(); f.close();
testlib.assertEquals(config.registries[1].branch, 'next'); testlib.assertEquals(config.registries[1].branch, 'next');
testlib.assertEquals(config.registries[1].type, 'gitea');
end); end);
testlib.run(); testlib.run();