feat(installer): install full trapos by default
This commit is contained in:
parent
f8e15d2267
commit
e10a1d5976
@ -37,13 +37,13 @@ Use [`docs/README.md`](docs/README.md) as the entrypoint for CC:Tweaked, CraftOS
|
|||||||
- 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.
|
||||||
- Global CraftOS-PC save data lives in `~/Library/Application Support/CraftOS-PC` on macOS and `~/.local/share/craftos-pc` on Linux. Repo launchers use local state instead: `.craftos/` for TrapOS and `.craftos-vanilla/` for vanilla CraftOS-PC. See [`docs/install-craftos-pc.md`](docs/install-craftos-pc.md).
|
- Global CraftOS-PC save data lives in `~/Library/Application Support/CraftOS-PC` on macOS and `~/.local/share/craftos-pc` on Linux. Repo launchers use local state instead: `.craftos/` for TrapOS and `.craftos-vanilla/` for vanilla CraftOS-PC. See [`docs/install-craftos-pc.md`](docs/install-craftos-pc.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).
|
- 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 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.
|
- `install-trapos.lua` is the one-time wget bootstrap (public entry point `https://trapos.trapcloud.fr/install`). It installs `trapos-core`/`ccpm`, seeds the default `guillaumearm/cc-libs` registry as a `gitea` registry on `git.trapcloud.fr` tracking `master` (the only channel), then runs `ccpm update` + `ccpm install trapos` and `trapos-postinstall`. Pass `--cpm-only` to stop after the ccpm bootstrap. 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.
|
||||||
|
|
||||||
## Conventions
|
## Conventions
|
||||||
|
|
||||||
- Bump the owning `packages/<name>/ccpm.json` version (and mirror it in `packages/index.json`) when changing module behavior; programs report it at runtime via `require('/apis/libversion')().forSelf()`. `install-ccpm.lua` is the only file that still carries its own `_VERSION` because it is the wget bootstrap and lives outside the package system.
|
- Bump the owning `packages/<name>/ccpm.json` version (and mirror it in `packages/index.json`) when changing module behavior; programs report it at runtime via `require('/apis/libversion')().forSelf()`. `install-trapos.lua` is the only file that still carries its own `_VERSION` because it is the wget bootstrap and lives outside the package system.
|
||||||
- Programs support `-version`/`--version` and `-help`/`--help`; router also supports `-silent`/`--silent`.
|
- Programs support `-version`/`--version` and `-help`/`--help`; router also supports `-silent`/`--silent`.
|
||||||
- French or English comments are fine; match surrounding code.
|
- French or English comments are fine; match surrounding code.
|
||||||
- Commit messages use lightweight conventional style: `topic(scope): description` or `topic: description`.
|
- Commit messages use lightweight conventional style: `topic(scope): description` or `topic: description`.
|
||||||
|
|||||||
42
README.md
42
README.md
@ -4,52 +4,47 @@ A small in-game operating system for ComputerCraft / CC:Tweaked, built around a
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Install `ccpm` first. This is the only step that needs `wget` with a URL:
|
One command installs everything — it bootstraps `ccpm`, syncs the default
|
||||||
|
registry (`guillaumearm/cc-libs`), and installs the full TrapOS:
|
||||||
```
|
```
|
||||||
wget run https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/master/install-ccpm.lua
|
wget run https://trapos.trapcloud.fr/install
|
||||||
```
|
```
|
||||||
|
|
||||||
Then sync the default registry (`guillaumearm/cc-libs`) and install TrapOS:
|
When it finishes, run `sandbox --help` to get started, or `trapos-upgrade` to
|
||||||
|
update later.
|
||||||
|
|
||||||
|
Install only the package manager (no full OS) with `--cpm-only`, then
|
||||||
|
cherry-pick packages yourself:
|
||||||
```
|
```
|
||||||
|
wget run https://trapos.trapcloud.fr/install --cpm-only
|
||||||
ccpm update
|
ccpm update
|
||||||
ccpm install trapos
|
ccpm install trapos-net
|
||||||
|
ccpm install trapos-ui
|
||||||
```
|
```
|
||||||
|
|
||||||
Install individual packages instead if you want to cherry-pick:
|
After install, every boot shows a colored MOTD with the installed version.
|
||||||
```
|
|
||||||
> ccpm install trapos-net
|
|
||||||
> ccpm install trapos-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
Install `ccpm` from the beta branch (one-time opt-in, asks for confirmation):
|
|
||||||
```
|
|
||||||
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.
|
|
||||||
|
|
||||||
After install, every boot shows a colored MOTD with the installed version and branch (lime for stable, orange + `[BETA]` for beta).
|
|
||||||
|
|
||||||
## Packages
|
## Packages
|
||||||
|
|
||||||
TrapOS is split into packages, each described by a `packages/<name>/ccpm.json`:
|
TrapOS is split into packages, each described by a `packages/<name>/ccpm.json`:
|
||||||
|
|
||||||
- `trapos-core`: the package manager (`ccpm`), event loop, `upgrade`, `events`.
|
- `trapos-core`: the package manager (`ccpm`), event loop, `trapos-upgrade`, `trapos-postinstall`, `events`.
|
||||||
- `trapos-test`: the test framework (`libtest`) and suite runner (`runtest`).
|
- `trapos-test`: the test framework (`libtest`) and suite runner (`runtest`).
|
||||||
- `trapos-boot`: the startup MOTD and autostart server launcher.
|
- `trapos-boot`: the startup MOTD and autostart server launcher.
|
||||||
- `trapos-net`: routed modem networking (`net`, `router`, `ping`, `ping-server`).
|
- `trapos-net`: routed modem networking (`net`, `router`, `ping`, `ping-server`).
|
||||||
- `trapos-ui`: the terminal UI toolkit (`libtui`, `tuidemo`).
|
- `trapos-ui`: the terminal UI toolkit (`libtui`, `tuidemo`).
|
||||||
- `trapos-ai`: the AI client for `opencode serve`.
|
- `trapos-ai`: the AI client for `opencode serve`.
|
||||||
- `trapos`: full TrapOS meta-package (`trapos-boot`, `trapos-net`, `trapos-ui`, `trapos-test`, and `trapos-ai` during beta).
|
- `trapos`: full TrapOS meta-package (`trapos-boot`, `trapos-net`, `trapos-ui`, `trapos-test`, `trapos-ai`, `trapos-sandbox`).
|
||||||
|
|
||||||
The `trapos` meta-package is the user-facing full install. Package descriptors list
|
The `trapos` meta-package is the user-facing full install. Package descriptors list
|
||||||
files and autostart servers; installed state is tracked under `/trapos`.
|
files and autostart servers; installed state is tracked under `/trapos`.
|
||||||
|
|
||||||
## ccpm
|
## ccpm
|
||||||
|
|
||||||
`ccpm` is the TrapOS package manager. `install-ccpm.lua` installs it by installing
|
`ccpm` is the TrapOS package manager. `install-trapos.lua` installs it by installing
|
||||||
the required `trapos-core` package and configures the default registry
|
the required `trapos-core` package and configures the default registry
|
||||||
(`guillaumearm/cc-libs`).
|
(`guillaumearm/cc-libs`), then (unless `--cpm-only`) installs the full `trapos`
|
||||||
|
meta-package.
|
||||||
|
|
||||||
```
|
```
|
||||||
ccpm install <package> ccpm reinstall <package> ccpm uninstall <package>
|
ccpm install <package> ccpm reinstall <package> ccpm uninstall <package>
|
||||||
@ -82,7 +77,8 @@ Servers listed in `manifest.autostart` are launched at boot by `startup/servers.
|
|||||||
- `router`: routes messages. You need to set up a router to use all `apis/net`-based programs and libraries.
|
- `router`: routes messages. You need to set up a router to use all `apis/net`-based programs and libraries.
|
||||||
- `ping`: pings machines using `apis/net`.
|
- `ping`: pings machines using `apis/net`.
|
||||||
- `events`: emits and logs computer events.
|
- `events`: emits and logs computer events.
|
||||||
- `upgrade`: alias for `ccpm upgrade`.
|
- `trapos-upgrade`: runs `ccpm update` then `ccpm upgrade`; pass `--reboot`/`-r` to reboot after upgrading.
|
||||||
|
- `trapos-postinstall`: prints the post-install welcome and next steps (run automatically by the installer).
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
See [DEVELOPMENT.md](./DEVELOPMENT.md) for local development installation.
|
See [DEVELOPMENT.md](./DEVELOPMENT.md) for local development installation.
|
||||||
|
|||||||
@ -56,7 +56,7 @@ Two safe-exec recipes wrap raw `--headless --exec` with `xpcall`, call `os.shutd
|
|||||||
|
|
||||||
- `just craftos-exec '<lua>'` — probe against **vanilla CraftOS-PC**. No mounts, no startup scripts. Use this when the question is purely about CC:Tweaked behavior and TrapOS files would be a distraction, or to confirm a behavior is upstream rather than something the dev env layered on.
|
- `just craftos-exec '<lua>'` — probe against **vanilla CraftOS-PC**. No mounts, no startup scripts. Use this when the question is purely about CC:Tweaked behavior and TrapOS files would be a distraction, or to confirm a behavior is upstream rather than something the dev env layered on.
|
||||||
|
|
||||||
- `just trapos-install` — drive the full real install (`install-ccpm.lua` → `ccpm update` → `ccpm install trapos`) on a fresh ephemeral state. This is the probe to run when changing anything in the install path itself.
|
- `just trapos-install` — drive the full real install (`install-trapos.lua`, which bootstraps ccpm then runs `ccpm update` + `ccpm install trapos` itself) on a fresh ephemeral state. This is the probe to run when changing anything in the install path itself.
|
||||||
|
|
||||||
Conventions:
|
Conventions:
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ Conventions:
|
|||||||
- `just repl` is a human-only interactive wrapper around `just trapos --cli`; automation and LLM agents must use `just trapos-exec '<lua>'` or `just craftos-exec '<lua>'` instead.
|
- `just repl` is a human-only interactive wrapper around `just trapos --cli`; automation and LLM agents must use `just trapos-exec '<lua>'` or `just craftos-exec '<lua>'` instead.
|
||||||
- `craftos` (GUI) now opens a single unlabelled `Computer 0` window with a top modem attached. Cross-machine testing requires an explicit `periphemu create` call from the shell rather than being implicit on boot — one extra command when you need a peer, no surprise windows or persisted ghost VMs.
|
- `craftos` (GUI) now opens a single unlabelled `Computer 0` window with a top modem attached. Cross-machine testing requires an explicit `periphemu create` call from the shell rather than being implicit on boot — one extra command when you need a peer, no surprise windows or persisted ghost VMs.
|
||||||
- `.craftos-vanilla/` is in `.gitignore` alongside `.craftos/`.
|
- `.craftos-vanilla/` is in `.gitignore` alongside `.craftos/`.
|
||||||
- `just trapos-install` is *not* part of `just ci`: it is network-dependent and slower than `just test`. Run it manually when touching `install-ccpm.lua` or ccpm package descriptors.
|
- `just trapos-install` is *not* part of `just ci`: it is network-dependent and slower than `just test`. Run it manually when touching `install-trapos.lua` or ccpm package descriptors.
|
||||||
- Higher CraftOS-PC invocation traffic during agent sessions; cheap enough that this is a good trade.
|
- Higher CraftOS-PC invocation traffic during agent sessions; cheap enough that this is a good trade.
|
||||||
- The harness version becomes a project-level concern. When CC:Tweaked ships breaking changes that require a newer CraftOS-PC build, we bump the minimum version in [`docs/install-craftos-pc.md`](../install-craftos-pc.md) and `check-craftos` keeps contributors honest.
|
- The harness version becomes a project-level concern. When CC:Tweaked ships breaking changes that require a newer CraftOS-PC build, we bump the minimum version in [`docs/install-craftos-pc.md`](../install-craftos-pc.md) and `check-craftos` keeps contributors honest.
|
||||||
- No CI integration yet. Running CraftOS-PC headless in GitHub Actions is feasible (the AppImage works on Ubuntu runners) but is out of scope; the contract is local-only for now.
|
- No CI integration yet. Running CraftOS-PC headless in GitHub Actions is feasible (the AppImage works on Ubuntu runners) but is out of scope; the contract is local-only for now.
|
||||||
|
|||||||
@ -8,6 +8,19 @@ Accepted
|
|||||||
|
|
||||||
2026-06-08
|
2026-06-08
|
||||||
|
|
||||||
|
## Update (2026-06-15)
|
||||||
|
|
||||||
|
The beta/stable two-channel model has been retired now that `next` is merged into
|
||||||
|
`master`: `master` is the only channel. The `wget` bootstrap is renamed
|
||||||
|
`install-ccpm.lua` → `install-trapos.lua` (public entry point
|
||||||
|
`https://trapos.trapcloud.fr/install`) and now installs the **full OS** in one shot —
|
||||||
|
it bootstraps `ccpm`, then runs `ccpm update` + `ccpm install trapos` and a
|
||||||
|
`trapos-postinstall` welcome. Pass `--cpm-only` to stop after the ccpm bootstrap. The
|
||||||
|
persisted `branch` field is always `master`; the `--beta` opt-in and its confirmation
|
||||||
|
prompt are gone. The `upgrade` program is replaced by `trapos-upgrade` (`ccpm update` +
|
||||||
|
`ccpm upgrade`, with `--reboot`/`-r`). References to `--beta`/`install-ccpm.lua` below
|
||||||
|
are retained as historical context.
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
The previous install flow (a `LIST_FILES` table inside `install.lua` and a single flat
|
The previous install flow (a `LIST_FILES` table inside `install.lua` and a single flat
|
||||||
|
|||||||
@ -7,9 +7,7 @@ Follow this order while playing.
|
|||||||
On the ComputerCraft computer:
|
On the ComputerCraft computer:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
wget run https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/next/install-ccpm.lua --beta
|
wget run https://trapos.trapcloud.fr/install
|
||||||
ccpm update
|
|
||||||
ccpm install trapos
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If the computer asks to reboot, reboot it.
|
If the computer asks to reboot, reboot it.
|
||||||
|
|||||||
@ -90,7 +90,7 @@ On macOS, use the `--rom` form shown above if the command fails with `Could not
|
|||||||
|
|
||||||
`just craftos` launches a vanilla CraftOS-PC with no mounts, persistent under `.craftos-vanilla/` (also gitignored). Use it when a probe should not see TrapOS files — for example, to confirm a behavior is upstream rather than TrapOS-specific.
|
`just craftos` launches a vanilla CraftOS-PC with no mounts, persistent under `.craftos-vanilla/` (also gitignored). Use it when a probe should not see TrapOS files — for example, to confirm a behavior is upstream rather than TrapOS-specific.
|
||||||
|
|
||||||
`just trapos-install` exercises the real ccpm bootstrap (`install-ccpm.lua` → `ccpm update` → `ccpm install trapos`) end-to-end on a fresh, ephemeral CraftOS-PC state. Network-dependent and slower than `just test`, so not part of `just ci`. Override the watchdog with `TRAP_CCLIBS_INSTALL_TIMEOUT_SECONDS` (default `60`).
|
`just trapos-install` exercises the real one-shot installer (`install-trapos.lua`, which bootstraps ccpm then runs `ccpm update` + `ccpm install trapos`) end-to-end on a fresh, ephemeral CraftOS-PC state. Network-dependent and slower than `just test`, so not part of `just ci`. Override the watchdog with `TRAP_CCLIBS_INSTALL_TIMEOUT_SECONDS` (default `60`).
|
||||||
|
|
||||||
For automated probes, use the safe wrappers. They mount the right environment,
|
For automated probes, use the safe wrappers. They mount the right environment,
|
||||||
shut down the machine after completion or Lua errors, and kill the host process
|
shut down the machine after completion or Lua errors, and kill the host process
|
||||||
|
|||||||
@ -14,12 +14,10 @@ CC Computer
|
|||||||
|
|
||||||
## 0. Install TrapOS and the AI package
|
## 0. Install TrapOS and the AI package
|
||||||
|
|
||||||
On a fresh CC computer (beta branch):
|
On a fresh CC computer:
|
||||||
|
|
||||||
```
|
```
|
||||||
wget run https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/next/install-ccpm.lua --beta
|
wget run https://trapos.trapcloud.fr/install
|
||||||
ccpm update
|
|
||||||
ccpm install trapos
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 1. Start `opencode serve`
|
## 1. Start `opencode serve`
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
local _VERSION = '5.1.0';
|
local _VERSION = '6.0.0';
|
||||||
|
|
||||||
local REPO_BASE = 'https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/';
|
local REPO_BASE = 'https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/master/';
|
||||||
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';
|
||||||
local LOCAL_LOCK_PATH = '/trapos/ccpm.lock.json';
|
local LOCAL_LOCK_PATH = '/trapos/ccpm.lock.json';
|
||||||
local DEFAULT_REGISTRY_NAME = 'guillaumearm/cc-libs';
|
local DEFAULT_REGISTRY_NAME = 'guillaumearm/cc-libs';
|
||||||
|
local INSTALL_BRANCH = 'master';
|
||||||
|
|
||||||
local function printUsage()
|
local function printUsage()
|
||||||
print('install-ccpm usage:');
|
print('install-trapos usage:');
|
||||||
print();
|
print();
|
||||||
print('\t\twget run <install-url>');
|
print('\t\twget run <install-url>');
|
||||||
print('\t\twget run <install-url> --beta');
|
print('\t\twget run <install-url> --cpm-only');
|
||||||
print('\t\twget run <install-url> --stable');
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readJsonFile(path)
|
local function readJsonFile(path)
|
||||||
@ -34,17 +34,6 @@ local function writeJsonFile(path, value)
|
|||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
local function confirmBeta()
|
|
||||||
print();
|
|
||||||
print('You are about to install the BETA branch (next).');
|
|
||||||
print('Beta builds may be unstable. Continue? (y/N)');
|
|
||||||
write('> ');
|
|
||||||
local answer = read();
|
|
||||||
if not answer then return false; end
|
|
||||||
answer = answer:lower();
|
|
||||||
return answer == 'y' or answer == 'yes';
|
|
||||||
end
|
|
||||||
|
|
||||||
local function fetchJson(url)
|
local function fetchJson(url)
|
||||||
local response = http.get(url);
|
local response = http.get(url);
|
||||||
if not response then return nil end
|
if not response then return nil end
|
||||||
@ -54,12 +43,12 @@ local function fetchJson(url)
|
|||||||
return textutils.unserializeJSON(body);
|
return textutils.unserializeJSON(body);
|
||||||
end
|
end
|
||||||
|
|
||||||
local function fetchManifest(branch)
|
local function fetchManifest()
|
||||||
return fetchJson(REPO_BASE .. branch .. '/manifest.json');
|
return fetchJson(REPO_BASE .. 'manifest.json');
|
||||||
end
|
end
|
||||||
|
|
||||||
local function fetchDescriptor(branch, pkg)
|
local function fetchDescriptor(pkg)
|
||||||
return fetchJson(REPO_BASE .. branch .. '/packages/' .. pkg .. '/ccpm.json');
|
return fetchJson(REPO_BASE .. 'packages/' .. pkg .. '/ccpm.json');
|
||||||
end
|
end
|
||||||
|
|
||||||
local function ensureProgramsPath()
|
local function ensureProgramsPath()
|
||||||
@ -76,7 +65,7 @@ end
|
|||||||
|
|
||||||
-- Resolve a list of package names + their dependencies into install order
|
-- Resolve a list of package names + their dependencies into install order
|
||||||
-- (deps first). Returns an ordered list of descriptors or nil, err.
|
-- (deps first). Returns an ordered list of descriptors or nil, err.
|
||||||
local function resolvePackages(branch, names)
|
local function resolvePackages(names)
|
||||||
local ordered = {};
|
local ordered = {};
|
||||||
local state = {}; -- name -> 'visiting' | 'done'
|
local state = {}; -- name -> 'visiting' | 'done'
|
||||||
|
|
||||||
@ -86,7 +75,7 @@ local function resolvePackages(branch, names)
|
|||||||
return false, 'dependency cycle detected at ' .. name;
|
return false, 'dependency cycle detected at ' .. name;
|
||||||
end
|
end
|
||||||
state[name] = 'visiting';
|
state[name] = 'visiting';
|
||||||
local desc = fetchDescriptor(branch, name);
|
local desc = fetchDescriptor(name);
|
||||||
if not desc then
|
if not desc then
|
||||||
return false, 'package not found: ' .. name;
|
return false, 'package not found: ' .. name;
|
||||||
end
|
end
|
||||||
@ -107,79 +96,57 @@ local function resolvePackages(branch, names)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Seed/refresh the default ccpm registry so it tracks the install branch.
|
-- Seed/refresh the default ccpm registry so it tracks the install branch.
|
||||||
local function seedCcpmConfig(branch)
|
local function seedCcpmConfig()
|
||||||
local cfg = readJsonFile(LOCAL_CONFIG_PATH) or { registries = {} };
|
local cfg = readJsonFile(LOCAL_CONFIG_PATH) or { registries = {} };
|
||||||
cfg.registries = cfg.registries or {};
|
cfg.registries = cfg.registries or {};
|
||||||
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 = 'gitea';
|
r.type = 'gitea';
|
||||||
r.branch = branch;
|
r.branch = INSTALL_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 = 'gitea', branch = branch });
|
table.insert(cfg.registries, 1, { name = DEFAULT_REGISTRY_NAME, type = 'gitea', branch = INSTALL_BRANCH });
|
||||||
end
|
end
|
||||||
writeJsonFile(LOCAL_CONFIG_PATH, cfg);
|
writeJsonFile(LOCAL_CONFIG_PATH, cfg);
|
||||||
end
|
end
|
||||||
|
|
||||||
local rawArgs = table.pack(...);
|
local rawArgs = table.pack(...);
|
||||||
local forceBeta, forceStable = false, false;
|
local cpmOnly = false;
|
||||||
|
|
||||||
for i = 1, rawArgs.n do
|
for i = 1, rawArgs.n do
|
||||||
local a = rawArgs[i];
|
local a = rawArgs[i];
|
||||||
if a == 'version' or a == '-version' or a == '--version' then
|
if a == 'version' or a == '-version' or a == '--version' then
|
||||||
print('install-ccpm v' .. _VERSION);
|
print('install-trapos v' .. _VERSION);
|
||||||
return;
|
return;
|
||||||
elseif a == 'help' or a == '-help' or a == '--help' then
|
elseif a == 'help' or a == '-help' or a == '--help' then
|
||||||
printUsage();
|
printUsage();
|
||||||
return;
|
return;
|
||||||
elseif a == '--beta' or a == '-beta' then
|
elseif a == '--cpm-only' or a == '-cpm-only' then
|
||||||
forceBeta = true;
|
cpmOnly = true;
|
||||||
elseif a == '--stable' or a == '-stable' then
|
|
||||||
forceStable = true;
|
|
||||||
elseif a ~= nil and a ~= '' then
|
elseif a ~= nil and a ~= '' then
|
||||||
printUsage();
|
printUsage();
|
||||||
return;
|
return;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local localManifest = readJsonFile(LOCAL_MANIFEST_PATH);
|
print('Fetching manifest from branch: ' .. INSTALL_BRANCH);
|
||||||
local localBranch = localManifest and localManifest.branch or nil;
|
local manifest = fetchManifest();
|
||||||
local branch;
|
|
||||||
|
|
||||||
if forceBeta then
|
|
||||||
branch = 'next';
|
|
||||||
if localBranch ~= 'next' then
|
|
||||||
if not confirmBeta() then
|
|
||||||
print('Aborted.');
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif forceStable then
|
|
||||||
branch = 'master';
|
|
||||||
else
|
|
||||||
branch = localBranch or 'master';
|
|
||||||
end
|
|
||||||
|
|
||||||
print('Fetching manifest from branch: ' .. branch);
|
|
||||||
local manifest = fetchManifest(branch);
|
|
||||||
if not manifest then
|
if not manifest then
|
||||||
print('Failed to fetch or parse manifest.json from ' .. branch);
|
print('Failed to fetch or parse manifest.json from ' .. INSTALL_BRANCH);
|
||||||
return;
|
return;
|
||||||
end
|
end
|
||||||
|
|
||||||
local requested = { 'trapos-core' };
|
local requested = { 'trapos-core' };
|
||||||
|
|
||||||
local resolved, resolveErr = resolvePackages(branch, requested);
|
local resolved, resolveErr = resolvePackages(requested);
|
||||||
if not resolved then
|
if not resolved then
|
||||||
print('Failed to resolve packages: ' .. resolveErr);
|
print('Failed to resolve packages: ' .. resolveErr);
|
||||||
return;
|
return;
|
||||||
end
|
end
|
||||||
|
|
||||||
local REPO_PREFIX = REPO_BASE .. branch .. '/';
|
|
||||||
|
|
||||||
-- Legacy file cleanup (pre-manifest installs).
|
-- Legacy file cleanup (pre-manifest installs).
|
||||||
fs.delete('ping-server.lua');
|
fs.delete('ping-server.lua');
|
||||||
fs.delete('ping.lua');
|
fs.delete('ping.lua');
|
||||||
@ -212,7 +179,7 @@ for _, desc in ipairs(resolved) do
|
|||||||
seenFile[filePath] = true;
|
seenFile[filePath] = true;
|
||||||
allFiles[#allFiles + 1] = filePath;
|
allFiles[#allFiles + 1] = filePath;
|
||||||
fs.delete(filePath);
|
fs.delete(filePath);
|
||||||
shell.execute('wget', REPO_PREFIX .. filePath, filePath);
|
shell.execute('wget', REPO_BASE .. filePath, filePath);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for _, srv in ipairs(desc.autostart or {}) do
|
for _, srv in ipairs(desc.autostart or {}) do
|
||||||
@ -234,22 +201,34 @@ end
|
|||||||
writeJsonFile(LOCAL_MANIFEST_PATH, {
|
writeJsonFile(LOCAL_MANIFEST_PATH, {
|
||||||
name = manifest.name or 'TrapOS',
|
name = manifest.name or 'TrapOS',
|
||||||
version = manifest.version or '?',
|
version = manifest.version or '?',
|
||||||
branch = branch,
|
branch = INSTALL_BRANCH,
|
||||||
files = allFiles,
|
files = allFiles,
|
||||||
autostart = autostart,
|
autostart = autostart,
|
||||||
});
|
});
|
||||||
|
|
||||||
writeJsonFile(LOCAL_LOCK_PATH, { packages = lockPackages });
|
writeJsonFile(LOCAL_LOCK_PATH, { packages = lockPackages });
|
||||||
seedCcpmConfig(branch);
|
seedCcpmConfig();
|
||||||
ensureProgramsPath();
|
ensureProgramsPath();
|
||||||
|
|
||||||
print();
|
print();
|
||||||
print('=> ccpm installed (branch: ' .. branch .. ')');
|
print('=> ccpm installed (branch: ' .. INSTALL_BRANCH .. ')');
|
||||||
print('=> Default registry: ' .. DEFAULT_REGISTRY_NAME);
|
print('=> Default registry: ' .. DEFAULT_REGISTRY_NAME);
|
||||||
print('=> Run: ccpm update');
|
|
||||||
print('=> Run: ccpm install trapos');
|
if cpmOnly then
|
||||||
|
print('=> Run: ccpm update');
|
||||||
|
print('=> Run: ccpm install trapos');
|
||||||
|
shell.setDir(previousDir);
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Full install: sync the registry and install the TrapOS meta-package.
|
||||||
|
shell.execute('ccpm', 'update');
|
||||||
|
shell.execute('ccpm', 'install', 'trapos');
|
||||||
|
|
||||||
if fs.exists('/startup/servers.lua') then
|
if fs.exists('/startup/servers.lua') then
|
||||||
shell.execute('/startup/servers.lua');
|
shell.execute('/startup/servers.lua');
|
||||||
end
|
end
|
||||||
|
|
||||||
|
shell.execute('trapos-postinstall');
|
||||||
|
|
||||||
shell.setDir(previousDir);
|
shell.setDir(previousDir);
|
||||||
@ -177,11 +177,10 @@ craftos-exec code:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# End-to-end install probe: drive the real ccpm bootstrap
|
# End-to-end install probe: drive the real one-shot installer
|
||||||
# (install-ccpm.lua -> `ccpm update` -> `ccpm install trapos`) on a fresh,
|
# (install-trapos.lua, which bootstraps ccpm then runs `ccpm update` +
|
||||||
# ephemeral CraftOS-PC state. Reflects the currently checked-out git branch:
|
# `ccpm install trapos` itself) on a fresh, ephemeral CraftOS-PC state.
|
||||||
# `master` -> --stable, `next` -> --beta (confirmation stubbed). Other
|
# Always installs from the published `master` branch (the only channel).
|
||||||
# branches are rejected because install-ccpm only knows master/next.
|
|
||||||
# Network-dependent and slower than `just test`, so not part of `just ci`.
|
# Network-dependent and slower than `just test`, so not part of `just ci`.
|
||||||
# Override timeout with TRAP_CCLIBS_INSTALL_TIMEOUT_SECONDS (default 60).
|
# Override timeout with TRAP_CCLIBS_INSTALL_TIMEOUT_SECONDS (default 60).
|
||||||
# See ADR-0005.
|
# See ADR-0005.
|
||||||
@ -191,31 +190,15 @@ trapos-install: check-install
|
|||||||
repo='{{justfile_directory()}}'
|
repo='{{justfile_directory()}}'
|
||||||
timeout_seconds="${TRAP_CCLIBS_INSTALL_TIMEOUT_SECONDS:-60}"
|
timeout_seconds="${TRAP_CCLIBS_INSTALL_TIMEOUT_SECONDS:-60}"
|
||||||
case "$timeout_seconds" in ''|*[!0-9]*) printf '%s\n' 'TRAP_CCLIBS_INSTALL_TIMEOUT_SECONDS must be a positive integer' >&2; exit 1 ;; esac
|
case "$timeout_seconds" in ''|*[!0-9]*) printf '%s\n' 'TRAP_CCLIBS_INSTALL_TIMEOUT_SECONDS must be a positive integer' >&2; exit 1 ;; esac
|
||||||
branch="$(git -C "$repo" rev-parse --abbrev-ref HEAD 2>/dev/null || echo '')"
|
|
||||||
case "$branch" in
|
|
||||||
master)
|
|
||||||
install_flag='--stable'
|
|
||||||
stub_read=''
|
|
||||||
;;
|
|
||||||
next)
|
|
||||||
install_flag='--beta'
|
|
||||||
stub_read="_G.read = function() return 'y' end; "
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
printf '%s\n' "trapos-install only supports the master or next branch (current: ${branch:-unknown}). install-ccpm.lua does not accept other branches." >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
printf '%s\n' "trapos-install: branch=$branch flag=$install_flag"
|
|
||||||
rom_arg=()
|
rom_arg=()
|
||||||
if [ "$(uname -s)" = "Darwin" ]; then
|
if [ "$(uname -s)" = "Darwin" ]; then
|
||||||
rom_arg=(--rom /Applications/CraftOS-PC.app/Contents/Resources)
|
rom_arg=(--rom /Applications/CraftOS-PC.app/Contents/Resources)
|
||||||
fi
|
fi
|
||||||
data_dir="$(mktemp -d)"
|
data_dir="$(mktemp -d)"
|
||||||
stage_dir="$(mktemp -d)"
|
stage_dir="$(mktemp -d)"
|
||||||
cp "$repo/install-ccpm.lua" "$stage_dir/install-ccpm.lua"
|
cp "$repo/install-trapos.lua" "$stage_dir/install-trapos.lua"
|
||||||
tmp="$(mktemp)"
|
tmp="$(mktemp)"
|
||||||
exec_code="${stub_read}shell.run('/staging/install-ccpm', '$install_flag'); shell.run('/programs/ccpm', 'update'); local ok = shell.run('/programs/ccpm', 'install', 'trapos'); if ok then print('__TRAPOS_INSTALL_OK__') end; os.shutdown()"
|
exec_code="shell.run('/staging/install-trapos'); if fs.exists('/trapos/manifest.json') and fs.exists('/trapos/ccpm.lock.json') then print('__TRAPOS_INSTALL_OK__') end; os.shutdown()"
|
||||||
craftos --directory "$data_dir" --headless "${rom_arg[@]}" --mount-ro "/staging=$stage_dir" --exec "$exec_code" >"$tmp" 2>&1 &
|
craftos --directory "$data_dir" --headless "${rom_arg[@]}" --mount-ro "/staging=$stage_dir" --exec "$exec_code" >"$tmp" 2>&1 &
|
||||||
pid="$!"
|
pid="$!"
|
||||||
( sleep "$timeout_seconds"; kill -TERM "$pid" >/dev/null 2>&1 ) &
|
( sleep "$timeout_seconds"; kill -TERM "$pid" >/dev/null 2>&1 ) &
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "TrapOS",
|
"name": "TrapOS",
|
||||||
"version": "0.9.3",
|
"version": "0.9.3",
|
||||||
"branch": "next",
|
"branch": "master",
|
||||||
"packages": [
|
"packages": [
|
||||||
"trapos"
|
"trapos"
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"packages": {
|
"packages": {
|
||||||
"trapos-core": "0.5.1",
|
"trapos-core": "0.6.0",
|
||||||
"trapos-test": "0.2.1",
|
"trapos-test": "0.2.1",
|
||||||
"trapos-boot": "0.3.3",
|
"trapos-boot": "0.3.3",
|
||||||
"trapos-net": "0.3.0",
|
"trapos-net": "0.3.0",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "trapos-core",
|
"name": "trapos-core",
|
||||||
"version": "0.5.1",
|
"version": "0.6.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": [
|
||||||
@ -8,7 +8,8 @@
|
|||||||
"apis/libccpm.lua",
|
"apis/libccpm.lua",
|
||||||
"apis/libversion.lua",
|
"apis/libversion.lua",
|
||||||
"programs/ccpm.lua",
|
"programs/ccpm.lua",
|
||||||
"programs/upgrade.lua",
|
"programs/trapos-upgrade.lua",
|
||||||
|
"programs/trapos-postinstall.lua",
|
||||||
"programs/events.lua"
|
"programs/events.lua"
|
||||||
],
|
],
|
||||||
"autostart": []
|
"autostart": []
|
||||||
|
|||||||
50
programs/trapos-postinstall.lua
Normal file
50
programs/trapos-postinstall.lua
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
local createVersion = require('/apis/libversion');
|
||||||
|
|
||||||
|
local function printUsage()
|
||||||
|
print('trapos-postinstall usage:');
|
||||||
|
print();
|
||||||
|
print('\t\ttrapos-postinstall');
|
||||||
|
print('\t\ttrapos-postinstall version');
|
||||||
|
print('\t\ttrapos-postinstall help');
|
||||||
|
end
|
||||||
|
|
||||||
|
local command = ...;
|
||||||
|
|
||||||
|
if command == 'version' or command == '-version' or command == '--version' then
|
||||||
|
print('v' .. createVersion().forSelf());
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
if command == 'help' or command == '-help' or command == '--help' then
|
||||||
|
printUsage();
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
if command ~= nil and command ~= '' then
|
||||||
|
printUsage();
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
local function readManifestVersion()
|
||||||
|
if not fs.exists('/trapos/manifest.json') then return nil; end
|
||||||
|
local f = fs.open('/trapos/manifest.json', 'r');
|
||||||
|
if not f then return nil; end
|
||||||
|
local data = f.readAll();
|
||||||
|
f.close();
|
||||||
|
local manifest = data and textutils.unserializeJSON(data);
|
||||||
|
return manifest and manifest.version or nil;
|
||||||
|
end
|
||||||
|
|
||||||
|
local version = readManifestVersion();
|
||||||
|
|
||||||
|
print();
|
||||||
|
if version then
|
||||||
|
print('=> TrapOS v' .. version .. ' installed.');
|
||||||
|
else
|
||||||
|
print('=> TrapOS installed.');
|
||||||
|
end
|
||||||
|
print();
|
||||||
|
print('Get started:');
|
||||||
|
print(' sandbox --help -- open the sandbox help');
|
||||||
|
print(' trapos-upgrade -- update and upgrade TrapOS');
|
||||||
|
print();
|
||||||
38
programs/trapos-upgrade.lua
Normal file
38
programs/trapos-upgrade.lua
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
local createVersion = require('/apis/libversion');
|
||||||
|
|
||||||
|
local function printUsage()
|
||||||
|
print('trapos-upgrade usage:');
|
||||||
|
print();
|
||||||
|
print('\t\ttrapos-upgrade');
|
||||||
|
print('\t\ttrapos-upgrade --reboot');
|
||||||
|
print('\t\ttrapos-upgrade version');
|
||||||
|
print('\t\ttrapos-upgrade help');
|
||||||
|
end
|
||||||
|
|
||||||
|
local rawArgs = table.pack(...);
|
||||||
|
local reboot = false;
|
||||||
|
|
||||||
|
for i = 1, rawArgs.n do
|
||||||
|
local a = rawArgs[i];
|
||||||
|
if a == 'version' or a == '-version' or a == '--version' then
|
||||||
|
print('v' .. createVersion().forSelf());
|
||||||
|
return;
|
||||||
|
elseif a == 'help' or a == '-help' or a == '--help' then
|
||||||
|
printUsage();
|
||||||
|
return;
|
||||||
|
elseif a == '--reboot' or a == '-reboot' or a == '-r' then
|
||||||
|
reboot = true;
|
||||||
|
elseif a ~= nil and a ~= '' then
|
||||||
|
printUsage();
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shell.execute('ccpm', 'update');
|
||||||
|
shell.execute('ccpm', 'upgrade');
|
||||||
|
|
||||||
|
if reboot then
|
||||||
|
print();
|
||||||
|
print('=> Rebooting...');
|
||||||
|
os.reboot();
|
||||||
|
end
|
||||||
@ -1,28 +0,0 @@
|
|||||||
local createVersion = require('/apis/libversion');
|
|
||||||
|
|
||||||
local function printUsage()
|
|
||||||
print('upgrade usage:');
|
|
||||||
print();
|
|
||||||
print('\t\tupgrade');
|
|
||||||
print('\t\tupgrade version');
|
|
||||||
print('\t\tupgrade help');
|
|
||||||
end
|
|
||||||
|
|
||||||
local command = ...;
|
|
||||||
|
|
||||||
if command == 'version' or command == '-version' or command == '--version' then
|
|
||||||
print('v' .. createVersion().forSelf());
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
|
|
||||||
if command == 'help' or command == '-help' or command == '--help' then
|
|
||||||
printUsage();
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
|
|
||||||
if command ~= nil and command ~= '' then
|
|
||||||
printUsage();
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
|
|
||||||
shell.execute('ccpm', 'upgrade');
|
|
||||||
@ -43,31 +43,29 @@ local function fakeHttp(routes)
|
|||||||
};
|
};
|
||||||
end
|
end
|
||||||
|
|
||||||
testlib.test('programs path resolves the ccpm command', function()
|
local INSTALL_BASE = 'https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/master/';
|
||||||
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 trapos-boot', function()
|
local function installRoutes()
|
||||||
local root = '/install-ccpm-test/fresh-beta';
|
return {
|
||||||
fs.delete(root);
|
[INSTALL_BASE .. 'manifest.json'] = textutils.serializeJSON({ name = 'TrapOS', version = 'test' }),
|
||||||
fs.makeDir(root);
|
[INSTALL_BASE .. 'packages/trapos-core/ccpm.json'] = textutils.serializeJSON({
|
||||||
|
|
||||||
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({
|
|
||||||
name = 'trapos-core',
|
name = 'trapos-core',
|
||||||
version = '1',
|
version = '1',
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
files = { 'apis/libccpm.lua', 'programs/ccpm.lua' },
|
files = { 'apis/libccpm.lua', 'programs/ccpm.lua' },
|
||||||
}),
|
}),
|
||||||
[base .. 'apis/libccpm.lua'] = 'libccpm-body',
|
[INSTALL_BASE .. 'apis/libccpm.lua'] = 'libccpm-body',
|
||||||
[base .. 'programs/ccpm.lua'] = 'ccpm-body',
|
[INSTALL_BASE .. 'programs/ccpm.lua'] = 'ccpm-body',
|
||||||
};
|
};
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Run install-trapos.lua inside a sandboxed env. `args` is a list of CLI args.
|
||||||
|
-- Returns { calls, root } for assertions.
|
||||||
|
local function runInstall(root, args)
|
||||||
|
fs.delete(root);
|
||||||
|
fs.makeDir(root);
|
||||||
|
|
||||||
|
local routes = installRoutes();
|
||||||
local calls = {
|
local calls = {
|
||||||
executes = {},
|
executes = {},
|
||||||
path = '/rom/programs',
|
path = '/rom/programs',
|
||||||
@ -85,9 +83,11 @@ testlib.test('fresh beta bootstrap leaves ccpm runnable without trapos-boot', fu
|
|||||||
setDir = function(path) calls.dir = path; end,
|
setDir = function(path) calls.dir = path; end,
|
||||||
path = function() return calls.path; end,
|
path = function() return calls.path; end,
|
||||||
setPath = function(path) calls.path = path; end,
|
setPath = function(path) calls.path = path; end,
|
||||||
execute = function(program, url, target)
|
execute = function(program, ...)
|
||||||
calls.executes[#calls.executes + 1] = { program = program, url = url, target = target };
|
local rest = { ... };
|
||||||
|
calls.executes[#calls.executes + 1] = { program = program, args = rest };
|
||||||
if program ~= 'wget' then return true; end
|
if program ~= 'wget' then return true; end
|
||||||
|
local url, target = rest[1], rest[2];
|
||||||
local body = routes[url];
|
local body = routes[url];
|
||||||
if not body then return false; end
|
if not body then return false; end
|
||||||
local dir = parentDir(target);
|
local dir = parentDir(target);
|
||||||
@ -100,22 +100,64 @@ testlib.test('fresh beta bootstrap leaves ccpm runnable without trapos-boot', fu
|
|||||||
},
|
},
|
||||||
}, { __index = _G });
|
}, { __index = _G });
|
||||||
|
|
||||||
local chunk, loadErr = loadfile('/trapos/install-ccpm.lua', 't', env);
|
local chunk, loadErr = loadfile('/trapos/install-trapos.lua', 't', env);
|
||||||
if not chunk then error(loadErr, 0); end
|
if not chunk then error(loadErr, 0); end
|
||||||
local ok, err = pcall(chunk, '--beta');
|
local ok, err = pcall(chunk, table.unpack(args));
|
||||||
if not ok then error(err, 0); end
|
if not ok then error(err, 0); end
|
||||||
|
|
||||||
|
return calls;
|
||||||
|
end
|
||||||
|
|
||||||
|
local function findExecute(calls, program, firstArg)
|
||||||
|
for _, call in ipairs(calls.executes) do
|
||||||
|
if call.program == program then
|
||||||
|
if firstArg == nil or call.args[1] == firstArg then
|
||||||
|
return true;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false;
|
||||||
|
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 bootstrap seeds a gitea master registry and runs ccpm', function()
|
||||||
|
local root = '/install-trapos-test/full';
|
||||||
|
local calls = runInstall(root, {});
|
||||||
|
|
||||||
testlib.assertTrue(fs.exists(root .. '/programs/ccpm.lua'));
|
testlib.assertTrue(fs.exists(root .. '/programs/ccpm.lua'));
|
||||||
testlib.assertTrue(string.find(calls.path, '/programs', 1, true));
|
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 f = fs.open(root .. '/trapos/ccpm.json', 'r');
|
||||||
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, 'master');
|
||||||
testlib.assertEquals(config.registries[1].type, 'gitea');
|
testlib.assertEquals(config.registries[1].type, 'gitea');
|
||||||
end);
|
end);
|
||||||
|
|
||||||
|
testlib.test('default install runs update, install trapos and postinstall', function()
|
||||||
|
local root = '/install-trapos-test/default';
|
||||||
|
local calls = runInstall(root, {});
|
||||||
|
|
||||||
|
testlib.assertTrue(findExecute(calls, 'ccpm', 'update'));
|
||||||
|
testlib.assertTrue(findExecute(calls, 'ccpm', 'install'));
|
||||||
|
testlib.assertTrue(findExecute(calls, 'trapos-postinstall'));
|
||||||
|
end);
|
||||||
|
|
||||||
|
testlib.test('--cpm-only stops after the ccpm bootstrap', function()
|
||||||
|
local root = '/install-trapos-test/cpm-only';
|
||||||
|
local calls = runInstall(root, { '--cpm-only' });
|
||||||
|
|
||||||
|
testlib.assertTrue(fs.exists(root .. '/programs/ccpm.lua'));
|
||||||
|
testlib.assertTrue(not findExecute(calls, 'ccpm', 'update'));
|
||||||
|
testlib.assertTrue(not findExecute(calls, 'ccpm', 'install'));
|
||||||
|
testlib.assertTrue(not findExecute(calls, 'trapos-postinstall'));
|
||||||
|
end);
|
||||||
|
|
||||||
testlib.run();
|
testlib.run();
|
||||||
Loading…
Reference in New Issue
Block a user