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`.
- 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).
- `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.
- 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:
```
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:
@ -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):
```
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.
@ -56,7 +56,7 @@ ccpm install <package> ccpm reinstall <package> ccpm uninstall <package>
ccpm update ccpm upgrade
ccpm ls ccpm available [term] ccpm search [term]
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>
```

View File

@ -85,7 +85,7 @@ local function createCcpm(opts)
end
local registry = {
name = name,
type = registryOpts.type or 'github',
type = registryOpts.type or 'gitea',
branch = registryOpts.branch or 'master',
};
cfg.registries[#cfg.registries + 1] = registry;
@ -176,6 +176,9 @@ local function createCcpm(opts)
if registry.type == 'github' then
local branch = registry.branch or 'master';
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
local base = registry.name;
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`:
- `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).
- `ccpm.lock.json` — installed packages `{ packages = { <name> = { version, registry,
files, dependencies, autostart } } }`, used by `ls`, `uninstall`, and `reinstall`.

View File

@ -7,7 +7,7 @@ Follow this order while playing.
On the ComputerCraft computer:
```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 install trapos
```

View File

@ -17,7 +17,7 @@ CC Computer
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 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_MANIFEST_PATH = '/trapos/manifest.json';
local LOCAL_CONFIG_PATH = '/trapos/ccpm.json';
@ -113,13 +113,13 @@ local function seedCcpmConfig(branch)
local found = false;
for _, r in ipairs(cfg.registries) do
if r.name == DEFAULT_REGISTRY_NAME then
r.type = 'github';
r.type = 'gitea';
r.branch = branch;
found = true;
end
end
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
writeJsonFile(LOCAL_CONFIG_PATH, cfg);
end

View File

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

View File

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

View File

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

View File

@ -33,6 +33,10 @@ local function ghBase(name, branch)
return 'https://raw.githubusercontent.com/' .. name .. '/' .. branch .. '/';
end
local function giteaBase(name, branch)
return 'https://git.trapcloud.fr/' .. name .. '/raw/branch/' .. branch .. '/';
end
testlib.test('registryBaseUrl resolves a github branch', function()
local ccpm = createCcpm({ stateDir = freshDirs() });
testlib.assertEquals(
@ -41,6 +45,18 @@ testlib.test('registryBaseUrl resolves a github branch', function()
);
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()
local ccpm = createCcpm({ stateDir = freshDirs() });
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');
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()
local base = ghBase('me/repo', 'master');
local routes = {
@ -171,6 +213,30 @@ testlib.test('registry add and remove round-trip', function()
testlib.assertTrue(not rmOk);
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()
-- compareVersions is internal; probe via available() status
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.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 = {
[base .. 'manifest.json'] = textutils.serializeJSON({ name = 'TrapOS', version = 'test' }),
[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());
f.close();
testlib.assertEquals(config.registries[1].branch, 'next');
testlib.assertEquals(config.registries[1].type, 'gitea');
end);
testlib.run();