212 Commits
Author SHA1 Message Date
cat 0fa145a1a0 internal/rosa/package/libpsl: 0.23.0 to 0.23.1
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 2m55s
Test / Hakurei (push) Successful in 4m43s
Test / Sandbox (race detector) (push) Successful in 6m5s
Test / Hakurei (race detector) (push) Successful in 7m5s
Test / ShareFS (push) Successful in 7m28s
Test / Flake checks (push) Successful in 1m10s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-02 10:15:12 +09:00
cat b5a65d1255 internal/rosa/package/cmake: 4.4.1 to 4.4.2
Test / Hakurei (push) Successful in 8m40s
Test / Hakurei (race detector) (push) Successful in 10m29s
Test / Sandbox (race detector) (push) Successful in 8m32s
Test / ShareFS (push) Successful in 10m48s
Test / Create distribution (push) Successful in 1m26s
Test / Sandbox (push) Successful in 1m35s
Test / Flake checks (push) Successful in 2m2s
Those regressions sure came quickly. Concerning.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-01 16:38:46 +09:00
cat ccdc0fa37e internal/rosa/package/libudev-zero: 1.0.4 to 1.0.5
Test / Sandbox (push) Successful in 5m17s
Test / Create distribution (push) Successful in 1m28s
Test / Hakurei (push) Successful in 11m52s
Test / Sandbox (race detector) (push) Successful in 9m19s
Test / Hakurei (race detector) (push) Successful in 13m57s
Test / ShareFS (push) Successful in 12m36s
Test / Flake checks (push) Successful in 1m16s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-01 16:38:20 +09:00
cat b97518552d internal/rosa/package/spirv: spirv-llvm-translator 22.1.4 to 22.1.5
Test / Create distribution (push) Successful in 54s
Test / Sandbox (push) Successful in 4m57s
Test / Hakurei (push) Successful in 9m25s
Test / Sandbox (race detector) (push) Successful in 10m37s
Test / Hakurei (race detector) (push) Successful in 14m8s
Test / ShareFS (push) Successful in 16m51s
Test / Flake checks (push) Successful in 1m33s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-01 16:37:51 +09:00
cat 67d14dc12c internal/rosa/package/noto: 2026.07.01 to 2026.08.01
Test / Create distribution (push) Successful in 1m12s
Test / Sandbox (push) Successful in 4m16s
Test / Hakurei (push) Successful in 8m40s
Test / Sandbox (race detector) (push) Successful in 10m47s
Test / Hakurei (race detector) (push) Successful in 14m34s
Test / ShareFS (push) Successful in 17m18s
Test / Flake checks (push) Successful in 1m31s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-01 16:37:18 +09:00
cat 695b1b4845 internal/rosa/package/harfbuzz: 14.2.1 to 14.3.0
Test / Create distribution (push) Successful in 1m16s
Test / Sandbox (push) Successful in 3m42s
Test / Hakurei (push) Successful in 7m42s
Test / Sandbox (race detector) (push) Successful in 10m51s
Test / Hakurei (race detector) (push) Successful in 13m57s
Test / ShareFS (push) Successful in 16m55s
Test / Flake checks (push) Successful in 1m38s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-01 16:36:58 +09:00
cat 2e5d954f49 internal/rosa/package/hwdata: 0.409 to 0.410
Test / Hakurei (race detector) (push) Successful in 6m59s
Test / Sandbox (push) Successful in 2m44s
Test / Sandbox (race detector) (push) Successful in 5m44s
Test / ShareFS (push) Successful in 6m57s
Test / Create distribution (push) Successful in 53s
Test / Hakurei (push) Successful in 2m50s
Test / Flake checks (push) Successful in 1m8s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-31 21:07:22 +09:00
cat e6af0c405a internal/rosa/package: pipewire/wireplumber
Test / Create distribution (push) Successful in 1m2s
Test / Sandbox (push) Successful in 3m53s
Test / Hakurei (push) Successful in 6m34s
Test / Sandbox (race detector) (push) Successful in 7m2s
Test / Hakurei (race detector) (push) Successful in 8m23s
Test / ShareFS (push) Successful in 9m37s
Test / Flake checks (push) Successful in 1m7s
These are built separately to avoid meson wrap.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-31 17:06:26 +09:00
cat 599a761b27 internal/rosa/package: lua
Test / Create distribution (push) Successful in 51s
Test / Sandbox (push) Successful in 2m55s
Test / Hakurei (push) Successful in 4m54s
Test / Sandbox (race detector) (push) Successful in 6m10s
Test / Hakurei (race detector) (push) Successful in 8m0s
Test / ShareFS (push) Successful in 8m29s
Test / Flake checks (push) Successful in 1m34s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-31 17:03:02 +09:00
cat b7aa91f08f cmd/mbf: set window title
Test / Hakurei (race detector) (push) Successful in 6m57s
Test / Sandbox (push) Successful in 3m8s
Test / Sandbox (race detector) (push) Successful in 5m46s
Test / ShareFS (push) Successful in 7m26s
Test / Create distribution (push) Successful in 50s
Test / Hakurei (push) Successful in 2m54s
Test / Flake checks (push) Successful in 1m9s
This displays ongoing and complete cures via the notify channel.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-31 15:49:07 +09:00
cat 280a736ce3 internal/pkg: cure entry/exit notification
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 2m55s
Test / Hakurei (push) Successful in 4m49s
Test / Sandbox (race detector) (push) Successful in 6m7s
Test / Hakurei (race detector) (push) Successful in 7m42s
Test / ShareFS (push) Successful in 8m10s
Test / Flake checks (push) Successful in 1m39s
This enables cure status display without inspecting internal state.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-31 13:58:32 +09:00
cat 4e41b9bc99 cmd/mbf: all command
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 2m56s
Test / Hakurei (push) Successful in 4m37s
Test / Sandbox (race detector) (push) Successful in 5m52s
Test / Hakurei (race detector) (push) Successful in 7m6s
Test / ShareFS (push) Successful in 7m15s
Test / Flake checks (push) Successful in 1m7s
This is a convenience command to cure all registered packages to avoid relying on the test.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-31 13:16:36 +09:00
cat 153c980a61 internal/rosa/package/kernel: 6.18.40 to 6.18.41
Test / Create distribution (push) Successful in 2m7s
Test / Sandbox (push) Successful in 5m21s
Test / Hakurei (push) Successful in 7m4s
Test / Sandbox (race detector) (push) Successful in 7m57s
Test / Hakurei (race detector) (push) Successful in 9m18s
Test / ShareFS (push) Successful in 9m55s
Test / Flake checks (push) Successful in 1m10s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 23:16:17 +09:00
cat a2f97f7e0f internal/rosa/package: use mirrors.kernel.org
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 2m56s
Test / Hakurei (push) Successful in 4m42s
Test / Sandbox (race detector) (push) Successful in 5m56s
Test / Hakurei (race detector) (push) Successful in 7m12s
Test / ShareFS (push) Successful in 7m23s
Test / Flake checks (push) Successful in 1m16s
The GNU mirror redirector was down yet again, and I have had enough. This change replaces all mentions of ftpmirror.gnu.org with mirrors.kernel.org.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 22:59:08 +09:00
cat 5e1b4bb0b8 cmd/mbf: print checksum to stdout
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 3m10s
Test / Hakurei (push) Successful in 5m12s
Test / Sandbox (race detector) (push) Successful in 6m20s
Test / Hakurei (race detector) (push) Successful in 7m23s
Test / ShareFS (push) Successful in 7m54s
Test / Flake checks (push) Successful in 1m11s
Same as the cure command, enables usage in scripts.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 22:45:05 +09:00
cat e73f9e0626 internal/pkg: highlight miscellaneous verbose output
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 3m11s
Test / Hakurei (push) Successful in 5m10s
Test / Sandbox (race detector) (push) Successful in 6m23s
Test / Hakurei (race detector) (push) Successful in 7m51s
Test / ShareFS (push) Successful in 8m21s
Test / Flake checks (push) Successful in 1m18s
These were missed when adding highlight for core cache verbose output.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 22:41:18 +09:00
cat ddd90b780b internal/rosa: drain optional unstructured input
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 2m56s
Test / Hakurei (push) Successful in 4m48s
Test / Sandbox (race detector) (push) Successful in 6m2s
Test / Hakurei (race detector) (push) Successful in 7m46s
Test / ShareFS (push) Successful in 7m56s
Test / Flake checks (push) Successful in 1m26s
This was missed, causing non-minimal kindEtc IR to be rejected.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 22:39:29 +09:00
cat 89c32f5614 cmd/mbf: print outcome pathname to stdout
Test / Create distribution (push) Successful in 1m1s
Test / Sandbox (push) Successful in 3m6s
Test / Hakurei (push) Successful in 4m47s
Test / Sandbox (race detector) (push) Successful in 6m4s
Test / Hakurei (race detector) (push) Successful in 7m10s
Test / ShareFS (push) Successful in 7m30s
Test / Flake checks (push) Successful in 1m6s
This enables use of the cure command in scripts.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 17:39:56 +09:00
cat 1567a3e582 internal/pkg: highlight cache verbose output
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 2m49s
Test / Hakurei (push) Successful in 4m33s
Test / Sandbox (race detector) (push) Successful in 5m50s
Test / Hakurei (race detector) (push) Successful in 7m11s
Test / ShareFS (push) Successful in 7m34s
Test / Flake checks (push) Successful in 1m21s
This highlights sections of messages, increasing readability in some cases.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 17:35:49 +09:00
cat aa9952cd9e internal/rosa/package/spirv: 1.4.350.1 to 1.4.357.0
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 3m1s
Test / Hakurei (push) Successful in 4m34s
Test / Sandbox (race detector) (push) Successful in 5m56s
Test / Hakurei (race detector) (push) Successful in 6m56s
Test / ShareFS (push) Successful in 7m21s
Test / Flake checks (push) Successful in 1m12s
This also switches spirv-tools to the vulkan-sdk tags to remain compatible with spriv-headers.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 16:52:25 +09:00
cat 99efc551ad internal/rosa/package/meson: respect CLICOLOR_FORCE
Test / Create distribution (push) Successful in 1m17s
Test / Sandbox (push) Successful in 3m22s
Test / Hakurei (push) Successful in 6m25s
Test / Sandbox (race detector) (push) Successful in 7m47s
Test / Hakurei (race detector) (push) Successful in 10m39s
Test / ShareFS (push) Successful in 14m12s
Test / Flake checks (push) Successful in 1m37s
Upstream had ticket and patch available since 2017, still unmerged and refuses to support the environment variable, so patch it in. This also strips out the variable for test execution to work around buggy test suites like glib.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 08:51:46 +09:00
cat 4dbfee0698 internal/rosa: force output colouring
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 3m0s
Test / Hakurei (push) Successful in 4m45s
Test / Sandbox (race detector) (push) Successful in 6m0s
Test / Hakurei (race detector) (push) Successful in 7m16s
Test / ShareFS (push) Successful in 7m47s
Test / Flake checks (push) Successful in 2m56s
This sets known de facto standard environment variables to enable colours during builds.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 06:01:54 +09:00
cat 4e65e41101 internal/rosa/package/mesa: 26.1.5 to 26.1.6
Test / Create distribution (push) Successful in 54s
Test / Sandbox (push) Successful in 3m33s
Test / Hakurei (push) Successful in 5m54s
Test / Sandbox (race detector) (push) Successful in 6m7s
Test / Hakurei (race detector) (push) Successful in 8m5s
Test / ShareFS (push) Successful in 7m16s
Test / Flake checks (push) Successful in 1m13s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 05:19:55 +09:00
cat b8306fe9e2 internal/rosa/package/python: vcs-versioning 2.2.2 to 2.2.3
Test / Create distribution (push) Successful in 1m7s
Test / Sandbox (push) Successful in 2m58s
Test / Hakurei (push) Successful in 6m24s
Test / Sandbox (race detector) (push) Successful in 5m37s
Test / Hakurei (race detector) (push) Successful in 8m14s
Test / ShareFS (push) Successful in 7m39s
Test / Flake checks (push) Successful in 1m20s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 05:19:21 +09:00
cat 6b246e9036 internal/rosa/package/glib: 2.89.2 to 2.89.3
Test / Sandbox (push) Successful in 1m32s
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (race detector) (push) Successful in 4m45s
Test / Hakurei (race detector) (push) Successful in 8m33s
Test / ShareFS (push) Successful in 7m26s
Test / Hakurei (push) Successful in 32m29s
Test / Flake checks (push) Successful in 1m9s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 05:18:23 +09:00
cat 869820ec6d cmd/mbf: enable output colouring
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 3m36s
Test / Hakurei (push) Successful in 6m11s
Test / Sandbox (race detector) (push) Successful in 7m44s
Test / Hakurei (race detector) (push) Successful in 9m57s
Test / ShareFS (push) Successful in 10m35s
Test / Flake checks (push) Successful in 1m30s
This respects the de facto standards, on top of checking stderr.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 05:16:39 +09:00
cat 6fb2065a51 internal/pkg: optionally colour output
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 2m55s
Test / Hakurei (push) Successful in 5m2s
Test / Sandbox (race detector) (push) Successful in 6m19s
Test / ShareFS (push) Successful in 8m41s
Test / Hakurei (race detector) (push) Successful in 8m49s
Test / Flake checks (push) Successful in 1m29s
This increases readability in some cases.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 05:15:19 +09:00
cat 698fd2d66a internal/rosa/package/libarchive: 3.8.8 to 3.8.9
Test / Create distribution (push) Successful in 1m6s
Test / Sandbox (push) Successful in 3m8s
Test / Hakurei (push) Successful in 5m32s
Test / Sandbox (race detector) (push) Successful in 6m28s
Test / Hakurei (race detector) (push) Successful in 7m49s
Test / ShareFS (push) Successful in 8m9s
Test / Flake checks (push) Successful in 1m14s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 04:02:23 +09:00
cat 4cfbc93aa0 internal/rosa/package/gcc: binutils 2.46.1 to 2.47
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 3m3s
Test / Hakurei (push) Successful in 4m59s
Test / Sandbox (race detector) (push) Successful in 6m24s
Test / Hakurei (race detector) (push) Successful in 8m0s
Test / ShareFS (push) Successful in 8m12s
Test / Flake checks (push) Successful in 1m15s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 04:02:00 +09:00
cat feec4b0d22 internal/rosa/package/cmake: 4.4.0 to 4.4.1
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 2m59s
Test / Hakurei (push) Successful in 5m16s
Test / Sandbox (race detector) (push) Successful in 6m37s
Test / Hakurei (race detector) (push) Successful in 7m44s
Test / ShareFS (push) Successful in 8m23s
Test / Flake checks (push) Successful in 1m15s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 03:24:48 +09:00
cat 6487b41d92 internal/rosa: remove legacy exec helper
Test / Hakurei (race detector) (push) Successful in 9m33s
Test / Sandbox (push) Successful in 5m27s
Test / Sandbox (race detector) (push) Successful in 8m21s
Test / ShareFS (push) Successful in 10m32s
Test / Create distribution (push) Successful in 1m51s
Test / Hakurei (push) Successful in 3m5s
Test / Flake checks (push) Successful in 1m28s
This change also adds a fourth stage to the bootstrap machinery, offering more correct toolchain validation that works around LLVM dynamic linking flaws.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-30 00:18:22 +09:00
cat 7908fb9583 internal/rosa/llvm: exclude runtime symbols
Test / Hakurei (push) Successful in 4m44s
Test / Sandbox (push) Successful in 3m5s
Test / Sandbox (race detector) (push) Successful in 5m55s
Test / ShareFS (push) Successful in 7m22s
Test / Create distribution (push) Successful in 1m0s
Test / Hakurei (race detector) (push) Successful in 6m22s
Test / Flake checks (push) Successful in 1m13s
These leak by default when static linking, which is considered unacceptable for many libraries.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-29 03:00:59 +09:00
cat 95aa7c205c internal/rosa: remove calls to low-level exec helper
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 2m54s
Test / Hakurei (push) Successful in 4m32s
Test / Sandbox (race detector) (push) Successful in 5m48s
Test / Hakurei (race detector) (push) Successful in 6m59s
Test / ShareFS (push) Successful in 7m29s
Test / Flake checks (push) Successful in 1m12s
This method predates the helper infrastructure, it is awkward to use and difficult to maintain for the replacement bootstrap mechanism. This change prepares for its removal.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-27 18:24:38 +09:00
cat bd0cc3656f internal/rosa/llvm: statically link libc++
Test / Hakurei (race detector) (push) Successful in 6m54s
Test / Sandbox (push) Successful in 2m53s
Test / Sandbox (race detector) (push) Successful in 5m58s
Test / ShareFS (push) Successful in 7m25s
Test / Create distribution (push) Successful in 53s
Test / Hakurei (push) Successful in 2m51s
Test / Flake checks (push) Successful in 1m9s
This avoids unnecessarily depending on the toolchain.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-27 18:15:00 +09:00
cat 0219240adb internal/rosa/package/qemu: 11.0.2 to 11.0.3
Test / Sandbox (push) Successful in 1m35s
Test / Hakurei (push) Successful in 3m19s
Test / Sandbox (race detector) (push) Successful in 4m40s
Test / Hakurei (race detector) (push) Successful in 5m49s
Test / ShareFS (push) Successful in 6m17s
Test / Flake checks (push) Successful in 1m16s
Test / Create distribution (push) Successful in 31s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-25 14:23:25 +09:00
cat aa4a15fc2c cmd/mbf: move gentoo bootstrap path
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 3m24s
Test / Sandbox (race detector) (push) Successful in 6m43s
Test / Hakurei (race detector) (push) Successful in 8m2s
Test / ShareFS (push) Successful in 8m10s
Test / Hakurei (push) Successful in 3m22s
Test / Flake checks (push) Successful in 1m18s
This is a lot more flexible for troubleshooting when used with the cure command.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-25 14:17:03 +09:00
cat 0d3efeb456 internal/rosa: remove xz utils hack
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 2m54s
Test / Hakurei (push) Successful in 4m33s
Test / Sandbox (race detector) (push) Successful in 6m5s
Test / Hakurei (race detector) (push) Successful in 8m0s
Test / ShareFS (push) Successful in 8m32s
Test / Flake checks (push) Successful in 1m27s
This replaces all xz invocations with the native decompressor. This also significantly cleans up the Gentoo stage3 bootstrap path.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-25 14:14:34 +09:00
cat 35147f6dfb internal/pkg: skip character device nodes
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 3m2s
Test / Hakurei (push) Successful in 5m1s
Test / Sandbox (race detector) (push) Successful in 6m18s
Test / Hakurei (race detector) (push) Successful in 7m20s
Test / ShareFS (push) Successful in 7m52s
Test / Flake checks (push) Successful in 1m18s
This allows unpacking of tarballs containing these entries.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-25 14:07:38 +09:00
cat e5abf51296 internal/pkg: decompress xz streams
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 2m54s
Test / Hakurei (push) Successful in 4m48s
Test / Sandbox (race detector) (push) Successful in 5m59s
Test / Hakurei (race detector) (push) Successful in 7m35s
Test / ShareFS (push) Successful in 7m42s
Test / Flake checks (push) Successful in 1m18s
This uses a port of the public domain xz implementation.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-25 14:03:34 +09:00
cat e26914cd6f internal/rosa/package/kernel: 6.18.39 to 6.18.40
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 3m0s
Test / ShareFS (push) Successful in 3m57s
Test / Hakurei (push) Successful in 4m9s
Test / Sandbox (race detector) (push) Successful in 5m36s
Test / Hakurei (race detector) (push) Successful in 6m47s
Test / Flake checks (push) Successful in 1m19s
Kernel headers bumped due to struct bpf_map_info changes and IFLA_BOND_LACP_STRICT.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-25 13:58:12 +09:00
cat b647170d0c internal/rosa/package/strace: build from git sources
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m48s
Test / Hakurei (push) Successful in 3m59s
Test / ShareFS (push) Successful in 4m1s
Test / Sandbox (race detector) (push) Successful in 5m31s
Test / Hakurei (race detector) (push) Successful in 6m42s
Test / Flake checks (push) Successful in 1m5s
This removes xz input. This change also enables tests.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-25 01:40:47 +09:00
cat 5e655a0bf6 internal/rosa/package: gawk
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 2m49s
Test / ShareFS (push) Successful in 3m56s
Test / Hakurei (push) Successful in 4m6s
Test / Sandbox (race detector) (push) Successful in 5m30s
Test / Hakurei (race detector) (push) Successful in 6m44s
Test / Flake checks (push) Successful in 1m4s
Reintroduce this to build strace without xz-compressed release tarball: bootstrap script explicitly requires gawk.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-25 01:21:41 +09:00
cat 89eb3d27aa internal/rosa/package/util-linux: add ncurses
Test / Create distribution (push) Successful in 50s
Test / Sandbox (push) Successful in 2m49s
Test / ShareFS (push) Successful in 3m51s
Test / Hakurei (push) Successful in 4m3s
Test / Sandbox (race detector) (push) Successful in 5m41s
Test / Hakurei (race detector) (push) Successful in 6m35s
Test / Flake checks (push) Successful in 1m5s
This enables more.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-25 00:54:25 +09:00
cat 3b7a22ff9b cmd/dist: default to /usr/local prefix
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 3m11s
Test / Hakurei (push) Successful in 4m36s
Test / ShareFS (push) Successful in 4m38s
Test / Sandbox (race detector) (push) Successful in 5m56s
Test / Hakurei (race detector) (push) Successful in 7m5s
Test / Flake checks (push) Successful in 1m5s
This conventionally makes more sense for software not installed by the package manager.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-24 19:12:59 +09:00
cat 6c2ca507b9 internal/rosa/package: byacc
Test / Create distribution (push) Successful in 2m9s
Test / Sandbox (push) Successful in 7m31s
Test / ShareFS (push) Successful in 9m54s
Test / Sandbox (race detector) (push) Successful in 2m27s
Test / Hakurei (push) Successful in 2m58s
Test / Hakurei (race detector) (push) Successful in 4m0s
Test / Flake checks (push) Successful in 1m16s
Much cleaner than bison and compiles much faster. This should be used whenever possible.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-24 18:48:20 +09:00
cat 1a8212ee02 internal/rosa/package/libdisplay-info: 0.3.0 to 0.4.0
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m50s
Test / ShareFS (push) Successful in 4m11s
Test / Sandbox (race detector) (push) Successful in 5m43s
Test / Hakurei (race detector) (push) Successful in 6m48s
Test / Hakurei (push) Successful in 2m29s
Test / Flake checks (push) Successful in 1m6s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-24 11:53:59 +09:00
cat 84bb2a5038 internal/rosa: update stage0 distribution
Test / Create distribution (push) Successful in 1m3s
Test / Sandbox (push) Successful in 2m44s
Test / ShareFS (push) Successful in 3m45s
Test / Sandbox (race detector) (push) Successful in 5m47s
Test / Hakurei (race detector) (push) Successful in 7m9s
Test / Hakurei (push) Successful in 2m49s
Test / Flake checks (push) Successful in 1m23s
This also replaces the slow bzip2 compression with zstd.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-24 11:10:59 +09:00
cat 46b247f911 internal/rosa/package/zstd: use zstd-compressed tarball
Test / Create distribution (push) Successful in 2m44s
Test / Sandbox (push) Successful in 6m14s
Test / Hakurei (push) Successful in 7m20s
Test / ShareFS (push) Successful in 7m24s
Test / Sandbox (race detector) (push) Successful in 8m49s
Test / Hakurei (race detector) (push) Successful in 10m15s
Test / Flake checks (push) Successful in 1m19s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-24 00:06:18 +09:00
cat 390f3b2dae internal/pkg: decompress zstd streams
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 3m2s
Test / ShareFS (push) Successful in 4m3s
Test / Hakurei (push) Successful in 4m16s
Test / Sandbox (race detector) (push) Successful in 5m37s
Test / Hakurei (race detector) (push) Successful in 6m49s
Test / Flake checks (push) Successful in 1m11s
This uses internal/zstd until compress/zstd becomes available.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-23 22:18:06 +09:00
cat 5d3e47d8e7 internal/rosa/package/libarchive: add runtime dependencies
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m59s
Test / ShareFS (push) Successful in 4m1s
Test / Hakurei (push) Successful in 4m10s
Test / Sandbox (race detector) (push) Successful in 5m31s
Test / Hakurei (race detector) (push) Successful in 6m47s
Test / Flake checks (push) Successful in 1m8s
These were missed due to being implied by the toolchain.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-23 22:02:06 +09:00
cat 6f2852547b internal/rosa/package/netfilter: use git protocol
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m51s
Test / ShareFS (push) Successful in 3m59s
Test / Hakurei (push) Successful in 4m7s
Test / Sandbox (race detector) (push) Successful in 5m57s
Test / Hakurei (race detector) (push) Successful in 7m28s
Test / Flake checks (push) Successful in 1m20s
The https service is down but somehow the git protocol is still accessible. Security implications do not apply due to KnownChecksum measurement.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-23 21:56:52 +09:00
cat 3cff369368 internal/rosa/package/xkbcommon: use fallback update filter
Test / Create distribution (push) Successful in 2m30s
Test / Sandbox (push) Successful in 5m35s
Test / Hakurei (push) Successful in 7m13s
Test / ShareFS (push) Successful in 7m16s
Test / Hakurei (race detector) (push) Successful in 10m49s
Test / Sandbox (race detector) (push) Successful in 3m20s
Test / Flake checks (push) Successful in 2m15s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-23 18:10:50 +09:00
cat 09de939955 internal/rosa: make build script executable
Test / Create distribution (push) Successful in 50s
Test / Sandbox (push) Successful in 3m24s
Test / ShareFS (push) Successful in 4m44s
Test / Hakurei (push) Successful in 4m53s
Test / Sandbox (race detector) (push) Successful in 6m12s
Test / Hakurei (race detector) (push) Successful in 7m29s
Test / Flake checks (push) Successful in 3m25s
This makes it slightly easier to invoke when working on a package via --enter.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-23 18:02:50 +09:00
cat e0eec632d0 internal/pkg: optional executable files
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 2m54s
Test / ShareFS (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 5m33s
Test / Hakurei (race detector) (push) Successful in 6m48s
Test / Hakurei (push) Successful in 2m29s
Test / Flake checks (push) Successful in 1m10s
This enables a FileArtifact implementation to specify whether its resulting file should be executable. This change also implements shebang and ELF magic checks in the file artifact.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-23 17:10:22 +09:00
cat 67dbb68818 internal/pkg: implementation revisions
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 2m43s
Test / ShareFS (push) Successful in 3m57s
Test / Hakurei (push) Successful in 4m3s
Test / Sandbox (race detector) (push) Successful in 5m34s
Test / Hakurei (race detector) (push) Successful in 6m36s
Test / Flake checks (push) Successful in 1m5s
This enables changing the behaviour of an artifact implementation without changing its IR structure. Unfortunately this changes the IR header structure resulting in many rebuilds.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-23 16:39:34 +09:00
cat 0e689d9983 internal/rosa/package: codeberg prefer release tarballs
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 3m53s
Test / ShareFS (push) Successful in 5m8s
Test / Sandbox (race detector) (push) Successful in 5m46s
Test / Hakurei (race detector) (push) Successful in 8m53s
Test / Hakurei (push) Successful in 2m36s
Test / Flake checks (push) Successful in 1m15s
Source archives are unstable.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-22 11:26:12 +09:00
cat 21a4067592 internal/rosa/package/perl: 5.42.2 to 5.44.0
Test / Create distribution (push) Successful in 54s
Test / Sandbox (push) Successful in 4m14s
Test / Hakurei (push) Successful in 6m59s
Test / ShareFS (push) Successful in 7m5s
Test / Sandbox (race detector) (push) Successful in 7m33s
Test / Hakurei (race detector) (push) Successful in 9m29s
Test / Flake checks (push) Successful in 1m17s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-22 11:24:46 +09:00
cat 639766dfca internal/rosa/package/gnu: parallel 20260622 to 20260722
Test / Create distribution (push) Successful in 1m5s
Test / Sandbox (push) Successful in 3m15s
Test / ShareFS (push) Successful in 4m51s
Test / Sandbox (race detector) (push) Successful in 6m53s
Test / Hakurei (race detector) (push) Successful in 9m42s
Test / Hakurei (push) Successful in 2m40s
Test / Flake checks (push) Successful in 1m11s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-22 11:23:50 +09:00
cat e4f025b9f1 internal/rosa/package/python: setuptools-scm 10.2.0 to 10.2.1
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 3m9s
Test / Hakurei (push) Successful in 5m7s
Test / ShareFS (push) Successful in 5m5s
Test / Sandbox (race detector) (push) Successful in 7m30s
Test / Hakurei (race detector) (push) Successful in 10m13s
Test / Flake checks (push) Successful in 1m17s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-22 11:23:24 +09:00
cat 1b65c8107c internal/rosa/package/kernel: 6.18.38 to 6.18.39
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 3m9s
Test / ShareFS (push) Successful in 4m16s
Test / Hakurei (push) Successful in 4m20s
Test / Sandbox (race detector) (push) Successful in 5m44s
Test / Hakurei (race detector) (push) Successful in 6m50s
Test / Flake checks (push) Successful in 1m8s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-21 12:13:22 +09:00
cat 1857ad8763 internal/rosa: optionally exclude toolchain in azalea
Test / Create distribution (push) Successful in 51s
Test / Sandbox (push) Successful in 2m46s
Test / ShareFS (push) Successful in 3m48s
Test / Sandbox (race detector) (push) Successful in 5m27s
Test / Hakurei (race detector) (push) Successful in 6m41s
Test / Hakurei (push) Successful in 2m42s
Test / Flake checks (push) Successful in 1m23s
This is useful for edge cases where programs rely on gcc bugs to behave correctly.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-19 03:38:35 +09:00
cat c822ff9aca internal/rosa: migrate early-compiler-rt to azalea
Test / Create distribution (push) Successful in 49s
Test / Sandbox (push) Successful in 2m44s
Test / ShareFS (push) Successful in 3m53s
Test / Hakurei (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 5m30s
Test / Hakurei (race detector) (push) Successful in 6m39s
Test / Flake checks (push) Successful in 1m5s
Had to do the cmake hack for now due to evaluator limitation with inherited version.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-18 23:56:05 +09:00
cat 9df1609660 internal/rosa: migrate early-runtimes to azalea
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 2m41s
Test / ShareFS (push) Successful in 3m50s
Test / Hakurei (push) Successful in 3m58s
Test / Sandbox (race detector) (push) Successful in 5m25s
Test / Hakurei (race detector) (push) Successful in 6m40s
Test / Flake checks (push) Successful in 1m5s
This is fully representable in azalea, so migrate it.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-18 23:23:16 +09:00
cat 22e9e85a03 internal/rosa: migrate llvm source to azalea
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 2m57s
Test / ShareFS (push) Successful in 3m58s
Test / Hakurei (push) Successful in 4m5s
Test / Sandbox (race detector) (push) Successful in 5m30s
Test / Hakurei (race detector) (push) Successful in 6m38s
Test / Flake checks (push) Successful in 1m6s
Previous change enabled this migration.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-18 23:14:18 +09:00
cat b79aa3ea1c internal/rosa/state: patch output-only packages
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m51s
Test / ShareFS (push) Successful in 3m56s
Test / Hakurei (push) Successful in 4m4s
Test / Sandbox (race detector) (push) Successful in 5m36s
Test / Hakurei (race detector) (push) Successful in 6m37s
Test / Flake checks (push) Successful in 1m5s
This is useful for common patched source code.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-18 23:05:52 +09:00
cat 8d9b14dfe1 internal/rosa/cmake: disable nuisance warnings
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m44s
Test / ShareFS (push) Successful in 3m52s
Test / Hakurei (push) Successful in 4m3s
Test / Sandbox (race detector) (push) Successful in 5m28s
Test / Hakurei (race detector) (push) Successful in 6m38s
Test / Flake checks (push) Successful in 1m6s
Author warnings are pointless here, and it makes no sense to make CMAKE_<LANG>_COMPILER_TARGET optional just to shut cmake up.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-18 13:44:41 +09:00
cat 5770f957e5 internal/rosa/package/gnu: libtool 2.5.4 to 2.6.2
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 2m58s
Test / ShareFS (push) Successful in 3m48s
Test / Hakurei (push) Successful in 3m58s
Test / Sandbox (race detector) (push) Successful in 5m30s
Test / Hakurei (race detector) (push) Successful in 6m42s
Test / Flake checks (push) Successful in 1m4s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-18 12:07:05 +09:00
cat e7903cf7e2 internal/rosa/package/wayland: 1.25.91 to 1.26.0
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 3m6s
Test / Hakurei (push) Successful in 4m49s
Test / ShareFS (push) Successful in 4m57s
Test / Sandbox (race detector) (push) Successful in 6m17s
Test / Hakurei (race detector) (push) Successful in 7m28s
Test / Flake checks (push) Successful in 1m9s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-18 11:57:10 +09:00
cat df199a8774 internal/rosa/package/nss: 3.125 to 3.126
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 3m0s
Test / ShareFS (push) Successful in 4m34s
Test / Hakurei (push) Successful in 4m52s
Test / Sandbox (race detector) (push) Successful in 6m26s
Test / Hakurei (race detector) (push) Successful in 7m48s
Test / Flake checks (push) Successful in 1m8s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-18 11:56:46 +09:00
cat d906bc2ee0 internal/rosa/package/spirv: disable arm64 broken tests
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 3m2s
Test / ShareFS (push) Successful in 4m0s
Test / Hakurei (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 5m35s
Test / Hakurei (race detector) (push) Successful in 6m44s
Test / Flake checks (push) Successful in 1m7s
These were newly broken by the latest release.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-17 16:15:32 +09:00
cat e0e9910243 internal/rosa/package/perl: fix release monitoring
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 3m3s
Test / Hakurei (push) Successful in 4m29s
Test / ShareFS (push) Successful in 4m22s
Test / Sandbox (race detector) (push) Successful in 5m51s
Test / Hakurei (race detector) (push) Successful in 6m56s
Test / Flake checks (push) Successful in 1m6s
The existing Microsoft Github monitoring is broken due to unconventional upstream tagging practices. This change switches to monitoring based on the web page instead.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-16 12:58:51 +09:00
cat c8d54cebe9 internal/rosa/package/mesa: 26.1.4 to 26.1.5
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 3m2s
Test / ShareFS (push) Successful in 4m7s
Test / Hakurei (push) Successful in 4m13s
Test / Sandbox (race detector) (push) Successful in 5m45s
Test / Hakurei (race detector) (push) Successful in 7m10s
Test / Flake checks (push) Successful in 1m18s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-16 12:56:02 +09:00
cat 74e7fb7818 internal/rosa/package/spirv: spirv-llvm-translator 22.1.2 to 22.1.4
Test / Sandbox (push) Successful in 2m8s
Test / Create distribution (push) Successful in 56s
Test / Hakurei (push) Successful in 5m6s
Test / ShareFS (push) Successful in 3m10s
Test / Sandbox (race detector) (push) Successful in 4m11s
Test / Hakurei (race detector) (push) Successful in 7m22s
Test / Flake checks (push) Successful in 1m11s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-15 14:36:12 +09:00
cat 8366cdd224 internal/rosa/package/spirv: spirv-tools 2026.1 to 2026.2
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 3m7s
Test / Hakurei (push) Successful in 4m40s
Test / ShareFS (push) Successful in 4m41s
Test / Sandbox (race detector) (push) Successful in 6m12s
Test / Hakurei (race detector) (push) Successful in 7m42s
Test / Flake checks (push) Successful in 1m16s
Upstream does not appear to understand the point of tags, so include relevant unreleased changes here.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-15 14:35:10 +09:00
cat 05f9939077 internal/rosa/package/glslang: 16.3.0 to 16.4.0
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m49s
Test / ShareFS (push) Successful in 4m4s
Test / Hakurei (push) Successful in 4m12s
Test / Sandbox (race detector) (push) Successful in 5m53s
Test / Hakurei (race detector) (push) Successful in 7m3s
Test / Flake checks (push) Successful in 1m36s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-15 14:31:45 +09:00
cat ae30f627dd internal/rosa/package/glib: 2.89.1 to 2.89.2
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 2m47s
Test / Hakurei (push) Successful in 4m5s
Test / ShareFS (push) Successful in 4m5s
Test / Sandbox (race detector) (push) Successful in 5m35s
Test / Hakurei (race detector) (push) Successful in 6m44s
Test / Flake checks (push) Successful in 1m10s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-15 01:41:12 +09:00
cat b4916dd431 internal/rosa/package/tamago: 1.26.4 to 1.26.5
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 2m43s
Test / Hakurei (push) Successful in 3m50s
Test / ShareFS (push) Successful in 3m53s
Test / Sandbox (race detector) (push) Successful in 5m42s
Test / Hakurei (race detector) (push) Successful in 6m40s
Test / Flake checks (push) Successful in 1m6s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-14 22:29:37 +09:00
cat 4cf235675a internal/rosa/meson: always prepend D
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 3m1s
Test / ShareFS (push) Successful in 4m37s
Test / Hakurei (push) Successful in 4m43s
Test / Sandbox (race detector) (push) Successful in 6m5s
Test / Hakurei (race detector) (push) Successful in 7m13s
Test / Flake checks (push) Successful in 1m6s
All flags in practice use this convention. An escape hatch is available by leaving the value empty.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-14 22:17:51 +09:00
cat 098943ab46 internal/rosa/meson: optionally use muon
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m51s
Test / ShareFS (push) Successful in 3m54s
Test / Sandbox (race detector) (push) Successful in 5m33s
Test / Hakurei (race detector) (push) Successful in 6m44s
Test / Hakurei (push) Successful in 2m23s
Test / Flake checks (push) Successful in 1m8s
This is a much faster implementation free of python dependency hell, however currently fails to handle symbol visibility correctly, so unable to default to on. This change also cleans up some meson arguments.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-14 21:45:07 +09:00
cat fb3df67ba6 internal/rosa/package: muon
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 2m51s
Test / ShareFS (push) Successful in 3m58s
Test / Hakurei (push) Successful in 4m14s
Test / Sandbox (race detector) (push) Successful in 5m37s
Test / Hakurei (race detector) (push) Successful in 6m41s
Test / Flake checks (push) Successful in 1m8s
Python-free meson drop-in replacement. Test suite still pulls in bootstrap python, but that is fine.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-14 20:09:41 +09:00
cat b1c882b4de internal/rosa/package/libucontext: 1.5.1 to 1.5.2
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 3m24s
Test / Hakurei (push) Successful in 4m42s
Test / ShareFS (push) Successful in 4m54s
Test / Sandbox (race detector) (push) Successful in 6m7s
Test / Hakurei (race detector) (push) Successful in 7m24s
Test / Flake checks (push) Successful in 1m8s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-14 17:48:55 +09:00
cat 0ed0d8abde internal/rosa/package/libpsl: 0.22.0 to 0.23.0
Test / Create distribution (push) Successful in 54s
Test / Sandbox (push) Successful in 3m8s
Test / Hakurei (push) Successful in 4m30s
Test / ShareFS (push) Successful in 4m31s
Test / Sandbox (race detector) (push) Successful in 6m23s
Test / Hakurei (race detector) (push) Successful in 7m48s
Test / Flake checks (push) Successful in 1m9s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-14 17:48:28 +09:00
cat 51e4426a4f internal/rosa: remove gawk
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m55s
Test / ShareFS (push) Successful in 3m58s
Test / Hakurei (push) Successful in 4m3s
Test / Sandbox (race detector) (push) Successful in 5m34s
Test / Hakurei (race detector) (push) Successful in 6m45s
Test / Flake checks (push) Successful in 1m10s
This change fully eliminates gawk.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-13 00:10:38 +09:00
cat 316edeb17b internal/rosa: fix GNU testsuite edge case
Test / Create distribution (push) Successful in 1m2s
Test / Sandbox (push) Successful in 3m2s
Test / ShareFS (push) Successful in 5m14s
Test / Sandbox (race detector) (push) Successful in 2m58s
Test / Hakurei (push) Successful in 3m6s
Test / Hakurei (race detector) (push) Successful in 4m5s
Test / Flake checks (push) Successful in 1m13s
For segments with a single test.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-12 22:37:57 +09:00
cat 8facae53c7 internal/rosa/package: replace gawk
Test / Create distribution (push) Successful in 1m1s
Test / Sandbox (push) Successful in 3m20s
Test / Hakurei (push) Successful in 4m54s
Test / ShareFS (push) Successful in 4m55s
Test / Sandbox (race detector) (push) Successful in 6m25s
Test / Hakurei (race detector) (push) Successful in 7m26s
Test / Flake checks (push) Successful in 1m21s
This replaces gawk in miscellaneous packages.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-12 22:09:56 +09:00
cat 7881bfd027 internal/rosa/package: awk
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 3m7s
Test / Hakurei (push) Successful in 4m9s
Test / ShareFS (push) Successful in 4m10s
Test / Sandbox (race detector) (push) Successful in 5m57s
Test / Hakurei (race detector) (push) Successful in 7m30s
Test / Flake checks (push) Successful in 1m17s
This should replace gawk in many cases.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-12 22:08:22 +09:00
cat 9e9469fe6c internal/rosa/package/go: disable test broken on arm64
Test / Create distribution (push) Successful in 1m3s
Test / Sandbox (push) Successful in 4m11s
Test / ShareFS (push) Successful in 5m43s
Test / Hakurei (push) Successful in 5m44s
Test / Sandbox (race detector) (push) Successful in 7m29s
Test / Hakurei (race detector) (push) Successful in 8m55s
Test / Flake checks (push) Successful in 2m45s
Not currently able to investigate the failure due to performance of the arm64 development machine.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-12 19:58:22 +09:00
cat b6d90eb8e0 internal/rosa/package/gnu: findutils 4.10.0 to 4.11.0
Test / Create distribution (push) Successful in 1m17s
Test / Sandbox (push) Successful in 3m15s
Test / ShareFS (push) Successful in 5m55s
Test / Hakurei (push) Successful in 6m13s
Test / Sandbox (race detector) (push) Successful in 8m40s
Test / Hakurei (race detector) (push) Successful in 11m4s
Test / Flake checks (push) Successful in 1m26s
Yet another broken gnulib test.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-12 19:34:02 +09:00
cat 879f911fd8 internal/rosa/package/p11-kit: 0.26.2 to 0.26.4
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 3m10s
Test / ShareFS (push) Successful in 4m36s
Test / Sandbox (race detector) (push) Successful in 5m58s
Test / Hakurei (race detector) (push) Successful in 7m10s
Test / Hakurei (push) Successful in 2m59s
Test / Flake checks (push) Successful in 3m33s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-12 19:21:39 +09:00
cat 1066fc0097 internal/rosa/package/meson: 1.11.1 to 1.11.2
Test / Create distribution (push) Successful in 51s
Test / Sandbox (push) Successful in 2m55s
Test / ShareFS (push) Successful in 4m26s
Test / Hakurei (push) Successful in 4m28s
Test / Sandbox (race detector) (push) Successful in 6m2s
Test / Hakurei (race detector) (push) Successful in 7m11s
Test / Flake checks (push) Successful in 1m31s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-12 19:21:15 +09:00
cat 3a3d8efb1e internal/rosa/package/python: early bootstrap variant
Test / Create distribution (push) Successful in 2m10s
Test / Sandbox (push) Successful in 6m44s
Test / ShareFS (push) Successful in 8m36s
Test / Sandbox (race detector) (push) Successful in 9m22s
Test / Hakurei (race detector) (push) Successful in 11m28s
Test / Hakurei (push) Successful in 2m25s
Test / Flake checks (push) Successful in 1m13s
This avoids pulling in python's insane dependency tree into the bootstrap path.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-11 21:13:44 +09:00
cat cb8c9e4e68 internal/rosa/package/git: disable more flaky tests
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 2m47s
Test / ShareFS (push) Successful in 3m51s
Test / Sandbox (race detector) (push) Successful in 5m36s
Test / Hakurei (race detector) (push) Successful in 6m41s
Test / Hakurei (push) Successful in 2m23s
Test / Flake checks (push) Successful in 1m6s
Discovered these during the most recent libffi-induced world rebuild.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-11 15:40:48 +09:00
cat 1c4a3b72bf internal/rosa/package/libffi: 3.7.0 to 3.5.2
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 2m55s
Test / ShareFS (push) Successful in 3m50s
Test / Hakurei (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 5m48s
Test / Hakurei (race detector) (push) Successful in 6m55s
Test / Flake checks (push) Successful in 1m11s
Appears to be the final non-contaminated release. This package cannot be safely blocked indefinitely like rsync and vim. This change discontinues frequent bumps and limits damage by regressions introduced by AI slop until long-term plans are decided.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-11 12:23:05 +09:00
cat fdca05487c internal/rosa/package/cmake: 4.3.4 to 4.4.0
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 2m53s
Test / ShareFS (push) Successful in 3m58s
Test / Sandbox (race detector) (push) Successful in 5m30s
Test / Hakurei (race detector) (push) Successful in 7m8s
Test / Hakurei (push) Successful in 2m20s
Test / Flake checks (push) Successful in 1m5s
This change also disables the bootstrap test because 4.4.0 broke the bootstrap test, and it makes little sense re-testing what has already succeeded.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 23:49:58 +09:00
cat 89db730bb9 internal/rosa/package/ncurses: enable deterministic archives
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 2m53s
Test / ShareFS (push) Successful in 3m54s
Test / Hakurei (push) Successful in 4m6s
Test / Sandbox (race detector) (push) Successful in 5m51s
Test / Hakurei (race detector) (push) Successful in 6m57s
Test / Flake checks (push) Successful in 1m7s
This is not done by default in upstream build system.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 17:48:32 +09:00
cat 5161fc24ec internal/rosa/package/go: 1.26.4 to 1.26.5
Test / Create distribution (push) Successful in 1m20s
Test / Sandbox (push) Successful in 3m35s
Test / ShareFS (push) Successful in 4m41s
Test / Hakurei (push) Successful in 4m48s
Test / Sandbox (race detector) (push) Successful in 6m23s
Test / Hakurei (race detector) (push) Successful in 7m12s
Test / Flake checks (push) Successful in 1m7s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 15:51:57 +09:00
cat e1f16e7720 internal/rosa: apply patches in specified order
Test / Create distribution (push) Successful in 1m1s
Test / Sandbox (push) Successful in 2m59s
Test / ShareFS (push) Successful in 4m4s
Test / Hakurei (push) Successful in 4m15s
Test / Sandbox (race detector) (push) Successful in 5m40s
Test / Hakurei (race detector) (push) Successful in 6m45s
Test / Flake checks (push) Successful in 1m30s
This seems more intuitive than letting the filesystem decide, and having to use awkward names.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 15:39:55 +09:00
cat 8e9b3a2ed1 internal/rosa/go: migrate to azalea
Test / Create distribution (push) Successful in 1m3s
Test / Sandbox (push) Successful in 3m9s
Test / Hakurei (push) Successful in 4m13s
Test / ShareFS (push) Successful in 4m13s
Test / Sandbox (race detector) (push) Successful in 5m41s
Test / Hakurei (race detector) (push) Successful in 6m50s
Test / Flake checks (push) Successful in 1m15s
Bootstrap still remains native, however the final toolchain is migrated to azalea.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 14:48:54 +09:00
cat fd0a81b304 internal/rosa/package/libffi: 3.6.0 to 3.7.0
Test / Create distribution (push) Successful in 59s
Test / ShareFS (push) Successful in 6m32s
Test / Sandbox (race detector) (push) Successful in 7m23s
Test / Hakurei (race detector) (push) Successful in 8m36s
Test / Sandbox (push) Successful in 1m31s
Test / Hakurei (push) Successful in 2m33s
Test / Flake checks (push) Successful in 1m17s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 13:41:02 +09:00
cat 1d6d89a11a internal/rosa/package/go: bootstrap 1.25.11 to 1.25.12
Test / Create distribution (push) Successful in 1m22s
Test / Sandbox (push) Successful in 5m47s
Test / ShareFS (push) Successful in 7m0s
Test / Sandbox (race detector) (push) Successful in 7m56s
Test / Hakurei (race detector) (push) Successful in 10m6s
Test / Hakurei (push) Successful in 2m59s
Test / Flake checks (push) Successful in 1m14s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 02:37:38 +09:00
cat 6a6fdab92d internal/rosa/package/x: xwayland 24.1.12 to 24.1.13
Test / Create distribution (push) Successful in 1m27s
Test / Sandbox (push) Successful in 6m24s
Test / Hakurei (push) Successful in 9m39s
Test / ShareFS (push) Successful in 8m13s
Test / Sandbox (race detector) (push) Successful in 9m29s
Test / Hakurei (race detector) (push) Successful in 11m41s
Test / Flake checks (push) Successful in 1m19s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 02:37:15 +09:00
cat 67c67574e8 internal/rosa/package/x: xserver 21.1.23 to 21.1.24
Test / Create distribution (push) Successful in 1m16s
Test / Sandbox (push) Successful in 6m7s
Test / Hakurei (push) Successful in 9m42s
Test / ShareFS (push) Successful in 8m55s
Test / Sandbox (race detector) (push) Successful in 10m21s
Test / Hakurei (race detector) (push) Successful in 3m56s
Test / Flake checks (push) Successful in 1m10s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 02:36:53 +09:00
cat 79be25433b internal/rosa/package/x: libXfont2 2.0.7 to 2.0.8
Test / Create distribution (push) Successful in 1m28s
Test / Sandbox (push) Successful in 4m42s
Test / ShareFS (push) Successful in 6m15s
Test / Sandbox (race detector) (push) Successful in 8m22s
Test / Hakurei (race detector) (push) Successful in 12m18s
Test / Hakurei (push) Successful in 2m59s
Test / Flake checks (push) Successful in 1m16s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 02:36:24 +09:00
cat a4d78e8a32 internal/rosa/package/python: hatchling 1.17.0 to 1.17.1
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 4m38s
Test / Hakurei (push) Successful in 9m19s
Test / Sandbox (race detector) (push) Successful in 7m50s
Test / ShareFS (push) Successful in 7m46s
Test / Hakurei (race detector) (push) Successful in 11m21s
Test / Flake checks (push) Successful in 2m53s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 02:35:41 +09:00
cat ab3c37f75a internal/rosa/package/wlroots: 0.20.1 to 0.20.2
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 3m23s
Test / Hakurei (push) Successful in 8m1s
Test / Sandbox (race detector) (push) Successful in 6m20s
Test / ShareFS (push) Successful in 6m30s
Test / Hakurei (race detector) (push) Successful in 11m34s
Test / Flake checks (push) Successful in 3m2s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 02:35:07 +09:00
cat e6757fe254 internal/rosa/package/wayland: 1.25.0 to 1.25.91
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 4m13s
Test / Hakurei (push) Successful in 7m1s
Test / ShareFS (push) Successful in 7m18s
Test / Sandbox (race detector) (push) Successful in 8m2s
Test / Hakurei (race detector) (push) Successful in 11m27s
Test / Flake checks (push) Successful in 3m12s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 02:34:32 +09:00
cat b0f0d9e060 internal/rosa/package/libva: 2.24.0 to 2.24.1
Test / Create distribution (push) Successful in 1m1s
Test / Sandbox (push) Successful in 3m34s
Test / ShareFS (push) Successful in 5m55s
Test / Sandbox (race detector) (push) Successful in 8m0s
Test / Hakurei (race detector) (push) Successful in 11m20s
Test / Hakurei (push) Successful in 4m8s
Test / Flake checks (push) Successful in 2m19s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 02:33:59 +09:00
cat ce58895a0d internal/rosa/package/fontconfig: 2.18.1 to 2.18.2
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 3m10s
Test / Hakurei (push) Successful in 5m0s
Test / ShareFS (push) Successful in 5m16s
Test / Sandbox (race detector) (push) Successful in 7m33s
Test / Hakurei (race detector) (push) Successful in 10m34s
Test / Flake checks (push) Successful in 2m59s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-10 02:33:16 +09:00
cat 3c78551b24 cmd/mbf: expose target load average
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 2m56s
Test / ShareFS (push) Successful in 3m55s
Test / Hakurei (push) Successful in 4m0s
Test / Sandbox (race detector) (push) Successful in 5m34s
Test / Hakurei (race detector) (push) Successful in 6m47s
Test / Flake checks (push) Successful in 1m5s
There are often good reason to override this.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-09 20:07:16 +09:00
cat 223e8e56b3 internal/rosa/meson: respect preferred loadavg target and job count
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 2m50s
Test / ShareFS (push) Successful in 3m55s
Test / Hakurei (push) Successful in 4m3s
Test / Sandbox (race detector) (push) Successful in 5m39s
Test / Hakurei (race detector) (push) Successful in 6m41s
Test / Flake checks (push) Successful in 1m5s
This was missed when first implementing jobs and was missed again implementing loadavg.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-09 19:37:08 +09:00
cat 17383ab353 internal/rosa/package/gnu: disable flaky coreutils test
Test / Flake checks (push) Successful in 2m43s
Test / ShareFS (push) Successful in 57s
Test / Sandbox (push) Successful in 1m20s
Test / Sandbox (race detector) (push) Successful in 1m23s
Test / Hakurei (push) Successful in 1m26s
Test / Hakurei (race detector) (push) Successful in 1m31s
Test / Create distribution (push) Successful in 46s
Another flaky test, once disabled but removed during an upgrade.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-09 10:50:53 +09:00
cat 237e793895 internal/rosa: respect preferred loadavg target
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 2m54s
Test / ShareFS (push) Successful in 3m57s
Test / Hakurei (push) Successful in 4m4s
Test / Sandbox (race detector) (push) Successful in 5m36s
Test / Hakurei (race detector) (push) Successful in 6m58s
Test / Flake checks (push) Successful in 1m11s
This generally improves build performance and system responsiveness.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-09 10:08:08 +09:00
cat 6cfd8fb934 internal/pkg: loadavg target in container environment
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 3m2s
Test / ShareFS (push) Successful in 3m58s
Test / Hakurei (push) Successful in 4m5s
Test / Sandbox (race detector) (push) Successful in 5m29s
Test / Hakurei (race detector) (push) Successful in 6m40s
Test / Flake checks (push) Successful in 1m4s
This exposes preferred loadavg target to the container initial process.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-09 09:45:43 +09:00
cat 2f1534853a internal/pkg: consolidate cache attributes
Test / Create distribution (push) Successful in 54s
Test / Sandbox (push) Successful in 2m58s
Test / ShareFS (push) Successful in 3m56s
Test / Hakurei (push) Successful in 3m59s
Test / Sandbox (race detector) (push) Successful in 5m31s
Test / Hakurei (race detector) (push) Successful in 6m38s
Test / Flake checks (push) Successful in 1m5s
This makes the interface stable.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-09 09:34:27 +09:00
cat 3f8e111d1c configure Azalea language detection
Test / Create distribution (push) Successful in 22s
Test / Sandbox (push) Successful in 1m5s
Test / Hakurei (push) Successful in 4m16s
Test / ShareFS (push) Successful in 4m18s
Test / Sandbox (race detector) (push) Successful in 5m34s
Test / Hakurei (race detector) (push) Successful in 6m32s
Test / Flake checks (push) Successful in 1m13s
This is not likely to be upstreamed anywhere, any time soon, so configure it here.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-09 03:13:11 +09:00
cat 9fae451dc0 internal/rosa/meson: set timeout multiplier
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 2m52s
Test / ShareFS (push) Successful in 3m54s
Test / Hakurei (push) Successful in 4m7s
Test / Sandbox (race detector) (push) Successful in 5m36s
Test / Hakurei (race detector) (push) Successful in 6m52s
Test / Flake checks (push) Successful in 1m11s
Current meson-based spurious test failures are generally always caused by timeouts under load, so mitigate that here.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-09 03:01:07 +09:00
cat e3666cda21 internal/rosa/make: run in hardcoded directory
Test / Create distribution (push) Successful in 1m7s
Test / Sandbox (push) Successful in 3m23s
Test / ShareFS (push) Successful in 6m2s
Test / Hakurei (push) Successful in 6m16s
Test / Sandbox (race detector) (push) Successful in 7m33s
Test / Hakurei (race detector) (push) Successful in 8m35s
Test / Flake checks (push) Successful in 1m10s
This actually eliminates some of the autotools nondeterminism, as autotools is not capable of stripping build pathnames.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-08 21:48:47 +09:00
cat 9c51805b47 internal/rosa/package/gnu: disable flaky coreutils tests
Test / Create distribution (push) Successful in 2m22s
Test / Sandbox (push) Successful in 4m50s
Test / ShareFS (push) Successful in 6m14s
Test / Hakurei (push) Successful in 6m17s
Test / Sandbox (race detector) (push) Successful in 7m32s
Test / Hakurei (race detector) (push) Successful in 8m47s
Test / Flake checks (push) Successful in 1m10s
These are huge and have incomprehensible output. Probability of failure increases under load, so disable them.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-08 21:31:38 +09:00
cat 3dca68fc95 cmd/mbf: validate build determinism
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 3m2s
Test / ShareFS (push) Successful in 6m4s
Test / Hakurei (push) Successful in 6m15s
Test / Sandbox (race detector) (push) Successful in 7m31s
Test / Hakurei (race detector) (push) Successful in 8m49s
Test / Flake checks (push) Successful in 1m17s
This rebuilds a package repeatedly and compares outcomes.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-08 21:28:21 +09:00
cat 6495118165 cmd/mbf: print all available handles
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 2m48s
Test / ShareFS (push) Successful in 4m4s
Test / Hakurei (push) Successful in 4m12s
Test / Sandbox (race detector) (push) Successful in 5m44s
Test / Hakurei (race detector) (push) Successful in 6m50s
Test / Flake checks (push) Successful in 1m5s
Useful for scripting.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-08 15:30:27 +09:00
cat 472849cfd6 internal/pkg: optionally force implementation entry
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 2m53s
Test / ShareFS (push) Successful in 3m56s
Test / Hakurei (push) Successful in 4m4s
Test / Sandbox (race detector) (push) Successful in 5m32s
Test / Hakurei (race detector) (push) Successful in 6m45s
Test / Flake checks (push) Successful in 1m20s
For validation of build determinism.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-08 15:26:42 +09:00
cat 3c6e9b3d05 internal/pkg: expose cure whence
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 3m1s
Test / ShareFS (push) Successful in 3m53s
Test / Hakurei (push) Successful in 4m6s
Test / Sandbox (race detector) (push) Successful in 5m34s
Test / Hakurei (race detector) (push) Successful in 6m40s
Test / Flake checks (push) Successful in 1m5s
Useful for cure determinism validation of KindExec.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-08 14:19:17 +09:00
cat aa5e77ef27 internal/rosa: populate mirror snapshot
Test / Create distribution (push) Successful in 54s
Test / Sandbox (push) Successful in 2m52s
Test / ShareFS (push) Successful in 3m54s
Test / Hakurei (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 5m45s
Test / Hakurei (race detector) (push) Successful in 6m38s
Test / Flake checks (push) Successful in 1m10s
This produces the same structure served by the dynamic server.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-07 21:14:57 +09:00
cat 76360979f9 internal/rosa: mirror response write methods
Test / Create distribution (push) Successful in 49s
Test / Sandbox (push) Successful in 2m52s
Test / ShareFS (push) Successful in 3m54s
Test / Hakurei (push) Successful in 4m4s
Test / Sandbox (race detector) (push) Successful in 5m39s
Test / Hakurei (race detector) (push) Successful in 6m42s
Test / Flake checks (push) Successful in 1m12s
For the fs.FS implementation and static publishing.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-07 20:18:18 +09:00
cat 6d55ee536e test: move nix files
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 2m53s
Test / ShareFS (push) Successful in 3m51s
Test / Hakurei (push) Successful in 4m11s
Test / Sandbox (race detector) (push) Successful in 5m29s
Test / Hakurei (race detector) (push) Successful in 6m41s
Test / Flake checks (push) Successful in 1m11s
These are too much clutter. Move them to test directory until the test suite replacement is upstreamed.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-07 18:56:27 +09:00
cat c8e8651694 cmd/mbf: shallow by default
Test / Create distribution (push) Successful in 1m3s
Test / Sandbox (push) Successful in 2m58s
Test / ShareFS (push) Successful in 4m6s
Test / Hakurei (push) Successful in 4m14s
Test / Sandbox (race detector) (push) Successful in 5m41s
Test / Hakurei (race detector) (push) Successful in 6m53s
Test / Flake checks (push) Successful in 1m7s
This is going to be used most of the time, with --deep only useful for fetching bootstrap artifacts.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-07 16:39:38 +09:00
cat aa5d38981d internal/pkg: optional shallow external cure
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 2m54s
Test / ShareFS (push) Successful in 4m6s
Test / Hakurei (push) Successful in 4m12s
Test / Sandbox (race detector) (push) Successful in 5m49s
Test / Hakurei (race detector) (push) Successful in 6m51s
Test / Flake checks (push) Successful in 1m22s
This saves time and is often more practical even for package maintainers.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-07 16:35:08 +09:00
cat b08feac26c internal/rosa/package: ipmitool
Test / Create distribution (push) Successful in 1m1s
Test / Sandbox (push) Successful in 2m54s
Test / Hakurei (push) Successful in 4m2s
Test / ShareFS (push) Successful in 4m1s
Test / Sandbox (race detector) (push) Successful in 5m43s
Test / Hakurei (race detector) (push) Successful in 6m55s
Test / Flake checks (push) Successful in 1m29s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-07 15:03:18 +09:00
cat 810b806a15 cmd/app: omit hidden files
Test / Create distribution (push) Successful in 1m4s
Test / Sandbox (push) Successful in 2m58s
Test / ShareFS (push) Successful in 4m1s
Test / Hakurei (push) Successful in 4m11s
Test / Sandbox (race detector) (push) Successful in 5m37s
Test / Hakurei (race detector) (push) Successful in 6m48s
Test / Flake checks (push) Successful in 1m9s
This avoids vim swap files breaking scripts.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-07 13:26:58 +09:00
cat 4a42657d88 internal/rosa/package/gnu: disable sed flaky test
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 2m45s
Test / ShareFS (push) Successful in 3m55s
Test / Hakurei (push) Successful in 3m59s
Test / Sandbox (race detector) (push) Successful in 5m41s
Test / Hakurei (race detector) (push) Successful in 6m46s
Test / Flake checks (push) Successful in 3m1s
This is causing way too many spurious failures.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-05 23:02:02 +09:00
cat f0b6659865 internal/rosa/package/kernel: 6.18.37 to 6.18.38
Test / Sandbox (push) Successful in 3m55s
Test / Create distribution (push) Successful in 58s
Test / Hakurei (push) Successful in 5m46s
Test / Sandbox (race detector) (push) Successful in 4m54s
Test / ShareFS (push) Successful in 3m41s
Test / Hakurei (race detector) (push) Successful in 8m15s
Test / Flake checks (push) Successful in 1m8s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-05 18:58:28 +09:00
cat a8ffaa20e0 internal/rosa/package/hwdata: 0.408 to 0.409
Test / Create distribution (push) Successful in 1m2s
Test / Sandbox (push) Successful in 3m13s
Test / Hakurei (push) Successful in 5m24s
Test / ShareFS (push) Successful in 5m29s
Test / Sandbox (race detector) (push) Successful in 7m4s
Test / Hakurei (race detector) (push) Successful in 8m47s
Test / Flake checks (push) Successful in 1m10s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-05 18:57:40 +09:00
cat fb62ae00e4 internal/rosa/package/python: setuptools 82.0.1 to 83.0.0
Test / Create distribution (push) Successful in 1m2s
Test / Sandbox (push) Successful in 3m8s
Test / Hakurei (push) Successful in 4m52s
Test / ShareFS (push) Successful in 4m58s
Test / Sandbox (race detector) (push) Successful in 7m16s
Test / Hakurei (race detector) (push) Successful in 8m56s
Test / Flake checks (push) Successful in 1m10s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-05 18:57:19 +09:00
cat 512d9b95bd internal/pkg: remove status acquisition from extern helper
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 2m59s
Test / Hakurei (push) Successful in 4m2s
Test / ShareFS (push) Successful in 4m4s
Test / Sandbox (race detector) (push) Successful in 5m42s
Test / Hakurei (race detector) (push) Successful in 6m45s
Test / Flake checks (push) Successful in 1m11s
Doing this together just makes it awkward to query status early, having to deal with cleaning up.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-04 23:46:50 +09:00
cat 5bf87561f5 internal/pkg: move concurrent cure implementation
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 2m58s
Test / ShareFS (push) Successful in 3m59s
Test / Hakurei (push) Successful in 4m52s
Test / Sandbox (race detector) (push) Successful in 5m30s
Test / Hakurei (race detector) (push) Successful in 6m40s
Test / Flake checks (push) Successful in 1m13s
This is useful independent of cure and might replace the Collect hack.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-04 23:27:12 +09:00
cat dde69dde61 internal/pkg: rename inputs method
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 2m57s
Test / ShareFS (push) Successful in 3m50s
Test / Hakurei (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 5m29s
Test / Hakurei (race detector) (push) Successful in 6m42s
Test / Flake checks (push) Successful in 1m12s
Inputs is more correct than dependencies in the current terminology.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-02 23:21:31 +09:00
cat 3ba6609444 internal/pkg: move outcome dereferencing
Test / Create distribution (push) Successful in 1m1s
Test / Sandbox (push) Successful in 3m3s
Test / Hakurei (push) Successful in 4m0s
Test / ShareFS (push) Successful in 4m7s
Test / Sandbox (race detector) (push) Successful in 5m33s
Test / Hakurei (race detector) (push) Successful in 6m40s
Test / Flake checks (push) Successful in 1m18s
This prepares substitute computation for shallow extern replacements.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-02 22:52:37 +09:00
cat 6dcc2fdc17 internal/rosa/package/mesa: 26.1.3 to 26.1.4
Test / Create distribution (push) Successful in 1m8s
Test / Sandbox (push) Successful in 3m28s
Test / ShareFS (push) Successful in 5m2s
Test / Hakurei (push) Successful in 5m4s
Test / Sandbox (race detector) (push) Successful in 6m18s
Test / Hakurei (race detector) (push) Successful in 7m30s
Test / Flake checks (push) Successful in 1m12s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-02 22:37:31 +09:00
cat c553b74807 internal/rosa/package/libva: 2.23.0 to 2.24.0
Test / Create distribution (push) Successful in 1m12s
Test / Sandbox (push) Successful in 3m11s
Test / ShareFS (push) Successful in 4m36s
Test / Hakurei (push) Successful in 4m41s
Test / Sandbox (race detector) (push) Successful in 6m19s
Test / Hakurei (race detector) (push) Successful in 7m39s
Test / Flake checks (push) Successful in 1m16s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-02 22:35:57 +09:00
cat 8c853c3eb6 internal/rosa/package/libseccomp: 2.6.0 to 2.6.1
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 2m55s
Test / ShareFS (push) Successful in 3m59s
Test / Hakurei (push) Successful in 4m9s
Test / Sandbox (race detector) (push) Successful in 5m57s
Test / Hakurei (race detector) (push) Successful in 7m9s
Test / Flake checks (push) Successful in 1m36s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-02 22:30:13 +09:00
cat d2f322e911 internal/rosa/package/gnutls: fix arm64-specific configure flag
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 2m58s
Test / Hakurei (push) Successful in 4m3s
Test / ShareFS (push) Successful in 4m4s
Test / Sandbox (race detector) (push) Successful in 5m29s
Test / Hakurei (race detector) (push) Successful in 6m45s
Test / Flake checks (push) Successful in 1m7s
Automatic prefix does not happen for the value string.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-02 20:58:23 +09:00
cat b538c69e01 internal/pkg: cache extern responses
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m24s
Test / ShareFS (push) Successful in 3m27s
Test / Hakurei (push) Successful in 3m46s
Test / Sandbox (race detector) (push) Successful in 5m1s
Test / Hakurei (race detector) (push) Successful in 6m15s
Test / Flake checks (push) Successful in 1m19s
This prepares substitute computation for shallow extern replacements.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-02 20:08:28 +09:00
cat c921ba4680 internal/rosa/package/qemu: set TIMEOUT_MULTIPLIER
Test / Create distribution (push) Successful in 1m2s
Test / ShareFS (push) Successful in 9m59s
Test / Sandbox (push) Successful in 1m40s
Test / Sandbox (race detector) (push) Successful in 2m29s
Test / Hakurei (push) Successful in 2m47s
Test / Hakurei (race detector) (push) Successful in 3m44s
Test / Flake checks (push) Successful in 1m13s
This uses the alpine linux value for now. The default timeouts make the test suite flaky under load.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-01 21:52:56 +09:00
cat 7404bf6025 internal/rosa/package/noto: 2026.06.01 to 2026.07.01
Test / Create distribution (push) Successful in 1m5s
Test / Sandbox (push) Successful in 2m59s
Test / ShareFS (push) Successful in 4m2s
Test / Hakurei (push) Successful in 4m15s
Test / Sandbox (race detector) (push) Successful in 5m42s
Test / Hakurei (race detector) (push) Successful in 6m49s
Test / Flake checks (push) Successful in 1m10s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-01 15:42:08 +09:00
cat 3975dd3e0f internal/rosa: create /bin symlinks via helper
Test / Create distribution (push) Successful in 3m19s
Test / Sandbox (push) Successful in 7m58s
Test / ShareFS (push) Successful in 10m31s
Test / Hakurei (push) Successful in 11m0s
Test / Sandbox (race detector) (push) Successful in 12m8s
Test / Hakurei (race detector) (push) Successful in 6m4s
Test / Flake checks (push) Successful in 2m47s
This centralises the workaround for surprisingly common buggy scripts with nonstandard hardcoded paths.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-01 15:03:26 +09:00
cat 3ab7116b29 internal/rosa/package/kernel: 6.12.94 to 6.18.37
Test / Create distribution (push) Successful in 1m44s
Test / ShareFS (push) Successful in 11m10s
Test / Sandbox (push) Successful in 1m52s
Test / Sandbox (race detector) (push) Successful in 2m50s
Test / Hakurei (push) Successful in 3m5s
Test / Hakurei (race detector) (push) Successful in 4m4s
Test / Flake checks (push) Successful in 1m15s
Finally jumping from 6.12 to 6.18, and the patches can be dropped.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-07-01 02:32:20 +09:00
cat 9be165d6ee internal/rosa/package/qemu: 11.0.1 to 11.0.2
Test / Create distribution (push) Successful in 1m2s
Test / Sandbox (push) Successful in 3m15s
Test / ShareFS (push) Successful in 5m52s
Test / Sandbox (race detector) (push) Successful in 8m40s
Test / Hakurei (race detector) (push) Successful in 10m27s
Test / Hakurei (push) Successful in 2m34s
Test / Flake checks (push) Successful in 1m12s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-30 19:53:21 +09:00
cat 1c55e7c772 internal/rosa/package/python: vcs-versioning 2.2.0 to 2.2.2
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 3m6s
Test / ShareFS (push) Successful in 4m20s
Test / Hakurei (push) Successful in 4m25s
Test / Sandbox (race detector) (push) Successful in 5m59s
Test / Hakurei (race detector) (push) Successful in 8m35s
Test / Flake checks (push) Successful in 3m58s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-30 19:51:02 +09:00
cat a981d185cf internal/rosa/package/git: 2.54.0 to 2.55.0
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 2m53s
Test / ShareFS (push) Successful in 4m13s
Test / Hakurei (push) Successful in 4m17s
Test / Sandbox (race detector) (push) Successful in 6m2s
Test / Hakurei (race detector) (push) Successful in 3m29s
Test / Flake checks (push) Successful in 1m33s
For some reason rust is now forced on by default without any check whatsoever. No idea why the maintainers think it was such a good idea to be so in your face.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-30 19:43:25 +09:00
cat d91951ca97 internal/rosa/package/acl: 2.3.2 to 2.4.0
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 2m17s
Test / Hakurei (push) Successful in 5m22s
Test / ShareFS (push) Successful in 4m20s
Test / Sandbox (race detector) (push) Successful in 5m23s
Test / Hakurei (race detector) (push) Successful in 8m3s
Test / Flake checks (push) Successful in 1m17s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-30 19:16:42 +09:00
cat 09a2ffc3bc internal/rosa/package/acl: attr 2.5.2 to 2.6.0
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 3m3s
Test / Hakurei (push) Successful in 5m1s
Test / ShareFS (push) Successful in 5m4s
Test / Sandbox (race detector) (push) Successful in 7m2s
Test / Hakurei (race detector) (push) Successful in 8m14s
Test / Flake checks (push) Successful in 1m21s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-30 19:16:09 +09:00
cat a6444658da internal/rosa/package/json-c: 0.18-20240915 to 0.19-20260627
Test / Create distribution (push) Successful in 1m2s
Test / Sandbox (push) Successful in 3m24s
Test / Hakurei (push) Successful in 5m0s
Test / ShareFS (push) Successful in 5m3s
Test / Sandbox (race detector) (push) Successful in 6m17s
Test / Hakurei (race detector) (push) Successful in 7m44s
Test / Flake checks (push) Successful in 1m10s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-30 19:06:41 +09:00
cat ed5615033c internal/rosa/package/gnu: parallel 20260522 to 20260622
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 3m8s
Test / ShareFS (push) Successful in 4m46s
Test / Sandbox (race detector) (push) Successful in 6m30s
Test / Hakurei (race detector) (push) Successful in 7m55s
Test / Hakurei (push) Successful in 2m51s
Test / Flake checks (push) Successful in 1m14s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-30 19:06:13 +09:00
cat d1319a497c internal/rosa: handle nil source
Test / Create distribution (push) Successful in 1m1s
Test / Sandbox (push) Successful in 3m15s
Test / Hakurei (push) Successful in 4m39s
Test / ShareFS (push) Successful in 4m52s
Test / Sandbox (race detector) (push) Successful in 6m7s
Test / Hakurei (race detector) (push) Successful in 7m23s
Test / Flake checks (push) Successful in 1m6s
Source is not always required. This improves flexibility.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-28 18:02:54 +09:00
cat cf7c34555c cmd/earlyinit: improve error messages
Test / Create distribution (push) Successful in 1m1s
Test / Sandbox (push) Successful in 2m55s
Test / Hakurei (push) Successful in 4m20s
Test / ShareFS (push) Successful in 4m26s
Test / Sandbox (race detector) (push) Successful in 6m11s
Test / Hakurei (race detector) (push) Successful in 7m22s
Test / Flake checks (push) Successful in 1m12s
This improves readability, especially on a small display.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-28 18:01:51 +09:00
cat d96eecded0 internal/rosa/package/pango: 1.57.1 to 1.58.0
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 3m0s
Test / ShareFS (push) Successful in 3m52s
Test / Hakurei (push) Successful in 4m5s
Test / Sandbox (race detector) (push) Successful in 5m31s
Test / Hakurei (race detector) (push) Successful in 6m43s
Test / Flake checks (push) Successful in 1m5s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-27 15:52:23 +09:00
cat 6863bcafd1 cmd/app: optional insecure options
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 2m58s
Test / ShareFS (push) Successful in 3m52s
Test / Hakurei (push) Successful in 4m1s
Test / Sandbox (race detector) (push) Successful in 5m35s
Test / Hakurei (race detector) (push) Successful in 6m39s
Test / Flake checks (push) Successful in 1m11s
These are useful for very specific cases by the maintainer. No app should ever require this.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-26 21:56:07 +09:00
cat 39f023d0e5 internal/rosa/package/glib: 2.89.0 to 2.89.1
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 3m5s
Test / ShareFS (push) Successful in 4m16s
Test / Hakurei (push) Successful in 4m22s
Test / Sandbox (race detector) (push) Successful in 5m56s
Test / Hakurei (race detector) (push) Successful in 6m53s
Test / Flake checks (push) Successful in 1m14s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-26 11:33:10 +09:00
cat a8a2f692e7 internal/rosa/package/libexpat: 2.8.1 to 2.8.2
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 2m56s
Test / ShareFS (push) Successful in 4m18s
Test / Hakurei (push) Successful in 4m22s
Test / Sandbox (race detector) (push) Successful in 5m48s
Test / Hakurei (race detector) (push) Successful in 7m3s
Test / Flake checks (push) Successful in 1m22s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-26 11:29:27 +09:00
cat 19f24c7206 internal/rosa/package/python: setuptools-scm 10.1.2 to 10.2.0
Test / Sandbox (push) Successful in 4m28s
Test / Create distribution (push) Successful in 1m3s
Test / ShareFS (push) Successful in 6m15s
Test / Hakurei (push) Successful in 6m18s
Test / Sandbox (race detector) (push) Successful in 7m33s
Test / Hakurei (race detector) (push) Successful in 8m52s
Test / Flake checks (push) Successful in 1m13s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-25 20:29:18 +09:00
cat 320432774a internal/rosa/package/python: vcs-versioning 2.1.2 to 2.2.0
Test / Create distribution (push) Successful in 1m16s
Test / Sandbox (push) Successful in 4m41s
Test / Hakurei (push) Successful in 6m2s
Test / ShareFS (push) Successful in 6m7s
Test / Sandbox (race detector) (push) Successful in 7m46s
Test / Hakurei (race detector) (push) Successful in 9m12s
Test / Flake checks (push) Successful in 1m13s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-25 20:28:48 +09:00
cat 0721b0fe6d internal/rosa/package/curl: 8.20.0 to 8.21.0
Test / Create distribution (push) Successful in 1m16s
Test / Sandbox (push) Successful in 4m7s
Test / Hakurei (push) Successful in 6m28s
Test / ShareFS (push) Successful in 6m28s
Test / Sandbox (race detector) (push) Successful in 7m40s
Test / Hakurei (race detector) (push) Successful in 9m0s
Test / Flake checks (push) Successful in 1m7s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-25 14:08:07 +09:00
cat 418e4a874d internal/rosa/package/libpsl: 0.21.5 to 0.22.0
Test / Create distribution (push) Successful in 1m6s
Test / Sandbox (push) Successful in 4m5s
Test / Hakurei (push) Successful in 6m17s
Test / ShareFS (push) Successful in 5m55s
Test / Sandbox (race detector) (push) Successful in 7m21s
Test / Hakurei (race detector) (push) Successful in 8m58s
Test / Flake checks (push) Successful in 1m8s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-25 14:07:38 +09:00
cat 8378e7a2c9 internal/rosa/package/vim: annotate blocked update
Test / Create distribution (push) Successful in 54s
Test / Sandbox (push) Successful in 3m3s
Test / Hakurei (push) Successful in 4m41s
Test / ShareFS (push) Successful in 4m50s
Test / Sandbox (race detector) (push) Successful in 6m46s
Test / Hakurei (race detector) (push) Successful in 8m52s
Test / Flake checks (push) Successful in 1m23s
Releases are unreasonably frequent, and the package is never exposed to the end user and never expected to run unconfined or consume untrusted input. Additionally, upstream is accepting AI slop.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-25 14:06:03 +09:00
cat 6210c9f272 internal/rosa/package: noto
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m42s
Test / ShareFS (push) Successful in 3m49s
Test / Hakurei (push) Successful in 4m1s
Test / Sandbox (race detector) (push) Successful in 5m33s
Test / Hakurei (race detector) (push) Successful in 6m43s
Test / Flake checks (push) Successful in 1m7s
Internationalisation is required anyway, so just package the entire noto fonts.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 10:45:01 +09:00
cat c2038fa925 internal/rosa/package: rename
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m52s
Test / ShareFS (push) Successful in 3m56s
Test / Hakurei (push) Successful in 4m6s
Test / Sandbox (race detector) (push) Successful in 5m34s
Test / Hakurei (race detector) (push) Successful in 6m45s
Test / Flake checks (push) Successful in 1m20s
Useful for packaging.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 10:39:38 +09:00
cat d797cca1f2 internal/rosa/package/python: vcs-versioning 2.1.1 to 2.1.2
Test / ShareFS (push) Successful in 32s
Test / Sandbox (race detector) (push) Successful in 36s
Test / Sandbox (push) Successful in 40s
Test / Create distribution (push) Successful in 58s
Test / Hakurei (race detector) (push) Successful in 1m13s
Test / Hakurei (push) Successful in 3m0s
Test / Flake checks (push) Successful in 1m16s
Another bug fix release already. Turns out upstream is using AI slop.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 09:52:59 +09:00
cat 2a51b433c8 cmd/app: exclude /tmp/ for X11 pathname socket
Test / Create distribution (push) Successful in 1m1s
Test / Sandbox (push) Successful in 2m57s
Test / ShareFS (push) Successful in 4m1s
Test / Hakurei (push) Successful in 4m3s
Test / Sandbox (race detector) (push) Successful in 5m41s
Test / Hakurei (race detector) (push) Successful in 6m37s
Test / Flake checks (push) Successful in 1m10s
This would otherwise cover the pathname socket.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 08:49:16 +09:00
cat e5ce36532b internal/rosa/package/toybox: 0.8.13 to 0.8.14
Test / Create distribution (push) Successful in 54s
Test / Sandbox (push) Successful in 2m56s
Test / ShareFS (push) Successful in 5m1s
Test / Hakurei (push) Successful in 5m11s
Test / Sandbox (race detector) (push) Successful in 7m10s
Test / Hakurei (race detector) (push) Successful in 7m54s
Test / Flake checks (push) Successful in 1m13s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 06:41:56 +09:00
cat 4c647388b0 internal/rosa/package/hakurei: 0.4.4 to 0.4.5
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 3m1s
Test / ShareFS (push) Successful in 3m57s
Test / Hakurei (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 5m31s
Test / Hakurei (race detector) (push) Successful in 6m39s
Test / Flake checks (push) Successful in 1m8s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 06:28:56 +09:00
cat 3a5f4af114 release: 0.4.5
Release / Create release (push) Successful in 1m0s
Test / Flake checks (push) Successful in 1m11s
Test / Create distribution (push) Successful in 30s
Test / ShareFS (push) Successful in 36s
Test / Hakurei (push) Successful in 43s
Test / Sandbox (race detector) (push) Successful in 43s
Test / Sandbox (push) Successful in 43s
Test / Hakurei (race detector) (push) Successful in 48s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 06:18:02 +09:00
cat 6195260480 internal/rosa/package/firmware: 20260519 to 20260622
Test / Create distribution (push) Successful in 1m2s
Test / Sandbox (push) Successful in 4m30s
Test / ShareFS (push) Successful in 6m7s
Test / Hakurei (push) Successful in 7m6s
Test / Sandbox (race detector) (push) Successful in 7m5s
Test / Hakurei (race detector) (push) Successful in 9m13s
Test / Flake checks (push) Successful in 1m15s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 06:11:20 +09:00
cat 21044d5a60 internal/rosa/package/vim: 9.2.0461 to 9.2.0707
Test / Create distribution (push) Successful in 1m4s
Test / Sandbox (push) Successful in 3m27s
Test / Hakurei (push) Successful in 8m16s
Test / Sandbox (race detector) (push) Successful in 6m18s
Test / ShareFS (push) Successful in 6m45s
Test / Hakurei (race detector) (push) Successful in 10m16s
Test / Flake checks (push) Successful in 1m26s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 06:10:58 +09:00
cat 025810bf0f internal/rosa/package/python: setuptools-scm 10.0.5 to 10.1.2
Test / Create distribution (push) Successful in 1m35s
Test / Sandbox (push) Successful in 4m59s
Test / ShareFS (push) Successful in 7m47s
Test / Hakurei (push) Successful in 7m50s
Test / Sandbox (race detector) (push) Successful in 9m6s
Test / Hakurei (race detector) (push) Successful in 11m59s
Test / Flake checks (push) Successful in 1m27s
All in-between releases are broken. Not sure how that happened.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 06:10:32 +09:00
cat 20354c0411 internal/rosa/package/python: vcs-versioning 1.1.1 to 2.1.1
Test / Create distribution (push) Successful in 1m4s
Test / Sandbox (push) Successful in 4m27s
Test / ShareFS (push) Successful in 6m52s
Test / Hakurei (push) Successful in 7m4s
Test / Sandbox (race detector) (push) Successful in 8m36s
Test / Hakurei (race detector) (push) Successful in 11m28s
Test / Flake checks (push) Successful in 1m28s
The environment variable changed for this package only, did not appear to affect other packages.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 06:09:42 +09:00
cat 9fbcd0daf2 internal/rosa/package/libarchive: 3.8.7 to 3.8.8
Test / Create distribution (push) Successful in 1m1s
Test / ShareFS (push) Successful in 5m35s
Test / Sandbox (race detector) (push) Successful in 7m51s
Test / Hakurei (race detector) (push) Successful in 10m28s
Test / Sandbox (push) Successful in 1m42s
Test / Hakurei (push) Successful in 3m7s
Test / Flake checks (push) Successful in 1m23s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-24 06:08:47 +09:00
cat 248f44a5a7 cmd/app: zero state buffer before reuse
Test / Create distribution (push) Successful in 54s
Test / Sandbox (push) Successful in 2m49s
Test / ShareFS (push) Successful in 3m49s
Test / Hakurei (push) Successful in 4m9s
Test / Sandbox (race detector) (push) Successful in 5m24s
Test / Hakurei (race detector) (push) Successful in 8m34s
Test / Flake checks (push) Successful in 4m13s
Package internal/store expects a zero-initialised buffer.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-23 09:19:11 +09:00
cat 401dd57cbc cmd/app: display user-facing error message
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 2m54s
Test / ShareFS (push) Successful in 4m0s
Test / Hakurei (push) Successful in 4m5s
Test / Sandbox (race detector) (push) Successful in 5m33s
Test / Hakurei (race detector) (push) Successful in 6m48s
Test / Flake checks (push) Successful in 1m9s
This is required for useful error messages for errors originating from internal/store.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-23 09:09:55 +09:00
cat 854bcc998b cmd/app: expose scheduling configuration
Test / Create distribution (push) Successful in 1m3s
Test / Sandbox (push) Successful in 2m54s
Test / ShareFS (push) Successful in 4m2s
Test / Hakurei (push) Successful in 4m12s
Test / Sandbox (race detector) (push) Successful in 5m44s
Test / Hakurei (race detector) (push) Successful in 6m45s
Test / Flake checks (push) Successful in 1m9s
Useful for the music player.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-23 06:33:27 +09:00
cat 358247be5b internal/rosa/package/x: xkeyboard-config 2.47 to 2.48
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 3m26s
Test / Hakurei (push) Successful in 4m55s
Test / ShareFS (push) Successful in 4m59s
Test / Sandbox (race detector) (push) Successful in 6m6s
Test / Hakurei (race detector) (push) Successful in 7m24s
Test / Flake checks (push) Successful in 1m16s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-23 00:44:18 +09:00
cat f517a8ef07 internal/rosa/package/libffi: 3.5.2 to 3.6.0
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 2m59s
Test / ShareFS (push) Successful in 4m21s
Test / Hakurei (push) Successful in 4m29s
Test / Sandbox (race detector) (push) Successful in 6m2s
Test / Hakurei (race detector) (push) Successful in 7m21s
Test / Flake checks (push) Successful in 1m15s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-23 00:43:24 +09:00
cat 973218f91f internal/rosa/package/qemu: disable netdev-socket test
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 2m58s
Test / ShareFS (push) Successful in 3m55s
Test / Hakurei (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 5m32s
Test / Hakurei (race detector) (push) Successful in 6m44s
Test / Flake checks (push) Successful in 1m13s
This fails with ipv6 disabled.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-22 01:21:09 +09:00
cat 0ea195837b internal/rosa/package/glib: disable gio suite
Test / Create distribution (push) Successful in 57s
Test / Sandbox (push) Successful in 4m18s
Test / ShareFS (push) Successful in 5m41s
Test / Sandbox (race detector) (push) Successful in 7m7s
Test / Hakurei (push) Successful in 2m42s
Test / Hakurei (race detector) (push) Successful in 3m31s
Test / Flake checks (push) Successful in 1m12s
This fails with ipv6 disabled.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-22 00:53:40 +09:00
cat 1348991634 internal/rosa/meson: skip specific test suites
Test / Create distribution (push) Successful in 55s
Test / ShareFS (push) Successful in 5m32s
Test / Sandbox (race detector) (push) Successful in 7m9s
Test / Hakurei (race detector) (push) Successful in 8m28s
Test / Sandbox (push) Successful in 1m30s
Test / Hakurei (push) Successful in 2m32s
Test / Flake checks (push) Successful in 1m7s
For disabling specific broken or flaky tests.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-22 00:53:17 +09:00
cat 14b445fde5 internal/rosa/package/openssl: disable test_bio_dgram
Test / Create distribution (push) Successful in 1m5s
Test / ShareFS (push) Successful in 9m39s
Test / Sandbox (push) Successful in 2m16s
Test / Sandbox (race detector) (push) Successful in 3m23s
Test / Hakurei (push) Successful in 4m8s
Test / Hakurei (race detector) (push) Successful in 4m57s
Test / Flake checks (push) Successful in 2m27s
This fails when ipv6 is disabled.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-21 21:43:46 +09:00
cat 218f7fa345 cmd/app: enforce mutable instance exclusion
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 2m47s
Test / ShareFS (push) Successful in 3m46s
Test / Hakurei (push) Successful in 3m57s
Test / Sandbox (race detector) (push) Successful in 5m31s
Test / Hakurei (race detector) (push) Successful in 6m39s
Test / Flake checks (push) Successful in 1m7s
This avoids invoking undefined behaviour in the underlying overlay filesystem implementation.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-21 02:09:01 +09:00
cat cd493fd95f cmd/app: centralise workdir
Test / Create distribution (push) Successful in 51s
Test / Sandbox (push) Successful in 2m47s
Test / ShareFS (push) Successful in 3m48s
Test / Hakurei (push) Successful in 4m1s
Test / Sandbox (race detector) (push) Successful in 5m19s
Test / Hakurei (race detector) (push) Successful in 6m31s
Test / Flake checks (push) Successful in 1m7s
This makes the directory structure significantly more manageable.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-21 00:48:18 +09:00
cat 9db70c83e3 cmd/app: configure username and hostname
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m42s
Test / ShareFS (push) Successful in 3m46s
Test / Hakurei (push) Successful in 4m0s
Test / Sandbox (race detector) (push) Successful in 5m33s
Test / Hakurei (race detector) (push) Successful in 6m42s
Test / Flake checks (push) Successful in 1m9s
These no longer need to be hardcoded since this is not subject to the limitations of home-manager.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 22:15:49 +09:00
cat 4e09241e5f cmd/app: optional interactive shell
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 3m4s
Test / Hakurei (push) Successful in 4m20s
Test / ShareFS (push) Successful in 4m19s
Test / Sandbox (race detector) (push) Successful in 5m36s
Test / Hakurei (race detector) (push) Successful in 6m51s
Test / Flake checks (push) Successful in 1m8s
Enabling this unconditionally causes the new configuration prompt to be shown when started from a terminal, and is generally less robust than not reading zshrc unless explicitly required.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 19:08:47 +09:00
cat bd4b300ea6 internal/rosa/package/cmake: 4.3.3 to 4.3.4
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 3m22s
Test / ShareFS (push) Successful in 4m38s
Test / Sandbox (race detector) (push) Successful in 6m34s
Test / Hakurei (race detector) (push) Successful in 7m57s
Test / Hakurei (push) Successful in 2m58s
Test / Flake checks (push) Successful in 1m26s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 17:56:09 +09:00
cat 6dc8214a1a internal/rosa/package/kernel: 6.12.93 to 6.12.94
Test / Create distribution (push) Successful in 51s
Test / Sandbox (push) Successful in 3m26s
Test / Hakurei (push) Successful in 6m11s
Test / ShareFS (push) Successful in 5m46s
Test / Sandbox (race detector) (push) Successful in 7m3s
Test / Hakurei (race detector) (push) Successful in 9m8s
Test / Flake checks (push) Successful in 1m20s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 17:55:49 +09:00
cat cada5a46ad internal/rosa/package/mesa: 26.1.2 to 26.1.3
Test / Create distribution (push) Successful in 1m3s
Test / Sandbox (push) Successful in 3m29s
Test / Hakurei (push) Successful in 5m43s
Test / ShareFS (push) Successful in 5m47s
Test / Sandbox (race detector) (push) Successful in 7m37s
Test / Hakurei (race detector) (push) Successful in 9m31s
Test / Flake checks (push) Successful in 1m20s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 17:55:08 +09:00
cat e747942829 internal/rosa/package/python: pytest 9.1.0 to 9.1.1
Test / Create distribution (push) Successful in 1m9s
Test / Sandbox (push) Successful in 3m24s
Test / ShareFS (push) Successful in 5m32s
Test / Sandbox (race detector) (push) Successful in 7m48s
Test / Hakurei (race detector) (push) Successful in 9m26s
Test / Hakurei (push) Successful in 3m0s
Test / Flake checks (push) Successful in 1m25s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 17:54:38 +09:00
cat 33b855123e internal/rosa/package/spirv: spirv-headers 1.4.350.0 to 1.4.350.1
Test / Create distribution (push) Successful in 51s
Test / Sandbox (push) Successful in 2m43s
Test / ShareFS (push) Successful in 3m43s
Test / Sandbox (race detector) (push) Successful in 5m46s
Test / Hakurei (race detector) (push) Successful in 7m0s
Test / Hakurei (push) Successful in 2m35s
Test / Flake checks (push) Successful in 1m38s
This unfortunately does not unblock SPIRV-LLVM-Translator.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 04:43:04 +09:00
cat 58ce134718 internal/outcome: attempt nscd path-hiding if present
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m46s
Test / ShareFS (push) Successful in 3m56s
Test / Hakurei (push) Successful in 4m9s
Test / Sandbox (race detector) (push) Successful in 5m42s
Test / Hakurei (race detector) (push) Successful in 6m50s
Test / Flake checks (push) Successful in 1m9s
This avoids creating the mount point on musl setups which accomplishes nothing and can run into permission problems.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 02:42:35 +09:00
cat 2066093343 cmd/app: remove sysfs bind mounts
Test / Create distribution (push) Successful in 51s
Test / Sandbox (push) Successful in 2m57s
Test / ShareFS (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 5m26s
Test / Hakurei (race detector) (push) Successful in 6m39s
Test / Hakurei (push) Successful in 2m46s
Test / Flake checks (push) Successful in 1m9s
This should be in common instead.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 01:57:55 +09:00
cat 07509b3ba2 cmd/app: additional bind types
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m58s
Test / ShareFS (push) Successful in 3m54s
Test / Hakurei (push) Successful in 4m7s
Test / Sandbox (race detector) (push) Successful in 5m27s
Test / Hakurei (race detector) (push) Successful in 6m43s
Test / Flake checks (push) Successful in 1m25s
This adds optional and device mount points.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 01:51:57 +09:00
cat a7485d587a cmd/app: pass user-specified arguments
Test / Create distribution (push) Successful in 50s
Test / Sandbox (push) Successful in 2m52s
Test / ShareFS (push) Successful in 3m48s
Test / Sandbox (race detector) (push) Successful in 5m20s
Test / Hakurei (race detector) (push) Successful in 6m37s
Test / Hakurei (push) Successful in 2m40s
Test / Flake checks (push) Successful in 1m26s
An extra argument is added to pad out argv0.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 01:44:47 +09:00
cat 4892beefc1 cmd/app: optionally override configured command
Test / Create distribution (push) Successful in 50s
Test / Sandbox (push) Successful in 2m45s
Test / ShareFS (push) Successful in 3m50s
Test / Hakurei (push) Successful in 4m1s
Test / Sandbox (race detector) (push) Successful in 5m33s
Test / Hakurei (race detector) (push) Successful in 6m35s
Test / Flake checks (push) Successful in 1m9s
Useful for multiple applications sharing state.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 01:31:07 +09:00
cat 7ab54b8c94 internal/rosa: read overridden version string from source
Test / Create distribution (push) Successful in 54s
Test / Sandbox (push) Successful in 3m2s
Test / ShareFS (push) Successful in 4m2s
Test / Hakurei (push) Successful in 4m10s
Test / Sandbox (race detector) (push) Successful in 5m31s
Test / Hakurei (race detector) (push) Successful in 6m42s
Test / Flake checks (push) Successful in 1m7s
This is more correct than the hardcoded string and is generally more robust against relative paths.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 01:18:12 +09:00
cat a4fab67811 internal/pkg: optionally exempt implementations from cures counter
Test / Create distribution (push) Successful in 51s
Test / Sandbox (push) Successful in 2m49s
Test / ShareFS (push) Successful in 3m48s
Test / Hakurei (push) Successful in 3m59s
Test / Sandbox (race detector) (push) Successful in 5m23s
Test / Hakurei (race detector) (push) Successful in 6m39s
Test / Flake checks (push) Successful in 1m26s
This avoids holding up many slots with a long pipeline.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 01:03:28 +09:00
cat ed5cdd38a4 cmd/dist: build hsu separately
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m41s
Test / ShareFS (push) Successful in 3m47s
Test / Hakurei (push) Successful in 4m0s
Test / Sandbox (race detector) (push) Successful in 5m25s
Test / Hakurei (race detector) (push) Successful in 6m36s
Test / Flake checks (push) Successful in 1m8s
This program must be built with cgo disabled, and was missed when migrating build script.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 00:59:47 +09:00
cat f6318304ee hst: fix ephemeral overlay order
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 2m55s
Test / ShareFS (push) Successful in 4m13s
Test / Hakurei (push) Successful in 4m19s
Test / Sandbox (race detector) (push) Successful in 5m58s
Test / Hakurei (race detector) (push) Successful in 6m53s
Test / Flake checks (push) Successful in 1m11s
This is quite counterintuitive otherwise.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 00:20:31 +09:00
cat cb618093d5 hst: optionally disable file placement
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m39s
Test / ShareFS (push) Successful in 3m46s
Test / Sandbox (race detector) (push) Successful in 5m28s
Test / Hakurei (race detector) (push) Successful in 6m37s
Test / Hakurei (push) Successful in 2m46s
Test / Flake checks (push) Successful in 1m17s
This works around stubborn package managers.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-20 00:16:35 +09:00
cat b0b2471c0c cmd/app: include template name in container metadata
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 3m3s
Test / ShareFS (push) Successful in 3m46s
Test / Hakurei (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 5m27s
Test / Hakurei (race detector) (push) Successful in 6m38s
Test / Flake checks (push) Successful in 1m10s
This helps disambiguate active mutable containers.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-19 23:36:31 +09:00
cat 344d2b8207 cmd/app: use ROSA_ prefix
Test / Create distribution (push) Successful in 54s
Test / Sandbox (push) Successful in 2m52s
Test / ShareFS (push) Successful in 3m51s
Test / Hakurei (push) Successful in 3m59s
Test / Sandbox (race detector) (push) Successful in 5m29s
Test / Hakurei (race detector) (push) Successful in 6m38s
Test / Flake checks (push) Successful in 1m24s
This avoids awkward case-insensitive zsh completion.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-19 23:29:51 +09:00
cat 3938e8bce5 cmd/app: multiple template uppers
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m44s
Test / ShareFS (push) Successful in 3m53s
Test / Hakurei (push) Successful in 4m6s
Test / Sandbox (race detector) (push) Successful in 5m27s
Test / Hakurei (race detector) (push) Successful in 6m40s
Test / Flake checks (push) Successful in 1m12s
Having multiple environments is useful, and this was trivial to implement.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-18 03:51:49 +09:00
cat aee15b4f2a cmd/app: common configuration file
Test / Create distribution (push) Successful in 1m36s
Test / Sandbox (push) Successful in 3m28s
Test / ShareFS (push) Successful in 4m33s
Test / Hakurei (push) Successful in 4m41s
Test / Sandbox (race detector) (push) Successful in 6m45s
Test / Hakurei (race detector) (push) Successful in 7m46s
Test / Flake checks (push) Successful in 1m33s
Generally useful for shared storage and environment.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-18 02:35:56 +09:00
cat 18b1103fdc internal/rosa/llvm: 22.1.7 to 22.1.8
Test / Create distribution (push) Successful in 1m13s
Test / Sandbox (push) Successful in 3m20s
Test / ShareFS (push) Successful in 8m47s
Test / Hakurei (push) Successful in 8m51s
Test / Sandbox (race detector) (push) Successful in 2m54s
Test / Hakurei (race detector) (push) Successful in 4m22s
Test / Flake checks (push) Successful in 1m18s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-17 21:49:38 +09:00
cat c5a02da0f0 internal/rosa/package/python: 3.14.5 to 3.14.6
Test / Create distribution (push) Successful in 1m8s
Test / Sandbox (push) Successful in 3m14s
Test / ShareFS (push) Successful in 6m39s
Test / Hakurei (push) Successful in 7m35s
Test / Sandbox (race detector) (push) Successful in 2m53s
Test / Hakurei (race detector) (push) Successful in 4m27s
Test / Flake checks (push) Successful in 1m19s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-17 21:49:07 +09:00
cat c0c2f3233a internal/rosa/package/util-linux: 2.42.1 to 2.42.2
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 2m58s
Test / ShareFS (push) Successful in 3m57s
Test / Hakurei (push) Successful in 4m7s
Test / Sandbox (race detector) (push) Successful in 5m47s
Test / Hakurei (race detector) (push) Successful in 7m4s
Test / Flake checks (push) Successful in 1m34s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-17 21:44:47 +09:00
cat bda00ac90e internal/rosa/package/hakurei: 0.4.3 to 0.4.4
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m41s
Test / ShareFS (push) Successful in 3m48s
Test / Hakurei (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 5m33s
Test / Hakurei (race detector) (push) Successful in 6m42s
Test / Flake checks (push) Successful in 1m23s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-06-17 21:40:04 +09:00
295 changed files with 23444 additions and 4041 deletions
+1
View File
@@ -0,0 +1 @@
*.az linguist-language=Azalea
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
uses: actions/checkout@v4
- name: Build for release
run: nix build --print-out-paths --print-build-logs .#dist
run: nix build --print-out-paths --print-build-logs ./test#dist
- name: Release
uses: https://gitea.com/actions/release-action@main
+9 -9
View File
@@ -12,7 +12,7 @@ jobs:
uses: actions/checkout@v4
- name: Run NixOS test
run: nix build --out-link "result" --print-out-paths --print-build-logs .#checks.x86_64-linux.hakurei
run: nix build --out-link "result" --print-out-paths --print-build-logs ./test#checks.x86_64-linux.hakurei
- name: Upload test output
uses: actions/upload-artifact@v3
@@ -29,7 +29,7 @@ jobs:
uses: actions/checkout@v4
- name: Run NixOS test
run: nix build --out-link "result" --print-out-paths --print-build-logs .#checks.x86_64-linux.race
run: nix build --out-link "result" --print-out-paths --print-build-logs ./test#checks.x86_64-linux.race
- name: Upload test output
uses: actions/upload-artifact@v3
@@ -46,7 +46,7 @@ jobs:
uses: actions/checkout@v4
- name: Run NixOS test
run: nix build --out-link "result" --print-out-paths --print-build-logs .#checks.x86_64-linux.sandbox
run: nix build --out-link "result" --print-out-paths --print-build-logs ./test#checks.x86_64-linux.sandbox
- name: Upload test output
uses: actions/upload-artifact@v3
@@ -63,7 +63,7 @@ jobs:
uses: actions/checkout@v4
- name: Run NixOS test
run: nix build --out-link "result" --print-out-paths --print-build-logs .#checks.x86_64-linux.sandbox-race
run: nix build --out-link "result" --print-out-paths --print-build-logs ./test#checks.x86_64-linux.sandbox-race
- name: Upload test output
uses: actions/upload-artifact@v3
@@ -80,7 +80,7 @@ jobs:
uses: actions/checkout@v4
- name: Run NixOS test
run: nix build --out-link "result" --print-out-paths --print-build-logs .#checks.x86_64-linux.sharefs
run: nix build --out-link "result" --print-out-paths --print-build-logs ./test#checks.x86_64-linux.sharefs
- name: Upload test output
uses: actions/upload-artifact@v3
@@ -103,7 +103,7 @@ jobs:
uses: actions/checkout@v4
- name: Run checks
run: nix --print-build-logs --experimental-features 'nix-command flakes' flake check
run: nix --print-build-logs --experimental-features 'nix-command flakes' flake check ./test
dist:
name: Create distribution
@@ -116,9 +116,9 @@ jobs:
id: build-test
run: >-
export HAKUREI_REV="$(git rev-parse --short HEAD)" &&
sed -i.old 's/version = /version = "0.0.0-'$HAKUREI_REV'"; # version = /' package.nix &&
nix build --print-out-paths --print-build-logs .#dist &&
mv package.nix.old package.nix &&
sed -i.old 's/version = /version = "0.0.0-'$HAKUREI_REV'"; # version = /' test/package.nix &&
nix build --print-out-paths --print-build-logs ./test#dist &&
mv test/{package.nix.old,package.nix} &&
echo "rev=$HAKUREI_REV" >> $GITHUB_OUTPUT
- name: Upload test build
+1
View File
@@ -1,4 +1,5 @@
# produced by tools and text editors
*.swp
*.qcow2
*.test
*.out
+1 -6
View File
@@ -57,9 +57,4 @@ package [internal/rosa](https://pkg.go.dev/hakurei.app/internal/rosa).
- [fuse](https://github.com/libfuse/libfuse) to implement the filesystem.
New dependencies will generally not be added. Patches adding new dependencies
are very likely to be rejected.
## NixOS Module (deprecated)
The NixOS module is in maintenance mode and will be removed once planterette is
feature-complete. Full module documentation can be found [here](options.md).
are very likely to be rejected.
+110 -20
View File
@@ -4,10 +4,12 @@ import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
"hakurei.app/check"
"hakurei.app/ext"
"hakurei.app/fhs"
"hakurei.app/hst"
)
@@ -31,10 +33,19 @@ func parsePair(s string) (source, target *check.Absolute, err error) {
// parse decodes a high-level configuration stream and returns its
// corresponding [hst.Config].
func parse(id string, base *check.Absolute, r io.Reader) (*hst.Config, error) {
func parse(
id string,
base *check.Absolute,
r io.Reader,
templateP *string,
) (*hst.Config, error) {
shell := fhs.AbsRoot.Append("bin", "zsh")
home := hst.AbsPrivateTmp.Append("home")
root := hst.FSOverlay{
Target: fhs.AbsRoot,
Lower: []*check.Absolute{base.Append("initial")},
}
c := hst.Config{
ID: id,
Enablements: new(hst.Enablements),
@@ -51,13 +62,7 @@ func parse(id string, base *check.Absolute, r io.Reader) (*hst.Config, error) {
Container: &hst.ContainerConfig{
Env: make(map[string]string),
Filesystem: []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSOverlay{
Target: fhs.AbsRoot,
Lower: []*check.Absolute{
base.Append("template", "initial"),
},
Upper: base.Append("template", "upper"),
}},
{FilesystemConfig: &root},
{FilesystemConfig: &hst.FSBind{
Target: home,
Source: base.Append("state", id),
@@ -70,12 +75,6 @@ func parse(id string, base *check.Absolute, r io.Reader) (*hst.Config, error) {
Write: true,
Perm: 01777,
}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("block")}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("bus")}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("class")}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("dev")}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("devices")}},
},
Username: "chronos",
@@ -102,21 +101,28 @@ func parse(id string, base *check.Absolute, r io.Reader) (*hst.Config, error) {
if err := scanOnce(); err != nil {
return nil, err
}
if v, err := strconv.Atoi(s.Text()); err != nil {
if template, identity, ok := strings.Cut(s.Text(), ":"); !ok {
return nil, io.ErrUnexpectedEOF
} else if v, err := strconv.Atoi(identity); err != nil {
return nil, err
} else {
if templateP != nil {
*templateP = template
}
c.Identity = v
root.Upper = base.Append("template", template)
}
if err := scanOnce(); err != nil {
return nil, err
}
c.Container.Args = append(c.Container.Args, s.Text())
c.Container.Args = append(c.Container.Args, s.Text(), "")
var flagGPU, flagSystemBus bool
var flagInteractive, flagGPU, flagSystemBus bool
flags := map[string]*bool{
"gpu": &flagGPU,
"system_bus": &flagSystemBus,
"interactive": &flagInteractive,
"gpu": &flagGPU,
"system_bus": &flagSystemBus,
}
for s.Scan() {
@@ -176,10 +182,43 @@ func parse(id string, base *check.Absolute, r io.Reader) (*hst.Config, error) {
}
switch key {
case "username":
c.Container.Username = value
continue
case "hostname":
c.Container.Hostname = value
continue
case "group":
c.Groups = append(c.Groups, value)
continue
case "sched_policy":
if err := c.SchedPolicy.UnmarshalText([]byte(value)); err != nil {
return nil, err
}
continue
case "sched_priority":
v, err := strconv.Atoi(value)
if err != nil {
return nil, err
}
c.SchedPriority = ext.Int(v)
continue
case "insecure":
switch value {
case "pipewire":
*c.Enablements |= hst.EPipeWire
c.DirectPipeWire = true
continue
default:
return nil, fmt.Errorf("invalid insecure flag %q", value)
}
case "env":
if key, value, ok = strings.Cut(value, "="); !ok {
return nil, fmt.Errorf("invalid environment %q", key)
@@ -200,6 +239,20 @@ func parse(id string, base *check.Absolute, r io.Reader) (*hst.Config, error) {
)
continue
case "ro+":
source, target, err := parsePair(value)
if err != nil {
return nil, err
}
c.Container.Filesystem = append(c.Container.Filesystem,
hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{
Target: target,
Source: source,
Optional: true,
}},
)
continue
case "rw":
source, target, err := parsePair(value)
if err != nil {
@@ -214,6 +267,20 @@ func parse(id string, base *check.Absolute, r io.Reader) (*hst.Config, error) {
)
continue
case "dev":
source, target, err := parsePair(value)
if err != nil {
return nil, err
}
c.Container.Filesystem = append(c.Container.Filesystem,
hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{
Target: target,
Source: source,
Device: true,
}},
)
continue
case "own":
c.SessionBus.Own = append(c.SessionBus.Own, value)
continue
@@ -236,6 +303,10 @@ func parse(id string, base *check.Absolute, r io.Reader) (*hst.Config, error) {
return nil, err
}
if flagInteractive {
c.Container.Args[1] += "i"
}
if flagGPU {
c.Container.Filesystem = append(c.Container.Filesystem, []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{
@@ -250,7 +321,10 @@ func parse(id string, base *check.Absolute, r io.Reader) (*hst.Config, error) {
c.SystemBus = nil
}
if c.Container.Flags&hst.FShareTmpdir == 0 {
if c.Container.Flags&hst.FShareTmpdir == 0 &&
(c.Enablements.Unwrap()&hst.EX11 == 0 ||
c.Container.Flags&(hst.FHostNet|hst.FHostAbstract) ==
hst.FHostNet|hst.FHostAbstract) {
c.Container.Filesystem = append(c.Container.Filesystem,
hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSEphemeral{
Target: fhs.AbsTmp,
@@ -262,3 +336,19 @@ func parse(id string, base *check.Absolute, r io.Reader) (*hst.Config, error) {
return &c, nil
}
// list prints names of non-hidden entries in pathname.
func list(pathname *check.Absolute, dir bool) error {
dents, err := os.ReadDir(pathname.String())
if err != nil {
return err
}
for _, dent := range dents {
name := dent.Name()
if (dent.IsDir() != dir) || (len(name) > 0 && name[0] == '.') {
continue
}
fmt.Println(dent.Name())
}
return nil
}
+5 -9
View File
@@ -20,7 +20,7 @@ func TestParse(t *testing.T) {
want *hst.Config
err error
}{
{"com.discordapp.Discord", `8
{"com.discordapp.Discord", `nonfree:8
exec Discord --ozone-platform-hint=wayland
gpu
@@ -74,9 +74,9 @@ talk com.canonical.Unity
{FilesystemConfig: &hst.FSOverlay{
Target: fhs.AbsRoot,
Lower: []*check.Absolute{
base.Append("template", "initial"),
base.Append("initial"),
},
Upper: base.Append("template", "upper"),
Upper: base.Append("template", "nonfree"),
}},
{FilesystemConfig: &hst.FSBind{
Target: hst.AbsPrivateTmp.Append("home"),
@@ -91,12 +91,6 @@ talk com.canonical.Unity
Perm: 01777,
}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("block")}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("bus")}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("class")}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("dev")}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("devices")}},
{FilesystemConfig: &hst.FSBind{
Source: check.MustAbs("/sdcard"),
Write: true,
@@ -120,6 +114,7 @@ talk com.canonical.Unity
Args: []string{
"zsh", "-c",
"exec Discord --ozone-platform-hint=wayland",
"",
},
Flags: hst.FCoverRun | hst.FUserns | hst.FHostNet | hst.FMapRealUID |
@@ -135,6 +130,7 @@ talk com.canonical.Unity
tc.name,
base,
strings.NewReader(tc.data),
nil,
)
if !reflect.DeepEqual(err, tc.err) {
+112
View File
@@ -0,0 +1,112 @@
package main
import (
"errors"
"log"
"os"
"strconv"
"strings"
"hakurei.app/check"
"hakurei.app/fhs"
"hakurei.app/hst"
"hakurei.app/internal/env"
"hakurei.app/internal/lockedfile"
"hakurei.app/internal/outcome"
)
// MutationConflictError describes an active mutable instance.
type MutationConflictError string
func (e MutationConflictError) Error() string {
return "mutable instance active at " + string(e)
}
// informTemplate guards intention of a template or its derivatives.
func informTemplate(base *check.Absolute, name string, mutable bool) (func() error, error) {
mu := lockedfile.MutexAt(base.Append("lock", name).String())
if unlock, err := mu.Lock(); err != nil {
return nil, err
} else {
defer unlock()
}
marker := base.Append("lock", "."+name)
if p, err := os.ReadFile(marker.String()); err == nil {
if _, err = os.Stat(fhs.AbsProc.Append(string(p)).String()); err == nil {
return nil, MutationConflictError(p)
} else if !errors.Is(err, os.ErrNotExist) {
return nil, err
}
log.Printf("removing stale marker by %s", string(p))
if err = os.Remove(marker.String()); err != nil {
return nil, err
}
} else if !errors.Is(err, os.ErrNotExist) {
return nil, err
}
if !mutable {
return nil, nil
}
var active []hst.ID
var sc hst.Paths
env.CopyPaths().Copy(&sc, new(outcome.Hsu).MustID(nil))
entries, copyError := outcome.NewStore(&sc).All()
var s hst.State
for eh := range entries {
s = hst.State{}
if _, err := eh.Load(&s); err != nil {
return nil, err
}
if s.Validate(0) != nil || len(s.Container.Filesystem) < 1 {
continue
}
root, ok := s.Container.Filesystem[0].FilesystemConfig.(*hst.FSOverlay)
if !ok || root == nil {
continue
}
if !root.Target.Is(fhs.AbsRoot) ||
len(root.Lower) != 1 ||
!root.Lower[0].Is(base.Append("initial")) ||
!root.Upper.Is(base.Append("template", name)) ||
root.Work != nil {
continue
}
active = append(active, s.ID)
}
if err := copyError(); err != nil {
return nil, err
}
if len(active) != 0 {
var buf strings.Builder
buf.WriteString("derivative instances still active:")
for _, id := range active {
buf.WriteString("\n\t")
buf.WriteString(id.String())
}
return nil, errors.New(buf.String())
}
return func() error { return os.RemoveAll(marker.String()) }, os.WriteFile(
marker.String(),
[]byte(strconv.Itoa(os.Getpid())),
0400,
)
}
// acquireTemplate obtains exclusivity of a template.
func acquireTemplate(base *check.Absolute, name string) (remove func() error, err error) {
return informTemplate(base, name, true)
}
// enterTemplate checks against exclusivity of a template.
func enterTemplate(base *check.Absolute, name string) error {
_, err := informTemplate(base, name, false)
return err
}
+92 -36
View File
@@ -7,6 +7,7 @@ package main
import (
"context"
"errors"
"io"
"log"
"os"
"os/exec"
@@ -31,10 +32,11 @@ func main() {
defer stop()
var (
flagVerbose bool
flagBase string
flagVerbose bool
flagBase string
flagInsecure bool
base, template, initial, upper, work *check.Absolute
base, template, initial *check.Absolute
)
c := command.New(os.Stderr, log.Printf, "app", func([]string) (err error) {
msg.SwapVerbose(flagVerbose)
@@ -49,9 +51,7 @@ func main() {
}
template = base.Append("template")
initial = template.Append("initial")
upper = template.Append("upper")
work = template.Append("work")
initial = base.Append("initial")
return
}).Flag(
&flagVerbose,
@@ -59,8 +59,12 @@ func main() {
"Increase log verbosity",
).Flag(
&flagBase,
"d", command.StringFlag("$HAKUREI_APP_PATH"),
"d", command.StringFlag("$ROSA_APP_PATH"),
"Configuration and state directory",
).Flag(
&flagInsecure,
"insecure", command.BoolFlag(false),
"Allow use of insecure compatibility options",
)
{
@@ -70,17 +74,21 @@ func main() {
)
c.NewCommand(
"enter", "Enter mutable state template",
func([]string) error {
func(args []string) error {
if len(args) != 1 {
return list(template, true)
}
config := hst.Config{
ID: "app.hakurei.mutable",
ID: "app.hakurei.mutable." + args[0],
Container: &hst.ContainerConfig{
Hostname: "mutable",
Hostname: args[0] + "-mutable",
Filesystem: []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSOverlay{
Target: fhs.AbsRoot,
Lower: []*check.Absolute{initial},
Upper: upper,
Work: work,
Upper: template.Append(args[0]),
Work: base.Append("work", args[0]),
}},
{FilesystemConfig: &hst.FSEphemeral{
Target: fhs.AbsTmp,
@@ -89,7 +97,8 @@ func main() {
}},
},
Username: "chronos",
Flags: hst.FMultiarch |
Flags: hst.FNoPlace |
hst.FMultiarch |
hst.FDevel |
hst.FUserns |
hst.FHostNet |
@@ -113,7 +122,12 @@ func main() {
config.Container.Home = a
}
return run(ctx, msg, &config)
remove, err := acquireTemplate(base, args[0])
if err != nil {
return err
}
err = run(ctx, msg, false, &config)
return errors.Join(err, remove())
},
).Flag(
&flagShell,
@@ -126,29 +140,65 @@ func main() {
)
}
c.NewCommand(
"run", "Start the named application",
func(args []string) error {
if len(args) != 1 {
return errors.New("run requires 1 argument")
}
{
var (
flagCommand string
)
c.NewCommand(
"run", "Start the named application",
func(args []string) error {
if len(args) < 1 {
return list(base.Append("app"), false)
}
var config *hst.Config
f, err := os.Open(base.Append("app", args[0]).String())
if err != nil {
return err
}
config, err = parse(args[0], base, f)
if closeErr := f.Close(); err == nil {
err = closeErr
}
if err != nil {
return err
}
var config *hst.Config
var r io.Reader
f, err := os.Open(base.Append("app", args[0]).String())
if err != nil {
return err
}
r = f
return run(ctx, msg, config)
},
)
var common *os.File
if common, err = os.Open(base.Append("common").String()); err != nil {
if !errors.Is(err, os.ErrNotExist) {
_ = f.Close()
return err
}
} else {
r = io.MultiReader(f, common)
}
var name string
config, err = parse(args[0], base, r, &name)
if closeErr := f.Close(); err == nil {
err = closeErr
}
if common != nil {
if closeErr := common.Close(); err == nil {
err = closeErr
}
}
if err != nil {
return err
}
if flagCommand != "" {
config.Container.Args[2] = flagCommand
}
if err = enterTemplate(base, name); err != nil {
return err
}
return run(ctx, msg, flagInsecure, config, args[1:]...)
},
).
Flag(
&flagCommand,
"command", command.StringFlag(""),
"Override configured command",
)
}
c.MustParse(os.Args[1:], func(err error) {
if e, ok := errors.AsType[*exec.ExitError](err); ok && e != nil {
@@ -156,7 +206,13 @@ func main() {
}
if w, ok := err.(interface{ Unwrap() []error }); !ok {
log.Fatal(err)
var m string
m, ok = message.GetMessage(err)
if !ok {
log.Fatal(err)
return
}
log.Fatal(m)
} else {
errs := w.Unwrap()
for i, e := range errs {
+11 -1
View File
@@ -12,7 +12,13 @@ import (
)
// run starts a container via cmd/hakurei and returns after it terminates.
func run(ctx context.Context, msg message.Msg, config *hst.Config) error {
func run(
ctx context.Context,
msg message.Msg,
insecure bool,
config *hst.Config,
args ...string,
) error {
c, cancel := context.WithCancel(ctx)
defer cancel()
@@ -24,7 +30,11 @@ func run(ctx context.Context, msg message.Msg, config *hst.Config) error {
if msg.IsVerbose() {
cmd.Args = append(cmd.Args, "-v")
}
if insecure {
cmd.Args = append(cmd.Args, "--insecure")
}
cmd.Args = append(cmd.Args, "run", "3")
cmd.Args = append(cmd.Args, args...)
r, w, err := os.Pipe()
if err != nil {
+1 -1
View File
@@ -1 +1 @@
v0.4.4
v0.4.5
+25 -10
View File
@@ -35,8 +35,11 @@ func getenv(key, fallback string) string {
// mustRun runs a command with the current process's environment and panics
// on error or non-zero exit code.
func mustRun(ctx context.Context, name string, arg ...string) {
func mustRun(ctx context.Context, env []string, name string, arg ...string) {
cmd := exec.CommandContext(ctx, name, arg...)
if env != nil {
cmd.Env = append(cmd.Environ(), env...)
}
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
if err := cmd.Run(); err != nil {
panic(err)
@@ -49,11 +52,12 @@ var comp []byte
func main() {
log.SetFlags(0)
log.SetPrefix("")
log.SetOutput(os.Stdout)
verbose := os.Getenv("VERBOSE") != ""
runTests := os.Getenv("HAKUREI_DIST_MAKE") == ""
version = getenv("HAKUREI_VERSION", strings.TrimSpace(version))
prefix := getenv("PREFIX", "/usr")
prefix := getenv("PREFIX", "/usr/local")
destdir := getenv("DESTDIR", "dist")
if verbose {
@@ -91,26 +95,37 @@ func main() {
verboseFlag = "-buildvcs=false"
}
log.Printf("Building hakurei for %s/%s.", runtime.GOOS, runtime.GOARCH)
mustRun(ctx, "go", "generate", "./...")
log.Printf("Building hakurei %s for %s/%s.", version, runtime.GOOS, runtime.GOARCH)
mustRun(ctx, nil, "go", "generate", "./...")
mustRun(
ctx, "go", "build",
ctx, nil, "go", "build",
"-trimpath",
verboseFlag, "-o", s,
"-ldflags=-s -w "+
"-buildid= -linkmode external -extldflags=-static "+
"-X hakurei.app/internal/info.buildVersion="+version+" "+
"-X hakurei.app/internal/info.hakureiPath="+prefix+"/bin/hakurei "+
"-X hakurei.app/internal/info.hsuPath="+prefix+"/bin/hsu "+
"-X main.hakureiPath="+prefix+"/bin/hakurei",
"./...",
"-X hakurei.app/internal/info.hsuPath="+prefix+"/bin/hsu",
"./cmd/hakurei",
"./cmd/sharefs",
)
log.Println()
log.Printf("Building cmd/hsu for %s/%s.", runtime.GOOS, runtime.GOARCH)
mustRun(
ctx, []string{"CGO_ENABLED=0"}, "go", "build",
"-trimpath",
verboseFlag, "-o", s,
"-ldflags=-s -w "+
"-buildid= "+
"-X main.hakureiPath="+prefix+"/bin/hakurei",
"./cmd/hsu",
)
log.Println()
if runTests {
log.Println("##### Testing Hakurei.")
mustRun(
ctx, "go", "test",
ctx, nil, "go", "test",
"-ldflags=-buildid= -linkmode external -extldflags=-static",
"./...",
)
+3 -1
View File
@@ -7,6 +7,7 @@ package main
import (
"context"
"crypto/rand"
"io"
"log"
"os"
"os/signal"
@@ -51,13 +52,14 @@ func init() {
func fatal(v ...any) {
log.Println(v...)
log.Println("unable to continue, please reboot and resolve the problem manually")
log.SetOutput(io.Discard)
select {}
}
// must calls fatal with err if it is non-nil.
func must(err error) {
if err != nil {
log.Println(err)
fatal(err)
select {}
}
}
+3 -2
View File
@@ -26,8 +26,9 @@ var _ report.RepresentableError = ModprobeError{}
func (ModprobeError) Representable() {}
func (e ModprobeError) Error() string {
return fmt.Sprintf(
"modprobe exit status %d: %s",
e.ExitCode, strings.TrimSpace(e.Stderr),
"%s (exit status %d)",
strings.TrimPrefix(strings.TrimSpace(e.Stderr), "modprobe: "),
e.ExitCode,
)
}
+5 -2
View File
@@ -64,7 +64,7 @@ func TestPrintShowInstance(t *testing.T) {
Identity: 9 (org.chromium.Chromium)
Enablements: wayland, dbus, pipewire
Groups: video, dialout, plugdev
Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, cover_run, runtime, tmpdir
Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, noplace, device, cover_run, runtime, tmpdir
Home: /data/data/org.chromium.Chromium
Hostname: localhost
Path: /run/current-system/sw/bin/chromium
@@ -161,7 +161,7 @@ App
Identity: 9 (org.chromium.Chromium)
Enablements: wayland, dbus, pipewire
Groups: video, dialout, plugdev
Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, cover_run, runtime, tmpdir
Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, noplace, device, cover_run, runtime, tmpdir
Home: /data/data/org.chromium.Chromium
Hostname: localhost
Path: /run/current-system/sw/bin/chromium
@@ -354,6 +354,7 @@ App
"tty": true,
"multiarch": true,
"map_real_uid": true,
"noplace": true,
"device": true,
"cover_run": true,
"share_runtime": true,
@@ -506,6 +507,7 @@ App
"tty": true,
"multiarch": true,
"map_real_uid": true,
"noplace": true,
"device": true,
"cover_run": true,
"share_runtime": true,
@@ -705,6 +707,7 @@ func TestPrintPs(t *testing.T) {
"tty": true,
"multiarch": true,
"map_real_uid": true,
"noplace": true,
"device": true,
"cover_run": true,
"share_runtime": true,
+61 -9
View File
@@ -5,6 +5,7 @@ import (
"net/http"
"os"
"path/filepath"
"strconv"
"testing"
"hakurei.app/check"
@@ -21,41 +22,66 @@ type cache struct {
// Should generally not be used directly.
c *pkg.Cache
cures, jobs int
attr pkg.CacheAttr
// Primarily to work around missing landlock LSM.
hostAbstract bool
// Set SCHED_IDLE.
idle bool
// Unset [pkg.CSuppressInit].
verboseInit bool
// Whether to enable output colours.
color bool
// Unset [pkg.CExternShallow].
deep bool
// Loaded artifact of [rosa.QEMU].
qemu pkg.Artifact
base, mirror string
}
// writeTitle sets title of the terminal connected to [message.Msg].
func writeTitle(msg message.Msg, s string) {
msg.Suspend()
w := msg.GetLogger().Writer()
_, _ = w.Write([]byte("\x1b]0;" + s + "\a"))
msg.Resume()
}
// open opens the underlying [pkg.Cache].
func (cache *cache) open() (err error) {
if cache.c != nil {
return os.ErrInvalid
}
var hostname string
if hostname, err = os.Hostname(); err != nil {
return
}
var base *check.Absolute
if cache.base, err = filepath.Abs(cache.base); err != nil {
return
} else if base, err = check.NewAbs(cache.base); err != nil {
return
}
var notify chan bool
var flags int
if cache.idle {
flags |= pkg.CSchedIdle
cache.attr.Flags |= pkg.CSchedIdle
}
if cache.hostAbstract {
flags |= pkg.CHostAbstract
cache.attr.Flags |= pkg.CHostAbstract
}
if !cache.verboseInit {
flags |= pkg.CSuppressInit
cache.attr.Flags |= pkg.CSuppressInit
}
if !cache.deep {
cache.attr.Flags |= pkg.CExternShallow
}
if cache.color {
cache.attr.Flags |= pkg.CColourOutput
notify = make(chan bool, 1<<12)
cache.attr.Notify = notify
}
done := make(chan struct{})
@@ -77,10 +103,8 @@ func (cache *cache) open() (err error) {
cache.c, err = pkg.Open(
cache.ctx,
cache.msg,
flags,
cache.cures,
cache.jobs,
base,
&cache.attr,
)
if err != nil {
return
@@ -95,13 +119,36 @@ func (cache *cache) open() (err error) {
return
}
var r rosa.Remote
if r, err = rosa.NewRemote(cache.mirror, pub, http.DefaultClient); err != nil {
if r, err = rosa.NewRemote(http.DefaultClient, cache.mirror, pub); err != nil {
cache.c.Close()
return err
}
cache.c.SetExternal(r)
}
if cache.attr.Notify != nil {
cache.msg.Suspend()
_, _ = cache.msg.GetLogger().Writer().Write([]byte("\x1b[22;0t"))
cache.msg.Resume()
prefix := hostname + ": mbf "
go func() {
var n, nc uint64
for enter := range notify {
if enter {
n++
nc++
} else {
nc--
}
writeTitle(cache.msg, prefix+
"("+strconv.FormatUint(nc, 10)+
" of "+strconv.FormatUint(n, 10)+")")
}
}()
}
if cache.qemu != nil {
var pathname *check.Absolute
pathname, _, err = cache.c.Cure(cache.qemu)
@@ -122,6 +169,11 @@ func (cache *cache) open() (err error) {
func (cache *cache) Close() {
if cache.c != nil {
cache.c.Close()
if cache.attr.Notify != nil {
cache.msg.Suspend()
_, _ = cache.msg.GetLogger().Writer().Write([]byte("\x1b[23;0t"))
cache.msg.Resume()
}
}
}
+5 -5
View File
@@ -28,8 +28,8 @@ func TestNoReply(t *testing.T) {
c, err := pkg.Open(
t.Context(),
message.New(log.New(os.Stderr, "cir: ", 0)),
0, 0, 0,
check.MustAbs(t.TempDir()),
nil,
)
if err != nil {
t.Fatalf("Open: error = %v", err)
@@ -63,7 +63,7 @@ func TestNoReply(t *testing.T) {
}
<-done
wantIdent := pkg.MustDecode("fiZf-ZY_Yq6qxJNrHbMiIPYCsGkUiKCRsZrcSELXTqZWtCnESlHmzV5ThhWWGGYG")
wantIdent := pkg.MustDecode("bpVsJ69hdKPBntMh_u777g7-quFNVmMlBJQOlM_thiQa9JnOFLAbe5OlR4zNjZ32")
if gotIdent := c.Ident(a).Value(); gotIdent != wantIdent {
t.Errorf(
"cureFromIR: %s, want %s",
@@ -124,7 +124,7 @@ func TestDaemon(t *testing.T) {
cancel()
<-done
const want = "fiZf-ZY_Yq6qxJNrHbMiIPYCsGkUiKCRsZrcSELXTqZWtCnESlHmzV5ThhWWGGYG"
const want = "bpVsJ69hdKPBntMh_u777g7-quFNVmMlBJQOlM_thiQa9JnOFLAbe5OlR4zNjZ32"
if got := filepath.Base(p.String()); got != want {
t.Errorf("cureRemote: %s, want %s", got, want)
}
@@ -132,8 +132,8 @@ func TestDaemon(t *testing.T) {
wantLog := []string{
"",
"daemon: aborting all pending cures",
"daemon: attempting to cancel invalid artifact kQm9fmnCmXST1-MMmxzcau2oKZCXXrlZydo4PkeV5hO_2PKfeC8t98hrbV_ZZx_j",
"daemon: fulfilled artifact fiZf-ZY_Yq6qxJNrHbMiIPYCsGkUiKCRsZrcSELXTqZWtCnESlHmzV5ThhWWGGYG",
"daemon: attempting to cancel invalid artifact 58Vy_5beLZCvZX__KzRKyIE6vATleaZP1ZBxbqoWnekz9aZ1zkxNgcIUFI5V1_Jf",
"daemon: fulfilled artifact " + want,
}
gotLog := strings.Split(buf.String(), "\n")
slices.Sort(gotLog)
+4 -1
View File
@@ -21,7 +21,10 @@ func commandInfo(
r *rosa.Report,
) (err error) {
if len(args) == 0 {
return errors.New("info requires at least 1 argument")
for _, h := range rosa.Native().CollectAll() {
fmt.Println(h)
}
return nil
}
// recovered by HandleAccess
+210 -40
View File
@@ -27,6 +27,7 @@ import (
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"sync/atomic"
"syscall"
@@ -91,6 +92,11 @@ func main() {
var cm cache
defer func() { cm.Close() }()
if cm.color = ext.Isatty(syscall.Stderr) &&
os.Getenv("NO_COLOR") == "" &&
os.Getenv("TERM") != "dumb"; cm.color {
log.SetPrefix("\x1b[2mmbf: \x1b[0m")
}
var (
flagQuiet bool
@@ -202,13 +208,17 @@ func main() {
"v", command.BoolFlag(false),
"Do not suppress verbose output from init",
).Flag(
&cm.cures,
&cm.attr.Cures,
"cures", command.IntFlag(0),
"Maximum number of dependencies to cure at any given time",
).Flag(
&cm.jobs,
&cm.attr.Jobs,
"jobs", command.IntFlag(0),
"Preferred number of jobs to run, when applicable",
).Flag(
&cm.attr.Load,
"load-average", command.IntFlag(0),
"Preferred load average number, when applicable",
).Flag(
&cm.base,
"d", command.StringFlag("$MBF_CACHE_DIR"),
@@ -217,6 +227,11 @@ func main() {
&cm.mirror,
"r", command.StringFlag("$MBF_REMOTE"),
"URL of mirror service",
).Flag(
&cm.deep,
"deep", command.BoolFlag(false),
"Cure all inputs even when the required artifact is available "+
"via the mirror service",
).Flag(
&cm.idle,
"sched-idle", command.BoolFlag(false),
@@ -268,7 +283,7 @@ func main() {
if _, err := io.Copy(h, os.Stdin); err != nil {
return err
}
log.Println(pkg.Encode(pkg.Checksum(h.Sum(nil))))
fmt.Println(pkg.Encode(pkg.Checksum(h.Sum(nil))))
return nil
},
)
@@ -539,7 +554,9 @@ func main() {
if base, err := os.OpenRoot(cm.base); err != nil {
return err
} else {
h = rosa.NewMirror(msg, base.FS(), key)
var mux http.ServeMux
rosa.NewMirror(msg, base.FS(), key).Register(&mux)
h = &mux
}
server := http.Server{Addr: args[0], Handler: h}
@@ -561,28 +578,52 @@ func main() {
},
)
c.NewCommand(
"snapshot",
"Populate an empty directory with a static mirror snapshot",
func(args []string) error {
if len(args) != 1 {
return errors.New("snapshot requires 1 argument")
}
var key ed25519.PrivateKey
if p, err := os.ReadFile(filepath.Join(cm.base, "ed25519")); err != nil {
return err
} else if len(p) != ed25519.PrivateKeySize {
return errors.New("invalid private key")
} else {
key = p
}
var m rosa.Mirror
if base, err := os.OpenRoot(cm.base); err != nil {
return err
} else {
m = rosa.NewMirror(msg, base.FS(), key)
}
retry:
root, err := os.OpenRoot(args[0])
if err != nil {
if os.IsNotExist(err) {
if err = os.MkdirAll(args[0], 0755); err != nil {
return err
}
goto retry
}
return err
}
go func() { <-ctx.Done(); _ = root.Close() }()
return m.Populate(root)
},
)
{
var (
flagGentoo string
flagChecksum string
)
c.NewCommand(
"stage3",
"stage4",
"Check for toolchain 3-stage non-determinism",
func(args []string) (err error) {
s := rosa.Std
if flagGentoo != "" {
s -= 3 // magic number to discourage misuse
var checksum pkg.Checksum
if len(flagChecksum) != 0 {
if err = pkg.Decode(&checksum, flagChecksum); err != nil {
return
}
}
rosa.Native().SetGentooStage3(flagGentoo, checksum)
}
var (
pathname *check.Absolute
checksum [2]unique.Handle[pkg.Checksum]
@@ -590,7 +631,7 @@ func main() {
_llvm := rosa.H("llvm")
if err = cm.Do(func(cache *pkg.Cache) (err error) {
_, llvm := rosa.Native().New(s - 2).Load(_llvm)
_, llvm := rosa.Native().New(rosa.Std - 2).Load(_llvm)
pathname, _, err = cache.Cure(llvm)
return
}); err != nil {
@@ -599,22 +640,32 @@ func main() {
log.Println("stage1:", pathname)
if err = cm.Do(func(cache *pkg.Cache) (err error) {
_, llvm := rosa.Native().New(s - 1).Load(_llvm)
pathname, checksum[0], err = cache.Cure(llvm)
_, llvm := rosa.Native().New(rosa.Std - 1).Load(_llvm)
pathname, _, err = cache.Cure(llvm)
return
}); err != nil {
return
}
log.Println("stage2:", pathname)
if err = cm.Do(func(cache *pkg.Cache) (err error) {
_, llvm := rosa.Native().New(s).Load(_llvm)
pathname, checksum[1], err = cache.Cure(llvm)
_, llvm := rosa.Native().New(rosa.Std).Load(_llvm)
pathname, checksum[0], err = cache.Cure(llvm)
return
}); err != nil {
return
}
log.Println("stage3:", pathname)
if err = cm.Do(func(cache *pkg.Cache) (err error) {
_, llvm := rosa.Native().New(rosa.Stage3).Load(_llvm)
pathname, checksum[1], err = cache.Cure(llvm)
return
}); err != nil {
return
}
log.Println("stage4:", pathname)
if checksum[0] != checksum[1] {
err = &pkg.ChecksumMismatchError{
Got: checksum[0].Value(),
@@ -622,23 +673,34 @@ func main() {
}
} else {
log.Println(
"stage2 is identical to stage3",
"stage3 is identical to stage4",
"("+pkg.Encode(checksum[0].Value())+")",
)
}
return
},
).Flag(
&flagGentoo,
"gentoo", command.StringFlag(""),
"Bootstrap from a Gentoo stage3 tarball",
).Flag(
&flagChecksum,
"checksum", command.StringFlag(""),
"Checksum of Gentoo stage3 tarball",
)
}
c.NewCommand(
"all",
command.UsageInternal,
func([]string) error {
all := rosa.Native().CollectAll()
a := make(pkg.Collect, len(all))
for i, h := range all {
_, a[i] = rosa.Native().Std().Load(h)
}
return cm.Do(func(cache *pkg.Cache) (err error) {
_, _, err = cache.Cure(&a)
if pkg.IsCollected(err) {
err = nil
}
return
})
},
)
{
var (
flagDump string
@@ -648,9 +710,13 @@ func main() {
flagNoReply bool
flagFaults bool
flagPop bool
flagRebuild bool
flagBoot bool
flagStd bool
flagGentoo string
flagChecksum string
)
c.NewCommand(
"cure",
@@ -667,6 +733,18 @@ func main() {
t -= 1
}
if flagGentoo != "" {
var checksum pkg.Checksum
if len(flagChecksum) != 0 {
if err := pkg.Decode(&checksum, flagChecksum); err != nil {
return err
}
}
rosa.Native().SetGentooStage3(flagGentoo, checksum)
t -= 3 // magic number to discourage misuse
}
_, a := rosa.Native().New(t).Load(rosa.ArtifactH(unique.Make(args[0])))
if a == nil {
return fmt.Errorf("unknown artifact %q", args[0])
@@ -676,13 +754,17 @@ func main() {
default:
var pathname *check.Absolute
err := cm.Do(func(cache *pkg.Cache) (err error) {
pathname, _, err = cache.Cure(a)
if flagRebuild {
pathname, _, err = cache.CureNew(a)
} else {
pathname, _, err = cache.Cure(a)
}
return
})
if err != nil {
return err
}
log.Println(pathname)
fmt.Println(pathname)
if flagExport != "" {
msg.Verbosef("exporting %s to %s...", args[0], flagExport)
@@ -731,7 +813,7 @@ func main() {
ctx,
a,
"", true, os.Stdin, os.Stdout, os.Stderr,
rosa.AbsSystem.Append("bin", "mksh"),
rosa.AbsSystem.Append("bin", "sh"),
"sh",
)
})
@@ -743,7 +825,7 @@ func main() {
}
pathname, err := cureRemote(ctx, &addr, a, flags)
if !flagNoReply && err == nil {
log.Println(pathname)
fmt.Println(pathname)
}
if errors.Is(err, context.Canceled) {
@@ -837,9 +919,97 @@ func main() {
&flagPop,
"pop", command.BoolFlag(false),
"Display and destroy the most recent fault entry",
).Flag(
&flagRebuild,
"rebuild", command.BoolFlag(false),
"Always enter the artifact implementation",
).Flag(
&flagGentoo,
"gentoo", command.StringFlag(""),
"Bootstrap from a Gentoo stage3 tarball",
).Flag(
&flagChecksum,
"checksum", command.StringFlag(""),
"Checksum of Gentoo stage3 tarball",
)
}
c.NewCommand(
"validate",
"Repeatedly cure named artifact to validate determinism",
func(args []string) error {
stage := rosa.Std
if len(args) == 3 {
switch args[0] {
case "boot":
stage -= 2
case "std":
stage -= 1
default:
return fmt.Errorf("invalid stage %q", args[0])
}
args = args[1:]
}
if len(args) != 2 {
return errors.New("validate requires 2 arguments")
}
n, err := strconv.Atoi(args[0])
if err != nil {
return fmt.Errorf("invalid passes %q", args[0])
}
if n < 2 {
return errors.New("validate must rebuild at least twice")
}
_, a := rosa.Native().New(stage).Load(rosa.ArtifactH(unique.Make(args[1])))
if a == nil {
return fmt.Errorf("unknown artifact %q", args[1])
}
if !a.IsExclusive() && cm.attr.Jobs < 1 {
cm.attr.Jobs = runtime.NumCPU()/n + 1
}
res := make([]unique.Handle[pkg.Checksum], n)
if err = cm.Do(func(cache *pkg.Cache) error {
errs := make([]error, n)
var wg sync.WaitGroup
for i := range n {
wg.Go(func() {
_, res[i], errs[i] = cache.CureNew(a)
})
}
wg.Wait()
return errors.Join(errs...)
}); err != nil {
return err
}
for i := range n - 1 {
if res[i] == res[i+1] {
continue
}
var buf strings.Builder
buf.WriteString("nondeterminism:")
for _, o := range res {
buf.WriteString("\n\t")
buf.WriteString(filepath.Join(
cm.base,
"checksum",
pkg.Encode(o.Value()),
))
}
return errors.New(buf.String())
}
return nil
},
)
cleanC := c.New("clean", "Remove unused entries from the cache")
cleanC.NewCommand(
"fault",
+10
View File
@@ -65,6 +65,8 @@ const (
// Some programs fail to connect to dbus session running as a different uid,
// this option works around it by mapping priv-side caller uid in container.
FMapRealUID
// FNoPlace disables placement of /etc/passwd and /etc/group.
FNoPlace
// FDevice mount /dev/ from the init mount namespace as is in the container
// mount namespace.
@@ -101,6 +103,8 @@ func (flags Flags) String() string {
return "tty"
case FMapRealUID:
return "mapuid"
case FNoPlace:
return "noplace"
case FDevice:
return "device"
case FCoverRun:
@@ -197,6 +201,8 @@ type containerConfigJSON = struct {
// Corresponds to [FMapRealUID].
MapRealUID bool `json:"map_real_uid"`
// Corresponds to [FNoPlace].
NoPlace bool `json:"noplace,omitempty"`
// Corresponds to [FDevice].
Device bool `json:"device,omitempty"`
@@ -224,6 +230,7 @@ func (c *ContainerConfig) MarshalJSON() ([]byte, error) {
Tty: c.Flags&FTty != 0,
Multiarch: c.Flags&FMultiarch != 0,
MapRealUID: c.Flags&FMapRealUID != 0,
NoPlace: c.Flags&FNoPlace != 0,
Device: c.Flags&FDevice != 0,
CoverRun: c.Flags&FCoverRun != 0,
ShareRuntime: c.Flags&FShareRuntime != 0,
@@ -266,6 +273,9 @@ func (c *ContainerConfig) UnmarshalJSON(data []byte) error {
if v.MapRealUID {
c.Flags |= FMapRealUID
}
if v.NoPlace {
c.Flags |= FNoPlace
}
if v.Device {
c.Flags |= FDevice
}
+3 -3
View File
@@ -21,8 +21,8 @@ func TestFlagsString(t *testing.T) {
}{
{"none", 0, "none"},
{"none high", hst.FAll + 1, "none"},
{"all", hst.FAll, "multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, cover_run, runtime, tmpdir"},
{"all high", math.MaxUint, "multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, cover_run, runtime, tmpdir"},
{"all", hst.FAll, "multiarch, compat, devel, userns, net, abstract, tty, mapuid, noplace, device, cover_run, runtime, tmpdir"},
{"all high", math.MaxUint, "multiarch, compat, devel, userns, net, abstract, tty, mapuid, noplace, device, cover_run, runtime, tmpdir"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
@@ -53,7 +53,7 @@ func TestContainerConfig(t *testing.T) {
{"hostnet hostabstract mapuid", &hst.ContainerConfig{Flags: hst.FHostNet | hst.FHostAbstract | hst.FMapRealUID},
`{"env":null,"filesystem":null,"shell":null,"home":null,"args":null,"host_net":true,"host_abstract":true,"map_real_uid":true}`},
{"all", &hst.ContainerConfig{Flags: hst.FAll},
`{"env":null,"filesystem":null,"shell":null,"home":null,"args":null,"seccomp_compat":true,"devel":true,"userns":true,"host_net":true,"host_abstract":true,"tty":true,"multiarch":true,"map_real_uid":true,"device":true,"cover_run":true,"share_runtime":true,"share_tmpdir":true}`},
`{"env":null,"filesystem":null,"shell":null,"home":null,"args":null,"seccomp_compat":true,"devel":true,"userns":true,"host_net":true,"host_abstract":true,"tty":true,"multiarch":true,"map_real_uid":true,"noplace":true,"device":true,"cover_run":true,"share_runtime":true,"share_tmpdir":true}`},
}
for _, tc := range testCases {
+2 -2
View File
@@ -82,9 +82,9 @@ func (o *FSOverlay) Apply(z *ApplyState) {
z.Overlay(o.Target, o.Upper, o.Work, o.Lower...)
} else {
z.OverlayEphemeral(o.Target, slices.Concat(
[]*check.Absolute{o.Upper},
o.Lower,
[]*check.Absolute{o.Upper})...,
)
)...)
}
} else {
z.OverlayReadonly(o.Target, o.Lower...)
+1 -1
View File
@@ -70,7 +70,7 @@ func TestFSOverlay(t *testing.T) {
Upper: m("/tmp/upper"),
}, true, container.Ops{&container.MountOverlayOp{
Target: m("/"),
Lower: ms("/tmp/.src0", "/tmp/.src1", "/tmp/upper"),
Lower: ms("/tmp/upper", "/tmp/.src0", "/tmp/.src1"),
Upper: fhs.AbsRoot,
}}, m("/"), ms("/tmp/upper", "/tmp/.src0", "/tmp/.src1"),
"e*/:/tmp/upper:/tmp/.src0:/tmp/.src1"},
+1
View File
@@ -244,6 +244,7 @@ func TestTemplate(t *testing.T) {
"tty": true,
"multiarch": true,
"map_real_uid": true,
"noplace": true,
"device": true,
"cover_run": true,
"share_runtime": true,
+24 -4
View File
@@ -1,21 +1,29 @@
// Package env provides the [Paths] struct for efficiently building paths from the environment.
// Package env provides the [Paths] struct for efficiently building paths from
// the environment.
package env
import (
"errors"
"io/fs"
"log"
"os"
"strconv"
"hakurei.app/check"
"hakurei.app/fhs"
"hakurei.app/hst"
)
const VarRunNscd = fhs.Var + "run/nscd"
// Paths holds paths copied from the environment and is used to create [hst.Paths].
type Paths struct {
// TempDir is returned by [os.TempDir].
TempDir *check.Absolute
// RuntimePath is copied from $XDG_RUNTIME_DIR.
RuntimePath *check.Absolute
// Whether [VarRunNscd] is a directory.
HasNscd bool
}
// Copy expands [Paths] into [hst.Paths].
@@ -37,14 +45,17 @@ func (env *Paths) Copy(v *hst.Paths, userid int) {
}
// CopyPaths returns a populated [Paths].
func CopyPaths() *Paths { return CopyPathsFunc(log.Fatalf, os.TempDir, os.Getenv) }
func CopyPaths() *Paths {
return CopyPathsFunc(log.Fatalf, os.TempDir, os.Getenv, os.Stat)
}
// CopyPathsFunc returns a populated [Paths],
// using the provided [log.Fatalf], [os.TempDir], [os.Getenv] functions.
// CopyPathsFunc returns a populated [Paths], using the provided [log.Fatalf],
// [os.TempDir], [os.Getenv] functions.
func CopyPathsFunc(
fatalf func(format string, v ...any),
tempdir func() string,
getenv func(key string) string,
stat func(name string) (fs.FileInfo, error),
) *Paths {
const xdgRuntimeDir = "XDG_RUNTIME_DIR"
@@ -61,5 +72,14 @@ func CopyPathsFunc(
env.RuntimePath = a
}
if fi, err := stat(VarRunNscd); err != nil {
if !errors.Is(err, fs.ErrNotExist) {
fatalf("%v", err)
panic("unreachable")
}
} else {
env.HasNscd = fi.IsDir()
}
return &env
}
+4 -1
View File
@@ -2,6 +2,7 @@ package env_test
import (
"fmt"
"io/fs"
"reflect"
"testing"
@@ -104,7 +105,9 @@ func TestCopyPaths(t *testing.T) {
t.Fatalf("fatalf: %q, want %q", got, tc.fatal)
}
panic(stub.PanicExit)
}, func() string { return tc.tmp }, func(key string) string { return tc.env[key] })
}, func() string { return tc.tmp }, func(key string) string { return tc.env[key] }, func(name string) (fs.FileInfo, error) {
return nil, fs.ErrNotExist
})
if tc.fatal != "" {
t.Fatalf("copyPaths: expected fatal %q", tc.fatal)
+2
View File
@@ -23,6 +23,7 @@ import (
"hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/hst"
"hakurei.app/internal/env"
"hakurei.app/internal/stub"
"hakurei.app/internal/system"
"hakurei.app/message"
@@ -174,6 +175,7 @@ func checkOpBehaviour(t *testing.T, testCases []opBehaviourTestCase) {
call("cmdOutput", stub.ExpectArgs{container.Nonexistent, os.Stderr, []string{}, "/"}, []byte("0"), nil),
call("tempdir", stub.ExpectArgs{}, container.Nonexistent+"/tmp", nil),
call("lookupEnv", stub.ExpectArgs{"XDG_RUNTIME_DIR"}, wantRuntimePath, nil),
call("stat", stub.ExpectArgs{env.VarRunNscd}, stubFileInfoIsDir(true), nil),
call("getuid", stub.ExpectArgs{}, 1000, nil),
call("getgid", stub.ExpectArgs{}, 100, nil),
+1 -1
View File
@@ -110,7 +110,7 @@ func newOutcomeState(k syscallDispatcher, msg message.Msg, id *hst.ID, config *h
Paths: env.CopyPathsFunc(k.fatalf, k.tempdir, func(key string) string {
v, _ := k.lookupEnv(key)
return v
}),
}, k.stat),
Container: config.Container,
}
+2 -8
View File
@@ -143,10 +143,6 @@ func TestOutcomeRun(t *testing.T) {
// spTmpdirOp
Bind(m("/tmp/hakurei.0/tmpdir/9"), fhs.AbsTmp, std.BindWritable).
// spAccountOp
Place(m("/etc/passwd"), []byte("chronos:x:1971:100:Hakurei:/data/data/org.chromium.Chromium:/run/current-system/sw/bin/zsh\n")).
Place(m("/etc/group"), []byte("hakurei:x:100:\n")).
// spWaylandOp
Bind(m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/wayland"), m("/run/user/1971/wayland-0"), 0).
@@ -453,7 +449,7 @@ func TestOutcomeRun(t *testing.T) {
Path: m("/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start"),
Flags: hst.FUserns | hst.FHostNet | hst.FMapRealUID | hst.FShareRuntime | hst.FShareTmpdir,
Flags: hst.FUserns | hst.FHostNet | hst.FMapRealUID | hst.FNoPlace | hst.FShareRuntime | hst.FShareTmpdir,
},
SystemBus: &hst.BusConfig{
Talk: []string{"org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"},
@@ -548,8 +544,6 @@ func TestOutcomeRun(t *testing.T) {
Tmpfs(m("/run/user/"), xdgRuntimeDirSize, 0755).
Bind(m("/tmp/hakurei.0/runtime/1"), m("/run/user/1971"), std.BindWritable).
Bind(m("/tmp/hakurei.0/tmpdir/1"), m("/tmp/"), std.BindWritable).
Place(m("/etc/passwd"), []byte("u0_a1:x:1971:100:Hakurei:/var/lib/persist/module/hakurei/0/1:/run/current-system/sw/bin/zsh\n")).
Place(m("/etc/group"), []byte("hakurei:x:100:\n")).
Bind(m("/run/user/1971/wayland-0"), m("/run/user/1971/wayland-0"), 0).
Bind(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/pipewire"), m("/run/user/1971/pipewire-0"), 0).
Bind(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus"), m("/run/user/1971/bus"), 0).
@@ -716,7 +710,7 @@ func (k *stubNixOS) lookupEnv(key string) (string, bool) {
func (k *stubNixOS) stat(name string) (fs.FileInfo, error) {
switch name {
case "/var/run/nscd":
return nil, nil
return stubFileInfoIsDir(true), nil
case "/run/user/1971/pulse":
return nil, nil
case "/run/user/1971/pulse/native":
-4
View File
@@ -78,10 +78,6 @@ func TestShimEntrypoint(t *testing.T) {
// spTmpdirOp
Bind(m("/tmp/hakurei.10/tmpdir/9999"), fhs.AbsTmp, std.BindWritable).
// spAccountOp
Place(m("/etc/passwd"), []byte("chronos:x:1000:100:Hakurei:/data/data/org.chromium.Chromium:/run/current-system/sw/bin/zsh\n")).
Place(m("/etc/group"), []byte("hakurei:x:100:\n")).
// spWaylandOp
Bind(m("/tmp/hakurei.10/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/wayland"), m("/run/user/1000/wayland-0"), 0).
+13 -10
View File
@@ -6,6 +6,7 @@ import (
"syscall"
"hakurei.app/fhs"
"hakurei.app/hst"
"hakurei.app/internal/validate"
)
@@ -41,16 +42,18 @@ func (s spAccountOp) toContainer(state *outcomeStateParams) error {
state.env["USER"] = username
state.env["SHELL"] = state.Container.Shell.String()
state.params.
Place(fhs.AbsEtc.Append("passwd"),
[]byte(username+":x:"+
state.mapuid.String()+":"+
state.mapgid.String()+
":Hakurei:"+
state.Container.Home.String()+":"+
state.Container.Shell.String()+"\n")).
Place(fhs.AbsEtc.Append("group"),
[]byte("hakurei:x:"+state.mapgid.String()+":\n"))
if state.Container.Flags&hst.FNoPlace == 0 {
state.params.
Place(fhs.AbsEtc.Append("passwd"),
[]byte(username+":x:"+
state.mapuid.String()+":"+
state.mapgid.String()+
":Hakurei:"+
state.Container.Home.String()+":"+
state.Container.Shell.String()+"\n")).
Place(fhs.AbsEtc.Append("group"),
[]byte("hakurei:x:"+state.mapgid.String()+":\n"))
}
return nil
}
+2 -3
View File
@@ -38,6 +38,7 @@ func TestSpAccountOp(t *testing.T) {
{"success fallback username", func(bool, bool) outcomeOp { return spAccountOp{} }, func() *hst.Config {
c := hst.Template()
c.Container.Username = ""
c.Container.Flags = hst.FMapRealUID
return c
}, nil, []stub.Call{
// this op performs basic validation and does not make calls during toSystem
@@ -60,9 +61,7 @@ func TestSpAccountOp(t *testing.T) {
// this op configures the container state and does not make calls during toContainer
}, &container.Params{
Dir: config.Container.Home,
Ops: new(container.Ops).
Place(m("/etc/passwd"), []byte("chronos:x:1000:100:Hakurei:/data/data/org.chromium.Chromium:/run/current-system/sw/bin/zsh\n")).
Place(m("/etc/group"), []byte("hakurei:x:100:\n")),
Ops: new(container.Ops),
}, paramsWantEnv(config, map[string]string{
"HOME": config.Container.Home.String(),
"USER": config.Container.Username,
+14 -9
View File
@@ -18,13 +18,12 @@ import (
"hakurei.app/hst"
"hakurei.app/internal/acl"
"hakurei.app/internal/dbus"
"hakurei.app/internal/env"
"hakurei.app/internal/system"
"hakurei.app/internal/validate"
"hakurei.app/message"
)
const varRunNscd = fhs.Var + "run/nscd"
func init() { gob.Register(new(spParamsOp)) }
// spParamsOp initialises unordered fields of [container.Params] and the
@@ -136,17 +135,23 @@ type spFilesystemOp struct {
}
func (s *spFilesystemOp) toSystem(state *outcomeStateSys) error {
/* retrieve paths and hide them if they're made available in the sandbox;
this feature tries to improve user experience of permissive defaults, and
to warn about issues in custom configuration; it is NOT a security feature
and should not be treated as such, ALWAYS be careful with what you bind */
// retrieve paths and hide them if they're made available in the sandbox
//
// this feature tries to improve user experience of permissive defaults, and
// to warn about issues in custom configuration; it is NOT a security feature
// and should not be treated as such, ALWAYS be careful with what you bind
hidePaths := []string{
state.sc.RuntimePath.String(),
state.sc.SharePath.String(),
}
// this causes emulated passwd database to be bypassed on some /etc/ setups
varRunNscd,
if state.Paths == nil || state.HasNscd {
hidePaths = append(hidePaths,
// this causes emulated passwd database to be bypassed on some /etc/
// setups, made optional to avoid needlessly creating it on
// non-glibc systems when invoking permissive defaults
env.VarRunNscd,
)
}
// dbus.Address does not go through syscallDispatcher
+8 -2
View File
@@ -278,6 +278,8 @@ type archiveArtifact struct {
f Artifact
}
var _ CuresExempt = archiveArtifact{}
// NewArchive returns a new [Artifact] backed by the supplied [Artifact]. The
// source [Artifact] must be a [FileArtifact] and produce a stream compatible
// with [Reader].
@@ -301,8 +303,8 @@ func init() {
})
}
// Dependencies returns a slice containing the backing file.
func (a archiveArtifact) Dependencies() []Artifact {
// Inputs returns a slice containing the backing file.
func (a archiveArtifact) Inputs() []Artifact {
return []Artifact{a.f}
}
@@ -403,3 +405,7 @@ func (a archiveArtifact) Cure(t *TContext) (err error) {
}
return
}
// CuresExempt exempts the cheap [KindArchive] implementation often found at
// the end of a [FileArtifact] pipeline.
func (archiveArtifact) CuresExempt() {}
+2 -2
View File
@@ -186,7 +186,7 @@ func TestArchiveArtifact(t *testing.T) {
cureMany(t, c, []cureStep{
{"sample", pkg.NewArchive(
pkg.NewFile("", buf.Bytes()),
), ignorePathname, expectsFS(want), nil},
), ignorePathname, expectsFS(want), pkg.WNew, nil},
})
}, expectsFS{
".": {Mode: fs.ModeDir | 0700},
@@ -202,7 +202,7 @@ func TestArchiveArtifact(t *testing.T) {
"checksum/CBPcoVHuVUTVRCMbRl8J30RSSzm_tyfuXaZ-HlZsanY1sY50meOVmgaWDrGKbx9F/devices/uevent": {Mode: 0600, Data: []byte("add")},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/3oYyAbRJ_we7AgWo1BRcRcnxXFk3mAQ0Qui2nGQMi8GIJNJQtvUC6P2IeoA5mbjD": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CBPcoVHuVUTVRCMbRl8J30RSSzm_tyfuXaZ-HlZsanY1sY50meOVmgaWDrGKbx9F")},
"identifier/-zXKfphyWM2Ko7VMVURaEMSuixNokFSe0xFbnwR2RtRtvMrcPGWalV0LIn45PXTY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CBPcoVHuVUTVRCMbRl8J30RSSzm_tyfuXaZ-HlZsanY1sY50meOVmgaWDrGKbx9F")},
"substitute": {Mode: fs.ModeDir | 0700},
"work": {Mode: fs.ModeDir | 0700},
+12 -3
View File
@@ -73,7 +73,10 @@ func (c *Cache) Clean(dry, inputs bool, keep ...Artifact) (
continue
}
c.msg.Verbosef("arranging for destruction of %s...", name)
c.msg.Verbosef(
"arranging for destruction of %s%s%s...",
c.sgrIdent, name, c.sgrRes,
)
idents = append(idents, identPair{id, name})
}
@@ -102,7 +105,10 @@ func (c *Cache) Clean(dry, inputs bool, keep ...Artifact) (
if err = c.parent.Err(); err != nil {
return destroyedIdents, destroyedChecksums, err
}
c.msg.Verbosef("destroying checksum %s...", name)
c.msg.Verbosef(
"destroying checksum %s%s%s...",
c.sgrIdent, name, c.sgrRes,
)
if !dry {
if err = errors.Join(removeAll(c.base.Append(
dirChecksum,
@@ -130,7 +136,10 @@ func (c *Cache) Clean(dry, inputs bool, keep ...Artifact) (
continue
}
c.msg.Verbosef("destroying substitute %s...", name)
c.msg.Verbosef(
"destroying substitute %s%s%s...",
c.sgrIdent, name, c.sgrRes,
)
if !dry {
if err = os.Remove(c.base.Append(
dirStatus,
+12 -12
View File
@@ -48,7 +48,7 @@ func TestClean(t *testing.T) {
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/pPRjw2XYgjB5k8dYedwxTBMgHh4_v2JM_G2Vd-skQbAGOOgPsl3CGSUbEF7om_MO": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
"identifier/h6qx7m0vsyhO6oLEJgY2rKa1c6RZuIZ4QXxZSh__NZJ9VU0MIj5bFB-KuaPcsfpE": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
"lock": {Mode: 0644},
"variant": {Mode: 0400},
@@ -69,7 +69,7 @@ func TestClean(t *testing.T) {
"checksum/KgZ-FjbGuU-XP2QEHInpgv-2Zn0cTH5NqFMgTU0XrSdKmSwyC-3baVs1BMCP5spk": {Mode: 0400, Data: []byte("\xfd")},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/FMwSBYw22KqM8jZryfY2ChHXpLuVDdWYyNOYdHvIVYk8ujY6UnGRm5brr2sTTfpD": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/KgZ-FjbGuU-XP2QEHInpgv-2Zn0cTH5NqFMgTU0XrSdKmSwyC-3baVs1BMCP5spk")},
"identifier/tkrOYhQfTRaArk4nNYNjTmHQUmuJMVIoDeAKIQBm3I4uuMimBKXKMIY2gGZqwQg4": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/KgZ-FjbGuU-XP2QEHInpgv-2Zn0cTH5NqFMgTU0XrSdKmSwyC-3baVs1BMCP5spk")},
"lock": {Mode: 0644},
"variant": {Mode: 0400},
@@ -122,16 +122,16 @@ func TestClean(t *testing.T) {
"checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE/result": {Mode: 0444},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/Ef8KX6s_rS_nLgze0rj90zKyrGAvOnzyU0DL7nrYQWEG_f4a9pmUKI6HBEMD8AE8": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/H-eSiCo227-xdqyNl2R-5G3eqXPtbb8XegAB70I5OQb2majeZXJoCxTq9wJy5qqv")},
"identifier/xoIGLemzLF227e-w_AJcf_1Sgqh2gs3KFgqvOIWUQE-9P_y2vHBMBytL4GRGQqTb": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"identifier/KpxTUsUfGbsX6C6HU2j9cd9He3_tt2o2m2MgH4m0zial8lmoqSWY-Gc3KrS0k-UK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/H-eSiCo227-xdqyNl2R-5G3eqXPtbb8XegAB70I5OQb2majeZXJoCxTq9wJy5qqv")},
"identifier/xxQ43VMIS1WHMSEFnUdBNd6pulbtgiTorP_mtJpEsZENYhGBiDEL6Y2D8yqn0Sra": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"lock": {Mode: 0644},
"variant": {Mode: 0400},
"status": {Mode: fs.ModeDir | 0700},
"substitute": {Mode: fs.ModeDir | 0700},
"substitute/4bjS-QjGcSV4nth-W6Vg3-wolKmKgiq4Ld2oRIWcOfy6Wi41XXLAWPoo8FcDx6BH": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"substitute/dzO8FEY9lu4hwRT6BfRZOX-uYGsC_5XH4jEJ7sJyThcmG9J_w1ArOAaUCGfL8wAM": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"substitute/dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"substitute/td1tf1kb3z8iUFg2k1xlHeTTEz3xR4e77WSWdv2JhjmZyY6iuvodhdT8BblDOi0E": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"fault": {Mode: fs.ModeDir | 0700},
"work": {Mode: fs.ModeDir | 0700},
@@ -199,18 +199,18 @@ func TestClean(t *testing.T) {
"checksum/H-eSiCo227-xdqyNl2R-5G3eqXPtbb8XegAB70I5OQb2majeZXJoCxTq9wJy5qqv": {Mode: 0400, Data: []byte("kept")},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/Ef8KX6s_rS_nLgze0rj90zKyrGAvOnzyU0DL7nrYQWEG_f4a9pmUKI6HBEMD8AE8": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/H-eSiCo227-xdqyNl2R-5G3eqXPtbb8XegAB70I5OQb2majeZXJoCxTq9wJy5qqv")},
"identifier/xoIGLemzLF227e-w_AJcf_1Sgqh2gs3KFgqvOIWUQE-9P_y2vHBMBytL4GRGQqTb": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CyDnDvF-LaeGPcSW70tPosNCoclByWkTjznUUF1DcgzlIwkN9yzz1ZFME1TlPj6W")},
"identifier/KpxTUsUfGbsX6C6HU2j9cd9He3_tt2o2m2MgH4m0zial8lmoqSWY-Gc3KrS0k-UK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/H-eSiCo227-xdqyNl2R-5G3eqXPtbb8XegAB70I5OQb2majeZXJoCxTq9wJy5qqv")},
"identifier/xxQ43VMIS1WHMSEFnUdBNd6pulbtgiTorP_mtJpEsZENYhGBiDEL6Y2D8yqn0Sra": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CyDnDvF-LaeGPcSW70tPosNCoclByWkTjznUUF1DcgzlIwkN9yzz1ZFME1TlPj6W")},
"lock": {Mode: 0644},
"variant": {Mode: 0400},
"status": {Mode: fs.ModeDir | 0700},
"status/4bjS-QjGcSV4nth-W6Vg3-wolKmKgiq4Ld2oRIWcOfy6Wi41XXLAWPoo8FcDx6BH": {Mode: 0400, Data: []byte(statusHeader + "kept")},
"status/xoIGLemzLF227e-w_AJcf_1Sgqh2gs3KFgqvOIWUQE-9P_y2vHBMBytL4GRGQqTb": {Mode: 0400, Data: []byte(statusHeader + "kept")},
"status/xxQ43VMIS1WHMSEFnUdBNd6pulbtgiTorP_mtJpEsZENYhGBiDEL6Y2D8yqn0Sra": {Mode: 0400, Data: []byte(statusHeader + "kept")},
"status/td1tf1kb3z8iUFg2k1xlHeTTEz3xR4e77WSWdv2JhjmZyY6iuvodhdT8BblDOi0E": {Mode: 0400, Data: []byte(statusHeader + "kept")},
"substitute": {Mode: fs.ModeDir | 0700},
"substitute/4bjS-QjGcSV4nth-W6Vg3-wolKmKgiq4Ld2oRIWcOfy6Wi41XXLAWPoo8FcDx6BH": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CyDnDvF-LaeGPcSW70tPosNCoclByWkTjznUUF1DcgzlIwkN9yzz1ZFME1TlPj6W")},
"substitute/td1tf1kb3z8iUFg2k1xlHeTTEz3xR4e77WSWdv2JhjmZyY6iuvodhdT8BblDOi0E": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CyDnDvF-LaeGPcSW70tPosNCoclByWkTjznUUF1DcgzlIwkN9yzz1ZFME1TlPj6W")},
"fault": {Mode: fs.ModeDir | 0700},
"work": {Mode: fs.ModeDir | 0700},
@@ -238,7 +238,7 @@ func TestClean(t *testing.T) {
base := makeBase(t)
msg := message.New(log.New(os.Stderr, "clean: ", 0))
msg.SwapVerbose(testing.Verbose())
c, err := pkg.Open(t.Context(), msg, 0, 0, 0, base)
c, err := pkg.Open(t.Context(), msg, base, nil)
if err != nil {
t.Fatal(err)
}
+34 -2
View File
@@ -6,6 +6,9 @@ import (
"fmt"
"io"
"os"
"hakurei.app/internal/xz"
"hakurei.app/internal/zstd"
)
const (
@@ -13,6 +16,10 @@ const (
Gzip = iota
// Bzip2 denotes a stream compressed via [bzip2].
Bzip2
// Zstd denotes a stream compressed via [zstd].
Zstd
// XZ denotes a stream compressed via [xz].
XZ
)
// A decompressArtifact is a [FileArtifact] decompressing a backing
@@ -25,6 +32,7 @@ type decompressArtifact struct {
}
var _ FileArtifact = new(decompressArtifact)
var _ CuresExempt = new(decompressArtifact)
// decompressArtifactNamed embeds decompressArtifact for a [fmt.Stringer] stream.
type decompressArtifactNamed struct {
@@ -65,8 +73,8 @@ func init() {
})
}
// Dependencies returns a slice containing the backing file.
func (a *decompressArtifact) Dependencies() []Artifact {
// Inputs returns a slice containing the backing file.
func (a *decompressArtifact) Inputs() []Artifact {
return []Artifact{a.f}
}
@@ -90,6 +98,9 @@ func (c compoundCloser) Close() error {
return err
}
// IsExecutable returns false.
func (*decompressArtifact) IsExecutable() bool { return false }
// Cure returns a decompressor [io.ReadCloser].
func (a *decompressArtifact) Cure(r *RContext) (io.ReadCloser, error) {
sr, err := r.Open(a.f)
@@ -113,7 +124,28 @@ func (a *decompressArtifact) Cure(r *RContext) (io.ReadCloser, error) {
io.Closer
}{bzip2.NewReader(br), br}, nil
case Zstd:
return struct {
io.Reader
io.Closer
}{zstd.NewReader(br), br}, nil
case XZ:
var _dr io.Reader
if _dr, err = xz.NewReader(br, 0); err != nil {
_ = br.Close()
return nil, err
}
return struct {
io.Reader
io.Closer
}{_dr, br}, nil
default:
return nil, os.ErrInvalid
}
}
// CuresExempt exempts the cheap [KindDecompress] implementation often part of
// a [FileArtifact] pipeline.
func (*decompressArtifact) CuresExempt() {}
+3 -3
View File
@@ -43,7 +43,7 @@ func TestDecompress(t *testing.T) {
&client,
"file:///testdata",
pkg.Checksum{0xfd},
), pkg.Gzip), nil, nil, &pkg.ChecksumMismatchError{
), pkg.Gzip), nil, nil, pkg.WNew, &pkg.ChecksumMismatchError{
Got: testdataChecksum,
Want: pkg.Checksum{0xfd},
}},
@@ -52,7 +52,7 @@ func TestDecompress(t *testing.T) {
&client,
"file:///testdata",
testdataChecksum,
), pkg.Gzip), ignorePathname, expectsChecksum(sha512.Sum384([]byte{0})), nil},
), pkg.Gzip), ignorePathname, expectsChecksum(sha512.Sum384([]byte{0})), pkg.WNew, nil},
})
}, expectsFS{
".": {Mode: fs.ModeDir | 0700},
@@ -61,7 +61,7 @@ func TestDecompress(t *testing.T) {
"checksum/" + pkg.Encode(sha512.Sum384([]byte{0})): {Mode: 0400, Data: []byte{0}},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/QpjkahDrz7pz-tv0eAGNXR6x9NAtTjWCK5Hr7G1cIZj9rT7bLYJWUQeLD4wamAlF": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
"identifier/mae-iR_9LFT_BOEJ2IRzKsAlI754SalMjjt95fZeMd3gEyAzsrvuOXnXN0bFZJi4": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
"substitute": {Mode: fs.ModeDir | 0700},
"work": {Mode: fs.ModeDir | 0700},
+37 -16
View File
@@ -30,10 +30,16 @@ import (
// AbsWork is the container pathname [TContext.GetWorkDir] is mounted on.
var AbsWork = fhs.AbsRoot.Append("work/")
// EnvJobs is the name of the environment variable holding a decimal
// representation of the preferred job count. Its value must not affect cure
// outcome.
const EnvJobs = "CURE_JOBS"
const (
// EnvJobs is the name of the environment variable holding a decimal
// representation of the preferred job count. Its value must not affect cure
// outcome.
EnvJobs = "CURE_JOBS"
// EnvLoad is the name of the environment variable holding a decimal
// representation of the preferred loadavg target. Its value must not affect
// cure outcome.
EnvLoad = "CURE_LOAD"
)
// ExecPath is a slice of [Artifact] and the [check.Absolute] pathname to make
// it available at under in the container.
@@ -407,9 +413,9 @@ func init() {
func(r *IRReader) Artifact { return readExecArtifact(r, true) })
}
// Dependencies returns a slice of all artifacts collected from caller-supplied
// Inputs returns a slice of all artifacts collected from caller-supplied
// [ExecPath].
func (a *execArtifact) Dependencies() []Artifact {
func (a *execArtifact) Inputs() []Artifact {
artifacts := make([][]Artifact, 0, len(a.paths))
for _, p := range a.paths {
artifacts = append(artifacts, p.A)
@@ -438,7 +444,7 @@ func scanVerbose(
msg message.Msg,
cancel context.CancelFunc,
done chan<- struct{},
prefix string,
prefix, suffix string,
r io.Reader,
) {
defer close(done)
@@ -448,7 +454,7 @@ func scanVerbose(
bufio.MaxScanTokenSize<<12,
)
for s.Scan() {
msg.Verbose(prefix, s.Text())
msg.Verbose(prefix, s.Text()+suffix)
}
if err := s.Err(); err != nil && !errors.Is(err, os.ErrClosed) {
cancel()
@@ -471,7 +477,7 @@ const SeccompPresets = std.PresetStrict &
func (a *execArtifact) makeContainer(
ctx context.Context,
msg message.Msg,
flags, jobs int,
flags, jobs, load int,
hostNet bool,
temp, work *check.Absolute,
getArtifact GetArtifactFunc,
@@ -508,7 +514,10 @@ func (a *execArtifact) makeContainer(
z.Quiet = flags&CSuppressInit != 0
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
z.Dir, z.Path, z.Args = a.dir, a.path, a.args
z.Env = slices.Concat(a.env, []string{EnvJobs + "=" + strconv.Itoa(jobs)})
z.Env = slices.Concat(a.env, []string{
EnvJobs + "=" + strconv.Itoa(jobs),
EnvLoad + "=" + strconv.Itoa(load),
})
z.Grow(len(a.paths) + 4)
if a.arch != runtime.GOARCH {
@@ -617,7 +626,7 @@ func (c *Cache) EnterExec(
return ErrNotExec
}
deps := Collect(a.Dependencies())
deps := Collect(a.Inputs())
if _, _, err = c.Cure(&deps); err == nil {
return errors.New("unreachable")
} else if !IsCollected(err) {
@@ -649,8 +658,9 @@ func (c *Cache) EnterExec(
var z *container.Container
z, err = e.makeContainer(
ctx, c.msg,
c.flags,
c.jobs,
c.attr.Flags,
c.attr.Jobs,
c.attr.Load,
hostNet,
temp, work,
func(a Artifact) (*check.Absolute, unique.Handle[Checksum]) {
@@ -693,7 +703,7 @@ func (a *execArtifact) cure(f *FContext, hostNet bool) (err error) {
msg := f.GetMessage()
var z *container.Container
if z, err = a.makeContainer(
ctx, msg, f.cache.flags, f.GetJobs(), hostNet,
ctx, msg, f.cache.attr.Flags, f.GetJobs(), f.GetLoad(), hostNet,
f.GetTempDir(), f.GetWorkDir(),
f.GetArtifact,
f.cache.Ident,
@@ -718,14 +728,25 @@ func (a *execArtifact) cure(f *FContext, hostNet bool) (err error) {
brStdout, brStderr := f.cache.getReader(stdout), f.cache.getReader(stderr)
stdoutDone, stderrDone := make(chan struct{}), make(chan struct{})
var suffix, prefixO, prefixE string
if f.cache.attr.Flags&CColourOutput != 0 {
suffix = "\x1b[0m"
prefixO = "\x1b[1;37m(" + a.name + ")\x1b[0m"
prefixE = "\x1b[1;97m(" + a.name + ")\x1b[0m"
} else {
prefixO = "(" + a.name + ":1)"
prefixE = "(" + a.name + ":2)"
}
go scanVerbose(
msg, cancel, stdoutDone,
"("+a.name+":1)",
prefixO, suffix,
io.TeeReader(brStdout, status),
)
go scanVerbose(
msg, cancel, stderrDone,
"("+a.name+":2)",
prefixE, suffix,
io.TeeReader(brStderr, status),
)
defer func() {
+21 -21
View File
@@ -84,7 +84,7 @@ func TestExec(t *testing.T) {
},
}),
pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantOffline, nil},
), ignorePathname, wantOffline, pkg.WNew, nil},
{"substitution", pkg.NewExec(
"exec-offline", "", new(wantOffline.hash()), 0, false, false,
@@ -108,7 +108,7 @@ func TestExec(t *testing.T) {
},
}),
pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantOffline, nil},
), ignorePathname, wantOffline, pkg.WSubstitute, nil},
{"error passthrough", pkg.NewExec(
"", "", nil, 0, false, true,
@@ -118,7 +118,7 @@ func TestExec(t *testing.T) {
[]string{"testtool"},
pkg.MustPath("/proc/nonexistent", false, failingArtifact),
), nil, nil, &pkg.DependencyCureError{
), nil, nil, pkg.WNew, &pkg.DependencyCureError{
{
A: failingArtifact,
Err: stub.UniqueError(0xcafe),
@@ -133,7 +133,7 @@ func TestExec(t *testing.T) {
[]string{"testtool"},
pkg.ExecPath{},
), nil, nil, pkg.ErrInvalidPaths},
), nil, nil, pkg.WNew, pkg.ErrInvalidPaths},
})
// check init failure passthrough
@@ -183,11 +183,11 @@ func TestExec(t *testing.T) {
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/QwS7SmiatdqryQYgESdGw7Yw2PcpNf0vNfpvUA0t92BTlKiUjfCrXyMW17G2X77X": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/MEaM1v6MLRQ60JQOOKbfDzfJOdC3L8i30IgOpYbQdX68enwF0FN-P36_M4RX_0Vd": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
"identifier/" + expected.Offline: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
"identifier/" + expected.OfflineS: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/_OHzj_xdmfpaWfFN-_D9JpGpPlIjh84873E3Ui9xwv9PPPIt0BlzvH-cnPNeRsTl": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"substitute": {Mode: fs.ModeDir | 0700},
@@ -225,7 +225,7 @@ func TestExec(t *testing.T) {
},
}),
pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantNet, nil},
), ignorePathname, wantNet, pkg.WNew, nil},
})
destroyStatus(t, base, 2, 0)
@@ -242,7 +242,7 @@ func TestExec(t *testing.T) {
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/" + expected.Net: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/MEaM1v6MLRQ60JQOOKbfDzfJOdC3L8i30IgOpYbQdX68enwF0FN-P36_M4RX_0Vd": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"substitute": {Mode: fs.ModeDir | 0700},
@@ -269,7 +269,7 @@ func TestExec(t *testing.T) {
},
}),
pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantOffline, nil},
), ignorePathname, wantOffline, pkg.WNew, nil},
})
destroyStatus(t, base, 2, 0)
@@ -284,7 +284,7 @@ func TestExec(t *testing.T) {
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/" + expected.OvlRoot: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/MEaM1v6MLRQ60JQOOKbfDzfJOdC3L8i30IgOpYbQdX68enwF0FN-P36_M4RX_0Vd": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"substitute": {Mode: fs.ModeDir | 0700},
@@ -316,7 +316,7 @@ func TestExec(t *testing.T) {
return os.MkdirAll(t.GetWorkDir().String(), 0700)
},
}), pkg.Path(pkg.AbsWork, false /* ignored */, testtool),
), ignorePathname, wantOffline, nil},
), ignorePathname, wantOffline, pkg.WNew, nil},
})
destroyStatus(t, base, 2, 0)
@@ -331,7 +331,7 @@ func TestExec(t *testing.T) {
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/" + expected.Work: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/MEaM1v6MLRQ60JQOOKbfDzfJOdC3L8i30IgOpYbQdX68enwF0FN-P36_M4RX_0Vd": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"substitute": {Mode: fs.ModeDir | 0700},
@@ -385,7 +385,7 @@ func TestExec(t *testing.T) {
},
}),
pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantOffline, nil},
), ignorePathname, wantOffline, pkg.WNew, nil},
})
destroyStatus(t, base, 2, 0)
@@ -403,9 +403,9 @@ func TestExec(t *testing.T) {
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
"identifier/B-kc5iJMx8GtlCua4dz6BiJHnDAOUfPjgpbKq4e-QEn0_CZkSYs3fOA1ve06qMs2": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK")},
"identifier/2uIvmnqtzAx4Ed4PWV8xjZCWeJCwfE2IcCc0evM-Nd8mDUlgSU6nLtPLcpPUcMlG": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK")},
"identifier/" + expected.Layers: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/MEaM1v6MLRQ60JQOOKbfDzfJOdC3L8i30IgOpYbQdX68enwF0FN-P36_M4RX_0Vd": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"substitute": {Mode: fs.ModeDir | 0700},
@@ -438,7 +438,7 @@ func TestExec(t *testing.T) {
},
}),
pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantOffline, nil},
), ignorePathname, wantOffline, pkg.WNew, nil},
})
destroyStatus(t, base, 2, 0)
@@ -452,8 +452,8 @@ func TestExec(t *testing.T) {
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/kvJIqZo5DKFOxC2ZQ-8_nPaQzEAz9cIm3p6guO-uLqm-xaiPu7oRkSnsu411jd_U": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/Vzj9qaSVBtNyBQv_PW6uojFOWTwraHoaC0C6xdaGG1q_HTvSh4KLVxRcEQU1jd2Y": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/MEaM1v6MLRQ60JQOOKbfDzfJOdC3L8i30IgOpYbQdX68enwF0FN-P36_M4RX_0Vd": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/" + expected.Promote: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
"substitute": {Mode: fs.ModeDir | 0700},
@@ -503,7 +503,7 @@ func TestExec(t *testing.T) {
".": {Mode: fs.ModeDir | 0500},
"check": {Mode: 0400, Data: []byte("binfmt")},
}, nil},
}, pkg.WNew, nil},
})
destroyStatus(t, base, 2, 0)
@@ -519,9 +519,9 @@ func TestExec(t *testing.T) {
"checksum/UnDo4B5KneEUY5b4vRUk_y9MWgkWuw2N8f8a2XayO686xXur-aZmX2-7n_8tKMe3/check": {Mode: 0400, Data: []byte("binfmt")},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/6VQTJ1lI5BmVuI1YFYJ8ClO3MRORvTTrcWFDcUU-l5Ga8EofxCxGlSTYN-u8dKj_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UnDo4B5KneEUY5b4vRUk_y9MWgkWuw2N8f8a2XayO686xXur-aZmX2-7n_8tKMe3")},
"identifier/c-HodmoEG0f_WGdst9aN-duLMH7QDDXOUi7UcyArXMeM1fc9lYKKQlTCW8ktaK8X": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UnDo4B5KneEUY5b4vRUk_y9MWgkWuw2N8f8a2XayO686xXur-aZmX2-7n_8tKMe3")},
"identifier/_v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/5aevg3YpDxjqQZ-pdvXK7YqgkL5JKqcoStYQxeD96kuYar6K2mRQWMHib6NQRnpV")},
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/MEaM1v6MLRQ60JQOOKbfDzfJOdC3L8i30IgOpYbQdX68enwF0FN-P36_M4RX_0Vd": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"substitute": {Mode: fs.ModeDir | 0700},
+21 -2
View File
@@ -11,6 +11,8 @@ import (
type fileArtifact []byte
var _ KnownChecksum = new(fileArtifact)
var _ CuresExempt = new(fileArtifact)
var _ RevisionArtifact = new(fileArtifact)
// fileArtifactNamed embeds fileArtifact alongside a caller-supplied name.
type fileArtifactNamed struct {
@@ -62,8 +64,8 @@ func init() {
})
}
// Dependencies returns a nil slice.
func (*fileArtifact) Dependencies() []Artifact { return nil }
// Inputs returns a nil slice.
func (*fileArtifact) Inputs() []Artifact { return nil }
// IsExclusive returns false: Cure returns a prepopulated buffer.
func (*fileArtifact) IsExclusive() bool { return false }
@@ -75,7 +77,24 @@ func (a *fileArtifact) Checksum() Checksum {
return Checksum(h.Sum(nil))
}
// Revision satisfies [RevisionArtifact] for incompatible IsExecutable behaviour.
func (*fileArtifact) Revision() uint64 { return 0 }
// IsExecutable returns whether the contents begin with shebang or the ELF
// magic number.
func (a *fileArtifact) IsExecutable() bool {
return a != nil &&
(bytes.HasPrefix(
*a, []byte{'#', '!'},
) || bytes.HasPrefix(
*a, []byte{0x7f, 'E', 'L', 'F'},
))
}
// Cure returns the caller-supplied data.
func (a *fileArtifact) Cure(*RContext) (io.ReadCloser, error) {
return io.NopCloser(bytes.NewReader(*a)), nil
}
// CuresExempt exempts the cheap [KindFile] implementation.
func (*fileArtifact) CuresExempt() {}
+26 -7
View File
@@ -12,22 +12,41 @@ func TestFile(t *testing.T) {
t.Parallel()
want := expectsFile{0}
const ident = "N7M6W8-e55Wky_1q1a6qRKFVDw1S5XtPdB4HE2YZObG8OFum8HittyJgZUG5Ru2u"
wantShebang := expectsFile("#!/bin/sh\n")
const identShebang = "oKTGZb_TRtJf5G1iGGj4SOx1WUbI6YhmsUeEsCNvmK9tZYRwdwQf-DLFUxRPx5qm"
wantELF := expectsFile("\x7fELF\xde\xad\xbe\xef")
const identELF = "LjeHmIJgD1SiXIH8ewpGRed2_LU84NLapstnOAa_0hxLd8YY7x4KM0aApsj-RwCh"
checkWithCache(t, []cacheTestCase{
{"file", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
cureMany(t, c, []cureStep{
{"short", pkg.NewFile("null", []byte{0}), base.Append(
{"short", pkg.NewFile("null", want), base.Append(
"identifier",
"3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi",
), want, nil},
ident,
), want, pkg.WNew, nil},
{"shebang", pkg.NewFile("shebang", wantShebang), base.Append(
"identifier",
identShebang,
), wantShebang, pkg.WNew, nil},
{"elf", pkg.NewFile("ELF", wantELF), base.Append(
"identifier",
identELF,
), wantELF, pkg.WNew, nil},
})
}, expectsFS{
".": {Mode: fs.ModeDir | 0700},
"checksum": {Mode: fs.ModeDir | 0700},
"checksum/" + pkg.Encode(want.hash()): {Mode: 0400, Data: []byte{0}},
"checksum": {Mode: fs.ModeDir | 0700},
"checksum/" + pkg.Encode(want.hash()): {Mode: 0400, Data: want},
"checksum/" + pkg.Encode(wantShebang.hash()): {Mode: 0500, Data: wantShebang},
"checksum/" + pkg.Encode(wantELF.hash()): {Mode: 0500, Data: wantELF},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/" + ident: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + pkg.Encode(want.hash()))},
"identifier/" + identShebang: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + pkg.Encode(wantShebang.hash()))},
"identifier/" + identELF: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + pkg.Encode(wantELF.hash()))},
"substitute": {Mode: fs.ModeDir | 0700},
@@ -1,11 +1,11 @@
package expected
const (
Offline = "q5ktDTq0miP-VvB2blxqXQeaRXCUWgP_KbC18KNtUDtyoaI_h5mHmGuPMArVEBDs"
OfflineS = "IY91PCtOpCYy21AaIK0c9f8-Z6fb2_2ewoHWkt4dxoLf0GOrWqS8yAGFLV84b1Dw"
OvlRoot = "NacZGXwuRkTvcHaG08a22ujJ8qCWN0RSoFlRSR5FSt0ZcBbJ28FRvkYsHEtX7G8i"
Layers = "WBJDrATtX6rIE5yAu8ePX3WmDF0Tt9kFiue0m3cRnyRoVx1my8a67fh3CAW486oP"
Net = "CmYtj2sNB3LHtqiDuck_Lz3MjLLIiwyP8N4NDitQ1Icvv__LVP9p8tm-sHeQaKKp"
Promote = "TX3eCloaQFkV-SZIH6Jg6E5WKH--rcXY1P0jnZKmLFKWrNqnOzd4G9eIBh6i5ywN"
Work = "OuNiLSC68pZhAOr1YQ4WbV1tzASA0nxLEBcK7lO7MqxDY_j8dmP_C612RTuF23Lu"
Offline = "IKmVhALejtYA3JhN1PCfjKF-Dio1XVcOeMWDHhfSHCbb4iBNhGjFy2UspZveZvb8"
OfflineS = "6ZubjSyCnz4-TKgQZi_BbY-JUwsStYCtD_f-BTDOOotfEbqkm47W20AazHRaLviz"
OvlRoot = "Yox7WpG8B_OqIXWF4HWFZkUfsEl7DGzpFyZM0qtd9T8nQ-7SAkEUurlAe6_DJ6Iu"
Layers = "aAwfxDB-efVo379FNl178jK7HEKU3LEjHbZdaVVjk7GnXGZGEANNsXnB3SCUxM9A"
Net = "IU3GwU2jTBd7HjotvFo2wsDWBQGVGpamwiSKdc2G1EnhM-ZaacxAuK6q0wbTVxra"
Promote = "rOjetGHzT_jPErrBR24IAZKDj8Q9dLLqxFQqloMgjsULss0VXDI--n6LxuMBHvmZ"
Work = "7f9XDeREfvJIjCe0qesND0s0tasExAIcc-OH33-eq9tsrQPUXhJp4KEkpsYH4hCD"
)
@@ -1,11 +1,11 @@
package expected
const (
Offline = "WapqyoPxbWSnq07dWHt71mHaJXq99pAjJfFlELlJljSiZMhTFqqlzU1_mN86shSj"
OfflineS = "ibQZHcdXgNQ1OiMX1FrburBbGPVvKEHvPilbQCkm_0oV0BQCHomyyTbYNrFMGIwl"
OvlRoot = "V9anFOiRvjGfAeBhLl14AL8TKdWZyD0WTPYe4fS9mOBw8iW5Lmarvt6TG6MV8uWm"
Layers = "tKx7JNRoSBdK_7MdzI-nwTNV2wmiPzwYdcd17oLmXKL_iLmUzUiA79qTqdrTasrv"
Net = "aXyDLzBCJ9XltXZIfetEVsEkrqHfcXuD5XE_FcUnYbN3emwL55N6P8LlHzNfGnM5"
Promote = "3k4V16n96Lq04gjFSKmm4sFjyQ883FFBNXgTy9s_DjeTwxT3pg_iacEh8yMb_S4m"
Work = "6Q49MhFWRE3Ne6MycwAotgl1GtoU5WCHqJNWG2byYZCY-zX-IxPrWiKk7bKkNzhE"
Offline = "MTgCSzwPrzGigp9phvDPRwUTNGLm1KM2EsEtbz-l2cNieqjaGtnzm65CDXlSxXrl"
OfflineS = "p89bQg7_jR4nwaSbpEd08ne1jHOEw7Wlnlyv5FHq7ba1Kml3HSBZwEKRzu0gCqEb"
OvlRoot = "9ifwO6MAaV9kTqRR2O5PJzm8XhfXbr50mFLWyEHQm8OHHcJtAEUgXZzJYoZt9YVV"
Layers = "INuGActFPwJtS7mAR9Bkt7FD4yoHlXHSJ9CaSAQJrpkUBL_k815Cs_jvRfxy5-a7"
Net = "kJvy24uk4ePvHoxSKf4vMOhR4NxLbmyWlA9bTS7d3z3fE9WF1Tvpao9g-QuYU4vm"
Promote = "lYqyYrfjPawIbld5Qz0NbKvd_bmI3nJC1eEnlIQWzsjWE9uA1HuKPAaClnDeyG6L"
Work = "V6k4FqOBMRCmHiqchs5-joVGZ_MhNWZyXm3gdbU0S7S5eMze7G4SwYMTf66ojKQL"
)
@@ -1,11 +1,11 @@
package expected
const (
Offline = "Z6yXE5gOJScL3srmnVMWgCXccDiUNZ5snSrf6RkXuU1_U0rX_kGVwsfHUgNG_awd"
OfflineS = "zN16xv6LKRJRipUJwupyxg2rZcvf-qpsMn_qCxUmgxlTSuNwYI70ZEb7dHW5k0gO"
OvlRoot = "zYXJHFRLuxvUhuisZEXgGgVvdQd6piMfp5jmtT6jdVjvC2gICXquOq-UTwlrSD5I"
Layers = "_F8EDazHbcLeT0sVSQXRN_kn9IjduqJcDYgzXpsT-hpKU4EBcZ0PISN2zchpqMbm"
Net = "CA_FAaSIYJgapBEHV40doxpH23PdUEy_6s1TZc7wfSPN0XYqwGpMceXXDSabGveO"
Promote = "_3LPrLp--4h9k4GsNNApu9hHtAafq-GUhfU6d4hJKBDKT3bz_szOsvkXxc5sK53d"
Work = "FEgHeiCD_WT4wsfB-9kDH5n6cRWCEYtJmXdKZgmUUukAOoXumH_hLlosXREC-tqq"
Offline = "LlieSHVDe1lnKvfI8t4oGRg_2hPxwyy1drmaqc-EKCOENuS9C2YHrp2VY5pSyhbg"
OfflineS = "qccjM8oYjUuEYPKFFzAxDFVzMerSUKUZc18NdVQoiPWf-70XOsNK8NaUQqjTgTAD"
OvlRoot = "lpV2bb_KGYFHPiOn-jtGop8K_ew0y1p3BezRp0ebM93_a-T9J-vkqGD5uokda1aN"
Layers = "sM3DJm210CHPGHkAquIbrXhspB81FpVC60ApQrvJGD5El2i7cSONj7LWf7EWqKpT"
Net = "JihQUwsVETRYjb2-yIXLYZ6WVsaFebwl8btSYAsNQ2QapS5MZVaI-dYwrVoySycR"
Promote = "lGqwR4W2OjylSVitMQP1lc6wApOBkbMjsmIqkxQbfEZ3DHEQBbJr84ErW6Xb54zo"
Work = "aZgtyv6aMtoHFkHAaJr6nLaA7N_SHjShgWPyQ5UdzaIqYSiVqvCrZqSokGTCcTii"
)
+9 -1
View File
@@ -38,7 +38,15 @@ func main() {
}
environ := slices.DeleteFunc(slices.Clone(os.Environ()), func(s string) bool {
return s == "CURE_JOBS="+strconv.Itoa(runtime.NumCPU())
for _, t := range []string{
"CURE_JOBS=" + strconv.Itoa(runtime.NumCPU()),
"CURE_LOAD=" + strconv.Itoa(runtime.NumCPU()+2),
} {
if s == t {
return true
}
}
return false
})
var hostNet, layers, promote bool
+44 -26
View File
@@ -90,7 +90,7 @@ type IContext struct {
// returns and must not be exposed directly.
w io.Writer
// Optional [Artifact] to cureRes cache, replaces [IRKindIdent] with
// checksum values if non-nil.
// checksum values if non-nil. The pathname field may not be populated.
inputs map[Artifact]cureRes
}
@@ -173,7 +173,7 @@ func (i *IContext) mustWrite(p []byte) {
// WriteIdent writes the identifier of [Artifact] to the IR. The behaviour of
// WriteIdent is not defined for an [Artifact] not part of the slice returned by
// [Artifact.Dependencies].
// [Artifact.Inputs].
func (i *IContext) WriteIdent(a Artifact) {
buf := i.ic.getIdentBuf()
defer i.ic.putIdentBuf(buf)
@@ -235,13 +235,14 @@ func (ic *irCache) Encode(w io.Writer, a Artifact) (err error) {
}
// encode implements Encode but replaces identifiers with their cured checksums
// for a non-nil ident. Caller must acquire Cache.identMu.
// for a non-nil ident. The pathname field is unused. Caller must acquire
// Cache.identMu.
func (ic *irCache) encode(
w io.Writer,
a Artifact,
inputs map[Artifact]cureRes,
) (err error) {
deps := a.Dependencies()
deps := a.Inputs()
idents := make([]*extIdent, len(deps))
if inputs == nil {
for i, d := range deps {
@@ -277,10 +278,11 @@ func (ic *irCache) encode(
return *a == *b
})
// kind uint64 | deps_sz uint64
var buf [wordSize * 2]byte
// kind uint64 | rev uint64 | deps_sz uint64
var buf [wordSize * 3]byte
binary.LittleEndian.PutUint64(buf[:], uint64(a.Kind()))
binary.LittleEndian.PutUint64(buf[wordSize:], uint64(len(idents)))
binary.LittleEndian.PutUint64(buf[wordSize:], GetRevision(a))
binary.LittleEndian.PutUint64(buf[wordSize*2:], uint64(len(idents)))
if _, err = w.Write(buf[:]); err != nil {
return
}
@@ -330,7 +332,7 @@ func (ic *irCache) encodeAll(
return
}
for _, d := range a.Dependencies() {
for _, d := range a.Inputs() {
if err = ic.encodeAll(w, d, encoded); err != nil {
return
}
@@ -432,9 +434,9 @@ type (
// Common buffer for word-sized reads.
buf [wordSize]byte
// Dependencies sent before params, sorted by identifier. Resliced on
// Inputs sent before params, sorted by identifier. Resliced on
// each call to Next and checked to be depleted during Finalise.
deps []*extIdent
inputs []*extIdent
// Number of values already read, -1 denotes a finalised IRReader.
count int
@@ -518,7 +520,7 @@ const (
irMaxValues = 1 << 12
// irMaxDeps is the arbitrary maximum number of direct dependencies allowed
// to be returned by [Artifact.Dependencies] and subsequently decoded by
// to be returned by [Artifact.Inputs] and subsequently decoded by
// [IRDecoder].
irMaxDeps = 1 << 10
)
@@ -603,17 +605,17 @@ func (ir *IRReader) mustReadHeader(k IRValueKind) {
// putAll returns all dependency buffers to the underlying [Cache].
func (ir *IRReader) putAll() {
for _, buf := range ir.deps {
for _, buf := range ir.inputs {
ir.d.c.putIdentBuf(buf)
}
ir.deps = nil
ir.inputs = nil
}
// DiscardAll discards all unstructured dependencies. This is useful to
// implementations that encode dependencies as [IRKindIdent] which are read back
// via ReadIdent.
func (ir *IRReader) DiscardAll() {
if ir.deps == nil {
if ir.inputs == nil {
panic("attempting to discard dependencies twice")
}
ir.putAll()
@@ -625,13 +627,13 @@ var ErrDependencyDepleted = errors.New("reading past end of dependencies")
// Next returns the next unstructured dependency.
func (ir *IRReader) Next() Artifact {
if len(ir.deps) == 0 {
if len(ir.inputs) == 0 {
panic(ErrDependencyDepleted)
}
id := unique.Make(ID(ir.deps[0][wordSize:]))
ir.d.c.putIdentBuf(ir.deps[0])
ir.deps = ir.deps[1:]
id := unique.Make(ID(ir.inputs[0][wordSize:]))
ir.d.c.putIdentBuf(ir.inputs[0])
ir.inputs = ir.inputs[1:]
if a, ok := ir.d.ident[id]; !ok {
ir.putAll()
@@ -684,8 +686,8 @@ func (ir *IRReader) Finalise() (checksum unique.Handle[Checksum], ok bool) {
}
ir.r, ir.ibw = nil, nil
if len(ir.deps) != 0 {
panic(MissedDependencyError(len(ir.deps)))
if len(ir.inputs) != 0 {
panic(MissedDependencyError(len(ir.inputs)))
}
return
@@ -739,6 +741,15 @@ func (ir *IRReader) ReadString() string {
return unsafe.String(unsafe.SliceData(p), len(p))
}
// A RevisionError describes the first [Artifact] in an IR stream claiming a
// revision not supported by the registered implementation.
type RevisionError [2]uint64
func (e RevisionError) Error() string {
return "claimed revision " + strconv.FormatUint(e[0], 10) +
" differs from implementation value " + strconv.FormatUint(e[1], 10)
}
// decode decodes the next [Artifact] in the IR stream and returns any buffer
// originating from [Cache] before returning. decode returns [io.EOF] if and
// only if the underlying [io.Reader] is already read to EOF.
@@ -771,6 +782,9 @@ func (d *IRDecoder) decode() (a Artifact, err error) {
return
}
ir.mustRead(ir.buf[:])
rev := binary.LittleEndian.Uint64(ir.buf[:])
defer ir.putAll()
ir.mustRead(ir.buf[:])
sz := binary.LittleEndian.Uint64(ir.buf[:])
@@ -778,11 +792,11 @@ func (d *IRDecoder) decode() (a Artifact, err error) {
err = ErrIRDepend
return
}
ir.deps = make([]*extIdent, sz)
for i := range ir.deps {
ir.deps[i] = d.c.getIdentBuf()
ir.inputs = make([]*extIdent, sz)
for i := range ir.inputs {
ir.inputs[i] = d.c.getIdentBuf()
}
for _, buf := range ir.deps {
for _, buf := range ir.inputs {
ir.mustRead(buf[:])
}
@@ -791,6 +805,10 @@ func (d *IRDecoder) decode() (a Artifact, err error) {
err = syscall.ENOTRECOVERABLE
return
}
if _rev := GetRevision(a); _rev != rev {
err = RevisionError{rev, _rev}
return
}
if ir.count != -1 {
err = ErrRemainingIR
@@ -805,8 +823,8 @@ func (d *IRDecoder) decode() (a Artifact, err error) {
d.ident[id] = a
} else {
d.c.msg.Verbosef(
"artifact %s appeared more than once in IR stream",
Encode(id.Value()),
"artifact %s%s%s appeared more than once in IR stream",
d.c.sgrIdent, Encode(id.Value()), d.c.sgrRes,
)
}
+33
View File
@@ -135,3 +135,36 @@ func TestIRRoundtrip(t *testing.T) {
}
checkWithCache(t, testCasesCache)
}
func TestRevision(t *testing.T) {
checkWithCache(t, []cacheTestCase{{"revision", 0, nil,
func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
a := pkg.NewFile("", nil)
var buf bytes.Buffer
if err := c.EncodeAll(&buf, a); err != nil {
t.Fatal(err)
}
if _, err := c.NewDecoder(
bytes.NewReader(buf.Bytes()),
).Decode(); err != nil {
t.Fatalf("Decode: error = %v", err)
}
p := buf.Bytes()
p[8] = 0xfd
wantErr := pkg.RevisionError{0xfd, 0}
if _, err := c.NewDecoder(
bytes.NewReader(p),
).Decode(); !reflect.DeepEqual(err, wantErr) {
t.Fatalf("Decode: error = %v, want %v", err, wantErr)
}
}, expectsFS{
".": {Mode: fs.ModeDir | 0700},
"checksum": {Mode: fs.ModeDir | 0700},
"identifier": {Mode: fs.ModeDir | 0700},
"substitute": {Mode: fs.ModeDir | 0700},
"work": {Mode: fs.ModeDir | 0700},
},
}})
}
+5 -2
View File
@@ -54,8 +54,8 @@ func init() {
})
}
// Dependencies returns a nil slice.
func (*httpArtifact) Dependencies() []Artifact { return nil }
// Inputs returns a nil slice.
func (*httpArtifact) Inputs() []Artifact { return nil }
// IsExclusive returns false: Cure returns as soon as a response is received.
func (*httpArtifact) IsExclusive() bool { return false }
@@ -74,6 +74,9 @@ func (e ResponseStatusError) Error() string {
return "the requested URL returned non-OK status: " + http.StatusText(int(e))
}
// IsExecutable returns false.
func (*httpArtifact) IsExecutable() bool { return false }
// Cure sends the http request and returns the resulting response body reader
// wrapped to perform checksum validation. It is valid but not encouraged to
// close the resulting [io.ReadCloser] before it is read to EOF, as that causes
+2 -2
View File
@@ -104,7 +104,7 @@ func TestHTTPGet(t *testing.T) {
)
wantPathname := base.Append(
"identifier",
"oM-2pUlk-mOxK1t3aMWZer69UdOQlAXiAgMrpZ1476VoOqpYVP1aGFS9_HYy-D8_",
"COBRUwkxpIvZWJggpRxn7HVXiw6epXZOex8jGRJKpowpwukV7GRBY_LBvOJNQHue",
)
if pathname, checksum, err := c.Cure(f); err != nil {
t.Fatalf("Cure: error = %v", err)
@@ -158,7 +158,7 @@ func TestHTTPGet(t *testing.T) {
"checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU": {Mode: 0400, Data: []byte("\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69")},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/oM-2pUlk-mOxK1t3aMWZer69UdOQlAXiAgMrpZ1476VoOqpYVP1aGFS9_HYy-D8_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")},
"identifier/COBRUwkxpIvZWJggpRxn7HVXiw6epXZOex8jGRJKpowpwukV7GRBY_LBvOJNQHue": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")},
"substitute": {Mode: fs.ModeDir | 0700},
+484 -165
View File
File diff suppressed because it is too large Load Diff
+257 -108
View File
@@ -35,14 +35,14 @@ import (
"hakurei.app/message"
)
//go:linkname unsafeOpen hakurei.app/internal/pkg.open
func unsafeOpen(
ctx context.Context,
msg message.Msg,
flags, cures, jobs int,
base *check.Absolute,
lock bool,
) (*pkg.Cache, error)
var skipLock = func() pkg.CacheAttr {
var attr pkg.CacheAttr
*(*bool)(unsafe.Pointer(reflect.ValueOf(&attr).
Elem().
FieldByName("skipLock").
UnsafeAddr())) = true
return attr
}()
var (
// extension is a string uniquely identifying a set of custom [Artifact]
@@ -140,11 +140,11 @@ type stubArtifact struct {
cure func(t *pkg.TContext) error
}
func (a *stubArtifact) Kind() pkg.Kind { return a.kind }
func (a *stubArtifact) Params(ctx *pkg.IContext) { ctx.Write(a.params) }
func (a *stubArtifact) Dependencies() []pkg.Artifact { return a.deps }
func (a *stubArtifact) Cure(t *pkg.TContext) error { return a.cure(t) }
func (*stubArtifact) IsExclusive() bool { return false }
func (a *stubArtifact) Kind() pkg.Kind { return a.kind }
func (a *stubArtifact) Params(ctx *pkg.IContext) { ctx.Write(a.params) }
func (a *stubArtifact) Inputs() []pkg.Artifact { return a.deps }
func (a *stubArtifact) Cure(t *pkg.TContext) error { return a.cure(t) }
func (*stubArtifact) IsExclusive() bool { return false }
// A stubArtifactF implements [FloodArtifact] with hardcoded behaviour.
type stubArtifactF struct {
@@ -156,11 +156,11 @@ type stubArtifactF struct {
cure func(f *pkg.FContext) error
}
func (a *stubArtifactF) Kind() pkg.Kind { return a.kind }
func (a *stubArtifactF) Params(ctx *pkg.IContext) { ctx.Write(a.params) }
func (a *stubArtifactF) Dependencies() []pkg.Artifact { return a.deps }
func (a *stubArtifactF) Cure(f *pkg.FContext) error { return a.cure(f) }
func (a *stubArtifactF) IsExclusive() bool { return a.excl }
func (a *stubArtifactF) Kind() pkg.Kind { return a.kind }
func (a *stubArtifactF) Params(ctx *pkg.IContext) { ctx.Write(a.params) }
func (a *stubArtifactF) Inputs() []pkg.Artifact { return a.deps }
func (a *stubArtifactF) Cure(f *pkg.FContext) error { return a.cure(f) }
func (a *stubArtifactF) IsExclusive() bool { return a.excl }
// A stubFile implements [FileArtifact] with hardcoded behaviour.
type stubFile struct {
@@ -170,6 +170,8 @@ type stubFile struct {
stubArtifact
}
func (*stubFile) IsExecutable() bool { return false }
func (a *stubFile) Cure(*pkg.RContext) (io.ReadCloser, error) {
return io.NopCloser(bytes.NewReader(a.data)), a.err
}
@@ -330,7 +332,7 @@ func TestIdent(t *testing.T) {
},
nil,
}, unique.Make[pkg.ID](pkg.MustDecode(
"97Y85QewssfPbNIN9cyNhzD4e6dLHcDTU8rb2c34k-aCrZfBNXFUc0duPiLFFcw_",
"fkmge-H56Ph2LzNNbEUjTypes8LfOxrF_CEXg07kq6ho_nbTNvzQde9-bjB7gyB_",
))},
}
@@ -339,7 +341,7 @@ func TestIdent(t *testing.T) {
var cache *pkg.Cache
if a, err := check.NewAbs(t.TempDir()); err != nil {
t.Fatal(err)
} else if cache, err = pkg.Open(t.Context(), msg, 0, 0, 0, a); err != nil {
} else if cache, err = pkg.Open(t.Context(), msg, a, nil); err != nil {
t.Fatal(err)
}
t.Cleanup(cache.Close)
@@ -519,7 +521,10 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) {
}
var scrubFunc func() error // scrub after hashing
if c, err := pkg.Open(t.Context(), msg, flags, 1<<4, 0, base); err != nil {
if c, err := pkg.Open(t.Context(), msg, base, &pkg.CacheAttr{
Cures: 1 << 4,
Flags: flags,
}); err != nil {
t.Fatalf("Open: error = %v", err)
} else {
t.Cleanup(c.Close)
@@ -627,6 +632,7 @@ type cureStep struct {
pathname *check.Absolute
output expectsKnown
whence int
err error
}
@@ -646,7 +652,7 @@ func cureMany(t *testing.T, c *pkg.Cache, steps []cureStep) {
for _, step := range steps {
t.Log("cure step:", step.name)
if pathname, checksum, err := c.Cure(step.a); !reflect.DeepEqual(err, step.err) {
if pathname, checksum, whence, err := c.CureWhence(step.a); !reflect.DeepEqual(err, step.err) {
faults, _err := c.ReadFaults(step.a)
if _err != nil {
t.Errorf("ReadFaults: error = %v", _err)
@@ -663,6 +669,8 @@ func cureMany(t *testing.T, c *pkg.Cache, steps []cureStep) {
t.Logf("faulting cure terminated %s ago", time.Since(faults[0].Time()))
}
t.Fatalf("Cure: error = %v, want %v", err, step.err)
} else if step.whence != whence {
t.Fatalf("Cure: whence = %s, want %s", pkg.WhenceString(whence), pkg.WhenceString(step.whence))
} else if step.pathname != ignorePathname && !pathname.Is(step.pathname) {
t.Fatalf("Cure: pathname = %q, want %q", pathname, step.pathname)
} else if step.output == nil || checksum != makeChecksumH(step.output.hash()) {
@@ -774,28 +782,28 @@ func TestCache(t *testing.T) {
identifier,
new(testdata.hash()),
testdata, nil,
), wantPathname, testdata, nil},
), wantPathname, testdata, pkg.WNew, nil},
{"identical content", newStubFile(
pkg.KindHTTPGet,
identifier0,
new(testdata.hash()),
testdata, nil,
), wantPathname0, testdata, nil},
), wantPathname0, testdata, pkg.WCache, nil},
{"existing entry", newStubFile(
pkg.KindHTTPGet,
identifier,
new(testdata.hash()),
testdata, nil,
), wantPathname, testdata, nil},
), wantPathname, testdata, pkg.WCache, nil},
{"checksum mismatch", newStubFile(
pkg.KindHTTPGet,
pkg.ID{0xff, 0},
new(pkg.Checksum),
testdata, nil,
), nil, nil, &pkg.ChecksumMismatchError{
), nil, nil, pkg.WNew, &pkg.ChecksumMismatchError{
Got: testdata.hash(),
}},
@@ -816,13 +824,13 @@ func TestCache(t *testing.T) {
0x36, 0x65, 0x59, 0x33, 0xec, 0x2b,
0x41, 0x34, 0x65, 0x96, 0x68, 0x17,
0xa9, 0xc2, 0x08, 0xa1, 0x17, 0x17,
}, nil},
}, pkg.WNew, nil},
{"incomplete implementation", struct{ pkg.Artifact }{&stubArtifact{
kind: pkg.KindExec,
params: []byte("artifact overridden to be incomplete"),
}}, nil, nil, pkg.InvalidArtifactError(pkg.MustDecode(
"E__uZ1sLIvb84vzSm5Uezb03RogsiaeTt1nfIVv8TKnnf4LqwtSi-smdHhlkZrUJ",
}}, nil, nil, pkg.WNew, pkg.InvalidArtifactError(pkg.MustDecode(
"poVrv3zNINbHd-WUJihwgWQwJpbHURFHfpY7Zux-ztto_bQhhS5PdpbNMjdkXv-V",
))},
{"error passthrough", newStubFile(
@@ -830,18 +838,18 @@ func TestCache(t *testing.T) {
pkg.ID{0xff, 1},
nil,
nil, stub.UniqueError(0xcafe),
), nil, nil, stub.UniqueError(0xcafe)},
), nil, nil, pkg.WNew, stub.UniqueError(0xcafe)},
{"error caching", newStubFile(
pkg.KindHTTPGet,
pkg.ID{0xff, 1},
nil,
nil, nil,
), nil, nil, stub.UniqueError(0xcafe)},
), nil, nil, pkg.WCache, stub.UniqueError(0xcafe)},
{"cache hit bad type", overrideChecksum{testdata.hash(), overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{
kind: pkg.KindTar,
}}}, nil, nil, pkg.InvalidFileModeError(
}}}, nil, nil, pkg.WCache, pkg.InvalidFileModeError(
0400,
)},
@@ -853,7 +861,7 @@ func TestCache(t *testing.T) {
cure: func(f *pkg.FContext) error {
panic("attempting to cure impossible artifact")
},
}, nil, nil, &pkg.DependencyCureError{
}, nil, nil, pkg.WNew, &pkg.DependencyCureError{
{
A: failingFile,
Err: struct {
@@ -864,10 +872,10 @@ func TestCache(t *testing.T) {
}},
})
if c0, err := unsafeOpen(
if c0, err := pkg.Open(
t.Context(),
message.New(nil),
0, 0, 0, base, false,
base, &skipLock,
); err != nil {
t.Fatalf("open: error = %v", err)
} else {
@@ -875,7 +883,7 @@ func TestCache(t *testing.T) {
cureMany(t, c0, []cureStep{
{"cache hit ident", overrideIdent{
id: identifier,
}, wantPathname, testdata, nil},
}, wantPathname, testdata, pkg.WCache, nil},
{"cache miss checksum match", newStubFile(
pkg.KindHTTPGet,
@@ -886,7 +894,7 @@ func TestCache(t *testing.T) {
), base.Append(
"identifier",
pkg.Encode(testdata.hash()),
), testdata, nil},
), testdata, pkg.WNew, nil},
})
// cure after close
@@ -1016,30 +1024,30 @@ func TestCache(t *testing.T) {
{"initial directory", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{
kind: pkg.KindTar,
cure: makeSample,
}}}, wantPathname, want, nil},
}}}, wantPathname, want, pkg.WNew, nil},
{"identical identifier", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{
kind: pkg.KindTar,
}}}, wantPathname, want, nil},
}}}, wantPathname, want, pkg.WCache, nil},
{"identical checksum", overrideIdent{id0, &stubArtifact{
kind: pkg.KindTar,
cure: makeSample,
}}, wantPathname0, want, nil},
}}, wantPathname0, want, pkg.WNew, nil},
{"cure fault", overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{
kind: pkg.KindTar,
cure: func(t *pkg.TContext) error {
return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xcafe))
},
}}, nil, nil, stub.UniqueError(0xcafe)},
}}, nil, nil, pkg.WNew, stub.UniqueError(0xcafe)},
{"checksum mismatch", overrideChecksum{pkg.Checksum{}, overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{
kind: pkg.KindTar,
cure: func(t *pkg.TContext) error {
return makeGarbage(t.GetWorkDir(), nil)
},
}}}, nil, nil, &pkg.ChecksumMismatchError{
}}}, nil, nil, pkg.WNew, &pkg.ChecksumMismatchError{
Got: pkg.MustDecode(
"CUx-3hSbTWPsbMfDhgalG4Ni_GmR9TnVX8F99tY_P5GtkYvczg9RrF5zO0jX9XYT",
),
@@ -1050,7 +1058,7 @@ func TestCache(t *testing.T) {
pkg.ID{0xff, 2},
new(want.hash()),
testdata, nil,
), nil, nil, pkg.InvalidFileModeError(
), nil, nil, pkg.WCache, pkg.InvalidFileModeError(
fs.ModeDir | 0500,
)},
@@ -1064,7 +1072,7 @@ func TestCache(t *testing.T) {
_, err = io.ReadAll(r)
return err
},
}}, nil, nil, &os.PathError{
}}, nil, nil, pkg.WNew, &os.PathError{
Op: "read",
Path: base.Append(
"checksum",
@@ -1078,14 +1086,14 @@ func TestCache(t *testing.T) {
cure: func(t *pkg.TContext) error {
return nil
},
}}, nil, nil, pkg.NoOutputError{}},
}}, nil, nil, pkg.WNew, pkg.NoOutputError{}},
{"file output", overrideIdent{pkg.ID{0xff, 5}, &stubArtifact{
kind: pkg.KindTar,
cure: func(t *pkg.TContext) error {
return os.WriteFile(t.GetWorkDir().String(), []byte{0}, 0400)
},
}}, nil, nil, errors.New("non-file artifact produced regular file")},
}}, nil, nil, pkg.WNew, errors.New("non-file artifact produced regular file")},
{"symlink output", overrideIdent{pkg.ID{0xff, 6}, &stubArtifact{
kind: pkg.KindTar,
@@ -1095,7 +1103,7 @@ func TestCache(t *testing.T) {
t.GetWorkDir().String(),
)
},
}}, nil, nil, pkg.InvalidFileModeError(
}}, nil, nil, pkg.WNew, pkg.InvalidFileModeError(
fs.ModeSymlink | 0777,
)},
@@ -1115,8 +1123,8 @@ func TestCache(t *testing.T) {
},
}, base.Append(
"identifier",
"xMDWovje7OfyIaDy_2VnjpKxRqSOQ_LoeD946t-3WsS2V2SeMJ7nDGrNfpa4Pbc-",
), want, nil},
"gIH5eti07nBAhVti3ZTn8EIGOBCZWWvNpxg5CmCZlDzIC4mBdomPmQLeEpf1IQg9",
), want, pkg.WNew, nil},
{"substitutable", &stubArtifactF{
kind: pkg.KindExec,
@@ -1134,14 +1142,14 @@ func TestCache(t *testing.T) {
},
}, base.Append(
"identifier",
"k2ilgG5KQ9NXnMoT2oB6NdwOnSPRn_H24oXQc4l6qOYIxIG9XfuEczeyrR8UEv_f",
), want, nil},
"VGjpp7NVw3OYLpgOQumfM0KcJgY3suz6torykUczcg4bGT24ySkPn5hy-4dNqqkR",
), want, pkg.WSubstitute, nil},
})
if c0, err := unsafeOpen(
if c0, err := pkg.Open(
t.Context(),
message.New(nil),
0, 0, 0, base, false,
base, &skipLock,
); err != nil {
t.Fatalf("open: error = %v", err)
} else {
@@ -1163,8 +1171,8 @@ func TestCache(t *testing.T) {
},
}, base.Append(
"identifier",
"_EmV5nsYZ2UWHgRmLDMU8i-rJWDx-kv5_1pFrzQI7vMMCM5mAXivO8UZtVfOqMR_",
), want, nil},
"zeZ4JEZ0atAKl6Am67cBID6-KR18nZGgeYfU4qTuYaWhQC4eAn0dyTXdIBH9Bos8",
), want, pkg.WSubstitute, nil},
})
}
@@ -1188,15 +1196,15 @@ func TestCache(t *testing.T) {
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
"identifier/_EmV5nsYZ2UWHgRmLDMU8i-rJWDx-kv5_1pFrzQI7vMMCM5mAXivO8UZtVfOqMR_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
"identifier/zeZ4JEZ0atAKl6Am67cBID6-KR18nZGgeYfU4qTuYaWhQC4eAn0dyTXdIBH9Bos8": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
"identifier/___9_QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")},
"identifier/_wgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")},
"identifier/_woAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")},
"identifier/k2ilgG5KQ9NXnMoT2oB6NdwOnSPRn_H24oXQc4l6qOYIxIG9XfuEczeyrR8UEv_f": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
"identifier/xMDWovje7OfyIaDy_2VnjpKxRqSOQ_LoeD946t-3WsS2V2SeMJ7nDGrNfpa4Pbc-": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
"identifier/VGjpp7NVw3OYLpgOQumfM0KcJgY3suz6torykUczcg4bGT24ySkPn5hy-4dNqqkR": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
"identifier/gIH5eti07nBAhVti3ZTn8EIGOBCZWWvNpxg5CmCZlDzIC4mBdomPmQLeEpf1IQg9": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
"substitute": {Mode: fs.ModeDir | 0700},
"substitute/OyBGorh72Z9kVw35JUa8FbqDbpR4DqT-MX1jic0uKN5PdYmUBiAF38BRsIRnBigf": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
"substitute/nWPg893oqn_YNN8kgfZrs_LVLwP90e0mKxqU8UwoazQh-yBPwhoviD7of6YALx-M": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
"work": {Mode: fs.ModeDir | 0700},
}},
@@ -1235,7 +1243,7 @@ func TestCache(t *testing.T) {
pkg.ID{0xff, 1},
nil,
nil, stub.UniqueError(0xbad),
), nil, nil, stub.UniqueError(0xbad)},
), nil, nil, pkg.WNew, stub.UniqueError(0xbad)},
{"file output", overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{
kind: pkg.KindTar,
@@ -1246,7 +1254,7 @@ func TestCache(t *testing.T) {
0400,
)
},
}}, nil, nil, errors.New(
}}, nil, nil, pkg.WNew, errors.New(
"non-file artifact produced regular file",
)},
})
@@ -1363,14 +1371,14 @@ func TestCache(t *testing.T) {
}}}, base.Append(
"identifier",
pkg.Encode(pkg.ID{0xff, 0}),
), want, nil},
), want, pkg.WNew, nil},
{"reject", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xfe, 1}, &stubArtifact{
kind: pkg.KindTar,
cure: func(t *pkg.TContext) error {
return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xbad))
},
}}}, nil, nil, stub.UniqueError(0xbad)},
}}}, nil, nil, pkg.WNew, stub.UniqueError(0xbad)},
{"match", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{
kind: pkg.KindTar,
@@ -1380,7 +1388,7 @@ func TestCache(t *testing.T) {
}}}, base.Append(
"identifier",
pkg.Encode(pkg.ID{0xff, 1}),
), want, nil},
), want, pkg.WNew, nil},
})
}, expectsFS{
".": {Mode: fs.ModeDir | 0700},
@@ -1408,7 +1416,7 @@ func TestCache(t *testing.T) {
), base.Append(
"identifier",
pkg.Encode(pkg.Checksum{0xfe, 0}),
), expectsChecksum{0xff, 0}, nil},
), expectsChecksum{0xff, 0}, pkg.WNew, nil},
})
for _, p := range [][]string{
@@ -1485,7 +1493,7 @@ func TestCache(t *testing.T) {
), expectsFS{
".": {Mode: fs.ModeDir | 0500},
"result": {Mode: 0444},
}, nil},
}, pkg.WNew, nil},
{"substituted", substituted, base.Append(
"identifier",
@@ -1493,7 +1501,7 @@ func TestCache(t *testing.T) {
), expectsFS{
".": {Mode: fs.ModeDir | 0500},
"result": {Mode: 0444},
}, nil},
}, pkg.WSubstitute, nil},
})
}, expectsFS{
".": {Mode: fs.ModeDir | 0700},
@@ -1504,18 +1512,18 @@ func TestCache(t *testing.T) {
"checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV": {Mode: 0400, Data: []byte("destroyed")},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/0Jmc-vGnNDlXTD3jxy-4DGxHW-2-2LtLZ9SXaJtDIqu4uyHfDwDbghNBQ2aYRpab": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"identifier/L-A8SK4ZX631eyealbJVH08u5pAVEf2NMk8RmLlxl7BVADkU4hNjWD6pi5H7uL1F": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV")},
"identifier/VbVV2dFVosCriHnG9t5vwfW4lbHvzOkV2eYwpGpPJZOgNBc0g1wZAhbdKEweLqmW": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"identifier/aSMwvPAwdsIF9e1spuLyRNEc8aTFA4HRVasoNqGjxdm1laSMs2h2teGsoSzLp_pR": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV")},
"identifier/CLyyxJWn1yUGFs_0KnJ4ZSU2hH4-elvGFRB36x14LrNrKBJPxvORhL9O4Rc7oeYU": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV")},
"identifier/arv8a6z4i0x6pUb5Z2T-3iE4ETvyZj-uReHGKsS7uiBgMgKNEOzTGG3LIZb8vp0L": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV")},
"identifier/heRgWhNJmhm898V68kw0ta76t4rP1o29tYW_TrdyBWXGfo37K3QWA7Z-JkLXAwcn": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"identifier/q-VoVBI3IjcWTqwIokpi3y05CP113CHgHslc-XWnhOvDULwzVc3q9Y5xOCm_YyLZ": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"status": {Mode: fs.ModeDir | 0700},
"status/0Jmc-vGnNDlXTD3jxy-4DGxHW-2-2LtLZ9SXaJtDIqu4uyHfDwDbghNBQ2aYRpab": {Mode: fs.ModeSymlink | 0777, Data: []byte("dzO8FEY9lu4hwRT6BfRZOX-uYGsC_5XH4jEJ7sJyThcmG9J_w1ArOAaUCGfL8wAM")},
"status/VbVV2dFVosCriHnG9t5vwfW4lbHvzOkV2eYwpGpPJZOgNBc0g1wZAhbdKEweLqmW": {Mode: 0400, Data: []byte(statusHeader + "destroyed")},
"status/dzO8FEY9lu4hwRT6BfRZOX-uYGsC_5XH4jEJ7sJyThcmG9J_w1ArOAaUCGfL8wAM": {Mode: 0400, Data: []byte(statusHeader + "destroyed")},
"status/q-VoVBI3IjcWTqwIokpi3y05CP113CHgHslc-XWnhOvDULwzVc3q9Y5xOCm_YyLZ": {Mode: fs.ModeSymlink | 0777, Data: []byte("dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x")},
"status/heRgWhNJmhm898V68kw0ta76t4rP1o29tYW_TrdyBWXGfo37K3QWA7Z-JkLXAwcn": {Mode: 0400, Data: []byte(statusHeader + "destroyed")},
"status/dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x": {Mode: 0400, Data: []byte(statusHeader + "destroyed")},
"substitute": {Mode: fs.ModeDir | 0700},
"substitute/dzO8FEY9lu4hwRT6BfRZOX-uYGsC_5XH4jEJ7sJyThcmG9J_w1ArOAaUCGfL8wAM": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"substitute/dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")},
"work": {Mode: fs.ModeDir | 0700},
}},
@@ -1586,14 +1594,14 @@ func TestCache(t *testing.T) {
{"extern", a, base.Append(
"identifier",
pkg.Encode(wantIdent.Value()),
), wantOutput, nil},
), wantOutput, pkg.WExternal, nil},
{"substitute", _a, base.Append(
"identifier",
pkg.Encode(_wantIdent.Value()),
), _wantOutput, nil},
), _wantOutput, pkg.WExternal, nil},
{"mismatch", kca, nil, nil, &pkg.ChecksumMismatchError{
{"mismatch", kca, nil, nil, pkg.WExternal, &pkg.ChecksumMismatchError{
Got: wantChecksum,
}},
})
@@ -1607,17 +1615,163 @@ func TestCache(t *testing.T) {
"checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl/result": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent")},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/4HqRo4uTwRQjfy3d2cujMoDC_pC4iv20h4a7NYlx0UdbVuky18o5iK78TFEfPX2U": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/7AZcJm58ghFyTVf_v2baSntgpsxkP5el7ti9dC77C29n8YTEqQW9jRW92KGNdYnz": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")},
"identifier/c4aCI00C-ZVyo_FQDQLl1OYK4U_kjzxwrLdFDiXMHnbMcZXCkXo_nxUWauScZ_4V": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/cNoG77frXGRCJa7fUi1INKUEQg7L4qrX5acsSv-wqZdGZT7dQwM93rD3at6kSFFF": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
"identifier/gvCqzexZVqXjF8B5lKMcP5onmq3jJ6AKqzOW_WN0Fl2yTr9NKhPt9l_ClD2EOSlS": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")},
"identifier/k8yyhlBV3JpYzzywAnrRWkfp2TmgIDNC6FqMFwrrR2x0C3unBLveDNKgigOjG9MM": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/Xys8hPpJsKirZmTTuT7SwQ6661TCp_ZRu8iUjPPD7pC5E3ll7xw4zhNlZ2PVcz_-": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")},
"identifier/8sInO_dhPW9kweit7jVuH_vtMkRxlZT7XE4_yEKPZmpGkgVxkmxz0OpXgbMsH6ET": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/ofaXbB5gIza_7W4Rzo5XDe_8FwlCPKWn3TBcmGgFAkkTWMl5GXGmOzX89Jd2Mk2A": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
"identifier/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")},
"status": {Mode: fs.ModeDir | 0700},
"status/gvCqzexZVqXjF8B5lKMcP5onmq3jJ6AKqzOW_WN0Fl2yTr9NKhPt9l_ClD2EOSlS": {Mode: 0400, Data: []byte("\x00")},
"status/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: 0400, Data: []byte("\x00")},
"substitute": {Mode: fs.ModeDir | 0700},
"substitute/qOYrxy9ztKeOA96Os811_0Ox5sd8FBOxis6psJAnRJL5MLazFMaqmd4g7t7k1OHk": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"substitute/socGRnhdsJlJ4Z01ZwHFZdLzFH0rWvoaJrylcUKtvhBdGsE7VoYl-vdUuvfK8B4I": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"work": {Mode: fs.ModeDir | 0700},
}},
{"extern shallow", pkg.CExternShallow, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
a := &stubArtifactF{
kind: pkg.KindExec,
params: []byte("extern"),
}
wantIdent := c.Ident(a)
wantOutput := expectsFS{
".": {Mode: fs.ModeDir | 0500},
"result": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent")},
}
var wantChecksum pkg.Checksum
if err := pkg.SumFS(
&wantChecksum,
fstest.MapFS(wantOutput),
".",
); err != nil {
t.Fatal(err)
}
wantChecksumH := unique.Make(wantChecksum)
_a := &stubArtifactF{
kind: pkg.KindExec,
params: []byte("extern substitute"),
deps: []pkg.Artifact{pkg.NewFile("", nil)},
}
_wantIdent := c.Ident(_a)
_wantOutput := expectsFS{
".": {Mode: fs.ModeDir | 0500},
}
var _wantChecksum pkg.Checksum
if err := pkg.SumFS(
&_wantChecksum,
fstest.MapFS(_wantOutput),
".",
); err != nil {
t.Fatal(err)
}
_wantChecksumH := unique.Make(_wantChecksum)
kca := pkg.NewExec(
"", "",
new(pkg.Checksum), 0, false, false,
fhs.AbsRoot, nil, fhs.AbsRoot, nil,
)
kcIdent := c.Ident(kca)
fia := &stubArtifactF{
kind: pkg.KindExec,
params: []byte("flood input"),
deps: []pkg.Artifact{_a},
}
fiaIdent := c.Ident(fia)
flia := &stubArtifactF{
kind: pkg.KindExec,
params: []byte("flood input local"),
deps: []pkg.Artifact{_a},
}
fliaIdent := c.Ident(flia)
h := &stubArtifactF{
kind: pkg.KindExec,
params: []byte("hanging input"),
}
fhia := &stubArtifactF{
kind: pkg.KindExec,
params: []byte("flood input local"),
deps: []pkg.Artifact{h},
}
fhiaIdent := c.Ident(fhia)
c.SetExternal(stubExtern{
artifact: map[unique.Handle[pkg.ID]]pkg.Checksum{
wantIdent: wantChecksum,
_wantIdent: _wantChecksum,
kcIdent: wantChecksum,
fiaIdent: wantChecksum,
fliaIdent: wantChecksum,
fhiaIdent: wantChecksum,
},
checksum: map[unique.Handle[pkg.Checksum]]fstest.MapFS{
wantChecksumH: fstest.MapFS(wantOutput),
_wantChecksumH: fstest.MapFS(_wantOutput),
},
status: map[unique.Handle[pkg.ID]]string{
wantIdent: "\x00",
kcIdent: "unreachable",
},
})
cureMany(t, c, []cureStep{
{"extern", a, base.Append(
"identifier",
pkg.Encode(wantIdent.Value()),
), wantOutput, pkg.WExternal, nil},
{"flood shallow extern", fia, base.Append(
"identifier",
pkg.Encode(fiaIdent.Value()),
), wantOutput, pkg.WExternal, nil},
{"substitute", _a, base.Append(
"identifier",
pkg.Encode(_wantIdent.Value()),
), _wantOutput, pkg.WExternal, nil},
{"flood shallow local", flia, base.Append(
"identifier",
pkg.Encode(fliaIdent.Value()),
), wantOutput, pkg.WExternal, nil},
{"flood shallow hanging", fhia, nil, nil,
pkg.WNew, pkg.HangingInputError(c.Ident(h))},
{"mismatch", kca, nil, nil, pkg.WExternal, &pkg.ChecksumMismatchError{
Got: wantChecksum,
}},
})
}, expectsFS{
".": {Mode: fs.ModeDir | 0700},
"checksum": {Mode: fs.ModeDir | 0700},
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
"checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl": {Mode: fs.ModeDir | 0500},
"checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl/result": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent")},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/3fYJjSiWhklt7TK9MPVLGk5_8AIU8ostTcFPXULJf_qeAVG6pmC-Cqqu4ZhEXRxn": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")},
"identifier/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")},
"identifier/8sInO_dhPW9kweit7jVuH_vtMkRxlZT7XE4_yEKPZmpGkgVxkmxz0OpXgbMsH6ET": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/Xys8hPpJsKirZmTTuT7SwQ6661TCp_ZRu8iUjPPD7pC5E3ll7xw4zhNlZ2PVcz_-": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")},
"identifier/k8yyhlBV3JpYzzywAnrRWkfp2TmgIDNC6FqMFwrrR2x0C3unBLveDNKgigOjG9MM": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"identifier/mXlNz_v77nW7jstn_rJn4RL7dCQlkakM0y-HjO6tkDubtzaj-wCmW1hIr2Gk64_O": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")},
"status": {Mode: fs.ModeDir | 0700},
"status/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: 0400, Data: []byte("\x00")},
"substitute": {Mode: fs.ModeDir | 0700},
"substitute/socGRnhdsJlJ4Z01ZwHFZdLzFH0rWvoaJrylcUKtvhBdGsE7VoYl-vdUuvfK8B4I": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
"substitute/MccYezQ4pshkeBV4w_aAEIwvZdKHL3OAgAkR3ouZ43EF94Ur1HBHaN7njPfJAj50": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")},
"substitute/VV5W0_DiA1iylaqbKFThp1ZpV_y1ccVS1XyqDnDaXoHQ-EEyPI4XFrQHcHOF2hWG": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")},
"work": {Mode: fs.ModeDir | 0700},
}},
@@ -1635,7 +1789,7 @@ func TestErrors(t *testing.T) {
}{
{"InvalidLookupError", pkg.InvalidLookupError{
0xff, 0xf0,
}, "attempting to look up non-dependency artifact __AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"},
}, "attempting to look up non-input artifact __AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"},
{"InvalidArtifactError", pkg.InvalidArtifactError{
0xff, 0xfd,
@@ -1883,7 +2037,7 @@ func (earlyFailureF) Kind() pkg.Kind { return pkg.KindExec }
func (earlyFailureF) Params(*pkg.IContext) {}
func (earlyFailureF) IsExclusive() bool { return false }
func (a earlyFailureF) Dependencies() []pkg.Artifact {
func (a earlyFailureF) Inputs() []pkg.Artifact {
deps := make([]pkg.Artifact, a)
for i := range deps {
deps[i] = a - 1
@@ -1901,7 +2055,7 @@ func (a earlyFailureF) Cure(*pkg.FContext) error {
func BenchmarkEarlyDCE(b *testing.B) {
msg := message.New(log.New(os.Stderr, "dce: ", 0))
msg.SwapVerbose(testing.Verbose())
c, err := pkg.Open(b.Context(), msg, 0, 0, 0, check.MustAbs(b.TempDir()))
c, err := pkg.Open(b.Context(), msg, check.MustAbs(b.TempDir()), nil)
if err != nil {
b.Fatal(err)
}
@@ -1950,7 +2104,8 @@ func TestOpen(t *testing.T) {
if _, err := pkg.Open(
t.Context(),
message.New(nil),
0, 0, 0, check.MustAbs(container.Nonexistent),
check.MustAbs(container.Nonexistent),
nil,
); !reflect.DeepEqual(err, wantErr) {
t.Errorf("Open: error = %#v, want %#v", err, wantErr)
}
@@ -1978,7 +2133,8 @@ func TestOpen(t *testing.T) {
if _, err := pkg.Open(
t.Context(),
message.New(nil),
0, 0, 0, tempDir.Append("cache"),
tempDir.Append("cache"),
nil,
); !reflect.DeepEqual(err, wantErr) {
t.Errorf("Open: error = %#v, want %#v", err, wantErr)
}
@@ -2000,7 +2156,8 @@ func TestOpen(t *testing.T) {
if _, err := pkg.Open(
t.Context(),
message.New(nil),
0, 0, 0, tempDir.Append("cache"),
tempDir.Append("cache"),
nil,
); !reflect.DeepEqual(err, wantErr) {
t.Errorf("Open: error = %#v, want %#v", err, wantErr)
}
@@ -2021,7 +2178,7 @@ func TestOpen(t *testing.T) {
if _, err := pkg.Open(
t.Context(),
message.New(nil),
0, 0, 0, tempDir.Append("cache"),
tempDir.Append("cache"), nil,
); !reflect.DeepEqual(err, wantErr) {
t.Errorf("Open: error = %#v, want %#v", err, wantErr)
}
@@ -2074,8 +2231,8 @@ func TestExtensionRegister(t *testing.T) {
if _, err := pkg.Open(
t.Context(),
message.New(log.Default()),
0, 0, 0,
check.MustAbs(container.Nonexistent),
nil,
); !errors.Is(err, os.ErrNotExist) {
t.Fatalf("Open: error = %v", err)
}
@@ -2113,7 +2270,7 @@ func TestExtensionRegister(t *testing.T) {
pkg.Register(pkg.KindCustomOffset, nil)
t.Cleanup(func() { opened = false })
_, _ = pkg.Open(nil, nil, 0, 0, 0, nil)
_, _ = pkg.Open(nil, nil, nil, nil)
panic("unreachable")
})
@@ -2124,11 +2281,7 @@ func TestExtensionRegister(t *testing.T) {
base := check.MustAbs(t.TempDir())
t.Cleanup(func() { opened = false })
if c, err := pkg.Open(
t.Context(), nil,
0, 0, 0,
base,
); err != nil {
if c, err := pkg.Open(t.Context(), nil, base, nil); err != nil {
t.Fatal(err)
} else {
c.Close()
@@ -2156,8 +2309,7 @@ func TestExtensionRegister(t *testing.T) {
}
if _, err := pkg.Open(
t.Context(), nil,
0, 0, 0,
base,
base, nil,
); !reflect.DeepEqual(err, wantErr) {
t.Fatalf("Open: error = %v, want %v", err, wantErr)
}
@@ -2178,8 +2330,8 @@ func TestExtensionRegister(t *testing.T) {
if _, err := pkg.Open(
t.Context(), nil,
0, 0, 0,
base,
nil,
); !reflect.DeepEqual(err, pkg.ErrWouldPromote) {
t.Fatalf("Open: error = %v", err)
}
@@ -2192,8 +2344,7 @@ func TestExtensionRegister(t *testing.T) {
if c, err := pkg.Open(
t.Context(), nil,
pkg.CPromoteVariant, 0, 0,
base,
base, &pkg.CacheAttr{Flags: pkg.CPromoteVariant},
); err != nil {
t.Fatalf("Open: error = %v", err)
} else {
@@ -2218,8 +2369,7 @@ func TestExtensionRegister(t *testing.T) {
if _, err := pkg.Open(
t.Context(), nil,
0, 0, 0,
base,
base, nil,
); !reflect.DeepEqual(err, pkg.ErrInvalidExtension) {
t.Fatalf("Open: error = %v", err)
}
@@ -2236,8 +2386,7 @@ func TestExtensionRegister(t *testing.T) {
if _, err := pkg.Open(
t.Context(), nil,
0, 0, 0,
base,
base, nil,
); !reflect.DeepEqual(err, pkg.UnsupportedVariantError("rosa")) {
t.Fatalf("Open: error = %v", err)
}
+15 -2
View File
@@ -16,6 +16,8 @@ type tarArtifact struct {
f Artifact
}
var _ CuresExempt = new(tarArtifact)
// tarArtifactNamed embeds tarArtifact for a [fmt.Stringer] tarball.
type tarArtifactNamed struct {
tarArtifact
@@ -56,8 +58,8 @@ func init() {
})
}
// Dependencies returns a slice containing the backing file.
func (a *tarArtifact) Dependencies() []Artifact {
// Inputs returns a slice containing the backing file.
func (a *tarArtifact) Inputs() []Artifact {
return []Artifact{a.f}
}
@@ -170,6 +172,13 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
}
break
case tar.TypeChar:
t.GetMessage().Verbosef(
"%sskipping character device %d, %d %q%s",
t.cache.sgrWarn, header.Devmajor, header.Devminor, header.Name, t.cache.sgrRes,
)
continue
case tar.TypeXGlobalHeader:
continue // ignore
@@ -211,3 +220,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
}
return
}
// CuresExempt exempts the cheap [KindTar] implementation often at the end of a
// [FileArtifact] pipeline.
func (*tarArtifact) CuresExempt() {}
+9 -9
View File
@@ -80,8 +80,8 @@ func TestTar(t *testing.T) {
"checksum/" + wantEncode + "/work": {Mode: fs.ModeDir | 0500},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/T68YqeEW5moiwVe4J0wPvjERgyMUd4k_cKKxTcQx6AXqZaQAuuryu-Iv-qxDV6-T": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)},
"identifier/WbWIIUGl6bqDBsjU-UB69JqOWLjG5waiUJBUBGeeRp3V7FBbwaBe3sG1qm7DlPSk": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)},
"identifier/7OZ5ErCxUJyRnaaFvUKhTryjsJAoOBUR2MZpUB1DD57jRa09Xxsh9BUs0dM9z5uH": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)},
"identifier/paWdPW_BowV3345c4GP4xxSNgxVs_7F09m9m7OaH5XbyuI3dTGZ-kFPOXFbwgr5O": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)},
"substitute": {Mode: fs.ModeDir | 0700},
@@ -104,8 +104,8 @@ func TestTar(t *testing.T) {
"checksum/" + wantExpandEncode + "/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
"identifier": {Mode: fs.ModeDir | 0700},
"identifier/WbWIIUGl6bqDBsjU-UB69JqOWLjG5waiUJBUBGeeRp3V7FBbwaBe3sG1qm7DlPSk": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)},
"identifier/e3BECw_x_vDyTvj2P48MJVgwpgALeXQ90Ye2Y8gr6SwIPtMup6SR2LVcCTDRGpVi": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)},
"identifier/1g2Tcg7pOJkZFxlKploBm4U0vIyMYbxDkcwwydwsF9BMs-w-knFJS41jnqOt16jT": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)},
"identifier/7OZ5ErCxUJyRnaaFvUKhTryjsJAoOBUR2MZpUB1DD57jRa09Xxsh9BUs0dM9z5uH": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)},
"substitute": {Mode: fs.ModeDir | 0700},
@@ -212,24 +212,24 @@ func checkTarHTTP(
&client,
"file:///testdata",
testdataChecksum,
), pkg.Gzip)), ignorePathname, want, nil},
), pkg.Gzip)), ignorePathname, want, pkg.WNew, nil},
{"directory", pkg.NewTar(pkg.NewDecompress(
&tarDir,
pkg.Gzip,
)), ignorePathname, want, nil},
)), ignorePathname, want, pkg.WNew, nil},
{"multiple entries", pkg.NewTar(pkg.NewDecompress(
&tarDirMulti,
pkg.Gzip,
)), nil, nil, errors.New(
)), nil, nil, pkg.WNew, errors.New(
"input directory does not contain a single regular file",
)},
{"bad type", pkg.NewTar(pkg.NewDecompress(
&tarDirType,
pkg.Gzip,
)), nil, nil, errors.New(
)), nil, nil, pkg.WNew, errors.New(
"input directory does not contain a single regular file",
)},
@@ -239,6 +239,6 @@ func checkTarHTTP(
cure: func(t *pkg.TContext) error {
return stub.UniqueError(0xcafe)
},
}), nil, nil, stub.UniqueError(0xcafe)},
}), nil, nil, pkg.WNew, stub.UniqueError(0xcafe)},
})
}
+6 -1
View File
@@ -18,6 +18,11 @@ const (
jobsLE = `"$(expr ` + jobsE + ` '*' 2)"`
// jobsLFlagE is expression for flag with double of preferred job count.
jobsLFlagE = `"-j$(expr ` + jobsE + ` '*' 2)"`
// loadE is expression for preferred loadavg target set by [pkg].
loadE = `"$` + pkg.EnvLoad + `"`
// loadFlagE is expression for flag with preferred loadavg target.
loadFlagE = `"-l$` + pkg.EnvLoad + `"`
)
// newTar wraps [pkg.NewHTTPGetTar] with a simpler function signature.
@@ -102,7 +107,7 @@ func skipGNUTests(tests ...int64) string {
buf.WriteString(strconv.Itoa(int(n - 1)))
buf.WriteString(" ")
}
if i == len(tests)-1 || tests[i+1] != n+1 {
if i == len(tests)-1 || (tests[i+1] != n+1 && tests[i+1] != n+2) {
buf.WriteString(strconv.Itoa(int(n + 1)))
buf.WriteString("-")
}
+1
View File
@@ -16,6 +16,7 @@ func TestSkipGNUTests(t *testing.T) {
}{
{[]int64{764}, "1-763 765-"},
{[]int64{764, 0xcafe, 37, 9}, "1-8 10-36 38-763 765-51965 51967-"},
{[]int64{168, 170, 623, 764}, "1-167 169 171-622 624-763 765-"},
{[]int64{1, 2, 0xbed}, "3-3052 3054-"},
{[]int64{3, 4}, "1-2 5-"},
}
-124
View File
@@ -1,124 +0,0 @@
package rosa
import (
"fmt"
"io"
"net/http"
"os"
"time"
"hakurei.app/fhs"
"hakurei.app/internal/pkg"
)
// busyboxBin is a busybox binary distribution installed under bin/busybox.
type busyboxBin struct {
// Underlying busybox binary.
bin pkg.FileArtifact
}
// Kind returns the hardcoded [pkg.Kind] value.
func (a busyboxBin) Kind() pkg.Kind { return kindBusyboxBin }
// Params is a noop.
func (a busyboxBin) Params(*pkg.IContext) {}
// IsExclusive returns false: Cure performs a trivial filesystem write.
func (busyboxBin) IsExclusive() bool { return false }
// Dependencies returns the underlying busybox [pkg.FileArtifact].
func (a busyboxBin) Dependencies() []pkg.Artifact {
return []pkg.Artifact{a.bin}
}
func init() {
pkg.Register(kindBusyboxBin, func(r *pkg.IRReader) pkg.Artifact {
a := busyboxBin{r.Next().(pkg.FileArtifact)}
if _, ok := r.Finalise(); ok {
panic(pkg.ErrUnexpectedChecksum)
}
return a
})
}
// String returns the reporting name of the underlying file prefixed with expand.
func (a busyboxBin) String() string {
return "expand-" + a.bin.(fmt.Stringer).String()
}
// Cure installs the underlying busybox [pkg.File] to bin/busybox.
func (a busyboxBin) Cure(t *pkg.TContext) (err error) {
var r io.ReadCloser
if r, err = t.Open(a.bin); err != nil {
return
}
defer func() {
closeErr := r.Close()
if err == nil {
err = closeErr
}
}()
binDir := t.GetWorkDir().Append("bin")
if err = os.MkdirAll(binDir.String(), 0700); err != nil {
return
}
var w *os.File
if w, err = os.OpenFile(
binDir.Append("busybox").String(),
os.O_WRONLY|os.O_CREATE|os.O_EXCL,
0500,
); err != nil {
return
}
defer func() {
closeErr := w.Close()
if err == nil {
err = closeErr
}
}()
_, err = io.Copy(w, r)
return
}
// newBusyboxBin returns a [pkg.Artifact] containing a busybox installation from
// the https://busybox.net/downloads/binaries/ binary release.
func (s *S) newBusyboxBin() pkg.Artifact {
var version, url, checksum string
switch s.arch {
case "amd64":
version = "1.35.0"
url = "https://busybox.net/downloads/binaries/" +
version + "-" + s.linuxArch() + "-linux-musl/busybox"
checksum = "L7OBIsPu9enNHn7FqpBT1kOg_mCLNmetSeNMA3i4Y60Z5jTgnlX3qX3zcQtLx5AB"
case "arm64":
version = "1.31.0"
url = "https://busybox.net/downloads/binaries/" +
version + "-defconfig-multiarch-musl/busybox-armv8l"
checksum = "npJjBO7iwhjW6Kx2aXeSxf8kXhVgTCDChOZTTsI8ZfFfa3tbsklxRiidZQdrVERg"
default:
panic("unsupported target " + s.arch)
}
return pkg.NewExec(
"busybox-bin-"+version, s.arch, nil, pkg.ExecTimeoutMax, false, false,
fhs.AbsRoot, []string{
"PATH=/system/bin",
},
AbsSystem.Append("bin", "busybox"),
[]string{"hush", "-c", "" +
"busybox mkdir -p /work/system/bin/ && " +
"busybox cp /system/bin/busybox /work/system/bin/ && " +
"busybox --install -s /work/system/bin/"},
pkg.Path(AbsSystem, true, busyboxBin{pkg.NewHTTPGet(
&http.Client{Transport: &http.Transport{
// busybox website is really slow to respond
TLSHandshakeTimeout: 2 * time.Minute,
}}, url,
mustDecode(checksum),
)}),
)
}
+5 -4
View File
@@ -35,7 +35,7 @@ type CMakeHelper struct {
var _ Helper = new(CMakeHelper)
// extra returns the cmake handle alongside either ninja or make.
func (attr *CMakeHelper) extra(int) P {
func (attr *CMakeHelper) extra() P {
if attr != nil && attr.Make {
return P{_cmake, _make}
}
@@ -61,10 +61,10 @@ func (attr *CMakeHelper) script(t Toolchain, name string) string {
}
generate := "Ninja"
test := "ninja " + jobsFlagE + " test"
test := "ninja " + jobsFlagE + " " + loadFlagE + " test"
if attr.Make {
generate = "'Unix Makefiles'"
test = "make " + jobsFlagE + " test"
test = "make " + jobsFlagE + " " + loadFlagE + " test"
}
if attr.Test != "" {
test = attr.Test
@@ -84,6 +84,7 @@ func (attr *CMakeHelper) script(t Toolchain, name string) string {
return `
cmake -G ` + generate + ` \
-Wno-author -Wno-unused-cli \
-DCMAKE_C_COMPILER_TARGET="${ROSA_TRIPLE}" \
-DCMAKE_CXX_COMPILER_TARGET="${ROSA_TRIPLE}" \
-DCMAKE_ASM_COMPILER_TARGET="${ROSA_TRIPLE}" \
@@ -97,7 +98,7 @@ cmake -G ` + generate + ` \
}), " \\\n\t") + ` \
-DCMAKE_INSTALL_PREFIX=/system \
'/usr/src/` + name + `/` + filepath.Join(attr.Append...) + `'
cmake --build . --parallel=` + jobsE + `
cmake --build . --parallel=` + jobsE + ` -- ` + loadFlagE + `
DESTDIR=/work cmake --install .
` + script
}
+4 -2
View File
@@ -107,6 +107,8 @@ func init() {
a := cureEtc{}
if r.ReadUint32() == 0 {
a.minimal = true
} else {
r.Next()
}
if _, ok := r.Finalise(); ok {
panic(pkg.ErrUnexpectedChecksum)
@@ -118,8 +120,8 @@ func init() {
// IsExclusive returns false: Cure performs a few trivial filesystem writes.
func (cureEtc) IsExclusive() bool { return false }
// Dependencies returns a slice containing the backing iana-etc release.
func (a cureEtc) Dependencies() []pkg.Artifact {
// Inputs returns a slice containing the backing iana-etc release.
func (a cureEtc) Inputs() []pkg.Artifact {
if !a.minimal {
return []pkg.Artifact{ianaEtc}
}
+104
View File
@@ -0,0 +1,104 @@
package rosa
import (
"errors"
"io/fs"
"os"
"path/filepath"
"hakurei.app/internal/pkg"
)
// gentooOverlay are symlinks on top of a Gentoo LLVM stage3 tarball for
// compatibility with the Rosa OS stage0 distribution.
type gentooOverlay struct{ stage3 pkg.Artifact }
// Kind returns the hardcoded [pkg.Kind] value.
func (a gentooOverlay) Kind() pkg.Kind { return kindGentooOverlay }
// Params is a noop.
func (a gentooOverlay) Params(*pkg.IContext) {}
// IsExclusive returns false: Cure performs a trivial filesystem write.
func (gentooOverlay) IsExclusive() bool { return false }
// Inputs returns the underlying Gentoo stage3.
func (a gentooOverlay) Inputs() []pkg.Artifact {
return []pkg.Artifact{a.stage3}
}
func init() {
pkg.Register(kindGentooOverlay, func(r *pkg.IRReader) pkg.Artifact {
a := gentooOverlay{r.Next()}
if _, ok := r.Finalise(); ok {
panic(pkg.ErrUnexpectedChecksum)
}
return a
})
}
// String returns a hardcoded name.
func (a gentooOverlay) String() string { return "gentoo-overlay" }
// Revision returns a hardcoded value incremented on layout changes.
func (a gentooOverlay) Revision() uint64 { return 0 }
// Cure installs the overlay.
func (a gentooOverlay) Cure(f *pkg.FContext) (err error) {
pathname, _ := f.GetArtifact(a.stage3)
var stage3 *os.Root
if stage3, err = os.OpenRoot(pathname.String()); err != nil {
return err
}
defer func() {
closeErr := stage3.Close()
if err == nil {
err = closeErr
}
}()
fsys := stage3.FS()
system := f.GetWorkDir().Append("system")
bin := system.Append("bin")
if err = os.MkdirAll(bin.String(), 0700); err != nil {
return
}
linknames := []string{
"../../bin/sh",
}
var dents []os.DirEntry
const llvm = "usr/lib/llvm"
dents, err = fs.ReadDir(fsys, llvm)
if err != nil {
return
}
if len(dents) != 1 {
return errors.New("stage3 /" + llvm + " contains more than one entry")
}
llvmBin := filepath.Join(llvm, dents[0].Name(), "bin")
dents, err = fs.ReadDir(fsys, llvmBin)
if err != nil {
return
}
for _, dent := range dents {
linknames = append(linknames, filepath.Join(
"../..",
llvmBin,
dent.Name(),
))
}
for _, linkname := range linknames {
if err = os.Symlink(
linkname,
bin.Append(filepath.Base(linkname)).String(),
); err != nil {
return
}
}
return
}
+14 -7
View File
@@ -20,19 +20,26 @@ func (t Toolchain) NewViaGit(
return t.New(strings.TrimSuffix(
path.Base(url),
".git",
)+"-src-"+path.Base(rev), THostNet, t.Append(nil,
_nssCACert,
_git,
), &checksum, nil, `
)+"-src", path.Base(rev), nil, &PackageAttr{
KnownChecksum: &checksum,
HostNet: true,
Paths: []pkg.ExecPath{resolvconf()},
}, &GenericHelper{
Build: `
git \
-c advice.detachedHead=false \
clone \
--depth=1 \
--revision=`+rev+` \
--revision=` + rev + ` \
--shallow-submodules \
--recurse-submodules \
`+url+` \
` + url + ` \
/work
rm -rf /work/.git
`, resolvconf())
`,
},
_nssCACert,
_git,
)
}
+10 -28
View File
@@ -13,7 +13,7 @@ func (t Toolchain) newGo(
script string,
boot ...pkg.Artifact,
) pkg.Artifact {
return t.NewPackage("go", version, newTar(
return t.New("go", version, newTar(
"https://go.dev/dl/go"+version+".src.tar.gz",
checksum,
pkg.Gzip,
@@ -56,16 +56,15 @@ ln -s \
func init() {
const (
version = "1.26.4"
checksum = "fpqJlxa41wKRtbnviYNLk9VxgcL-5oIEDxsriF8svU6kNwQW70oRRA9gTz_ImVoB"
version = "1.25.12"
checksum = "XNrGD_boJl2-El_a_T3BuTcMin_WPoU-FGddcNG8dcXA8n2QuxZB7kaUaCWu60QX"
)
meta := Metadata{
Name: "go",
Description: "the Go programming language toolchain",
Name: "go-bootstrap",
Description: "the Go programming language toolchain (bootstrap)",
Website: "https://go.dev",
Version: version,
ID: 1227,
Exclude: true,
}
native.MustRegister(meta.Name, func(t Toolchain) (*Metadata, pkg.Artifact) {
var (
@@ -76,7 +75,7 @@ func init() {
)
switch t.arch {
case "amd64":
bootstrapEarly = []pkg.Artifact{t.NewPackage("go", "1.4-bootstrap", newTar(
bootstrapEarly = []pkg.Artifact{t.New("go", "1.4-bootstrap", newTar(
"https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz",
"8o9JL_ToiQKadCTb04nvBDkp8O1xiWOolAxVEqaTGodieNe4lOFEjlOxN3bwwe23",
pkg.Gzip,
@@ -152,8 +151,8 @@ sed -i \
)
go125 := t.newGo(
"1.25.11",
"cnqAQ8wpVZXcM6nHAfSqFkIW4L3H73ALB9rBfKUBbfgg4_pOF3I9zOZARgYQ6MR2",
version,
checksum,
[]string{"CGO_ENABLED=0"}, `
sed -i \
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
@@ -165,23 +164,6 @@ rm \
`, go123,
)
return &meta, t.newGo(
version,
checksum,
finalEnv, `
sed -i \
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
cmd/link/internal/`+t.arch+`/obj.go
sed -i \
's/cpu.X86.HasAVX512VBMI/& \&\& cpu.X86.HasPOPCNT/' \
internal/runtime/gc/scan/scan_amd64.go
rm \
os/root_unix_test.go \
cmd/cgo/internal/testsanitizers/tsan_test.go \
cmd/cgo/internal/testsanitizers/cshared_test.go
`, go125,
)
return &meta, go125
})
}
+37 -186
View File
@@ -1,27 +1,25 @@
package rosa
import (
"io/fs"
"regexp"
"slices"
"strings"
"unsafe"
"hakurei.app/internal/pkg"
)
var (
_llvmSource = H("llvm-project")
_muslHeaders = H("musl-headers")
_earlyCompilerRT = H("early-compiler-rt")
_earlyRuntimes = H("early-runtimes")
_musl = H("musl")
_llvmSource = H("llvm-project")
_muslHeaders = H("musl-headers")
_earlyRuntimes = H("early-runtimes")
_musl = H("musl")
_bash = H("bash")
_gawk = H("gawk")
_coreutils = H("coreutils")
_diffutils = H("diffutils")
_findutils = H("findutils")
_bash = H("bash")
_awk = H("awk")
_pythonEarly = H("python-early")
_coreutils = H("coreutils")
_diffutils = H("diffutils")
_findutils = H("findutils")
_zlib = H("zlib")
_zstd = H("zstd")
@@ -50,165 +48,6 @@ func litArgs(verbose bool, skipChecks ...string) string {
}
func init() {
var llvmPatches []KV
for _, name := range [...]string{
"increase-stack-size-unconditional",
"add-rosa-vendor",
"xfail-broken-tests",
"path-system-include",
"path-system-libraries",
} {
p, err := fs.ReadFile(nativeB, "package/llvm/"+name+".patch")
if err != nil {
panic(err)
}
llvmPatches = append(llvmPatches, KV{
name,
unsafe.String(unsafe.SliceData(p), len(p)),
})
}
native.MustRegister("early-compiler-rt", func(t Toolchain) (*Metadata, pkg.Artifact) {
meta := Metadata{
Name: "early-compiler-rt",
Description: "early LLVM runtime: compiler-rt",
Dependencies: P{_musl},
}
_meta, source := t.MustLoad(_llvmSource)
meta.Version = _meta.Version
major, _, _ := strings.Cut(meta.Version, ".")
return &meta, t.NewPackage("early-compiler-rt", meta.Version, source, &PackageAttr{
Flag: TExclusive,
}, &CMakeHelper{
Append: []string{"compiler-rt"},
Cache: []KV{
{"ENABLE_LINKER_BUILD_ID", "ON"},
// libc++ not yet available
{"CMAKE_CXX_COMPILER_TARGET", ""},
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_ENABLE_RTTI", "ON"},
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
{"LLVM_LINK_LLVM_DYLIB", "ON"},
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
{"COMPILER_RT_BUILD_BUILTINS", "ON"},
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "ON"},
{"COMPILER_RT_USE_BUILTINS_LIBRARY", "ON"},
{"COMPILER_RT_SANITIZERS_TO_BUILD", "asan"},
{"COMPILER_RT_BUILD_GWP_ASAN", "OFF"},
// does not work without libunwind
{"COMPILER_RT_BUILD_CTX_PROFILE", "OFF"},
{"COMPILER_RT_BUILD_LIBFUZZER", "OFF"},
{"COMPILER_RT_BUILD_MEMPROF", "OFF"},
{"COMPILER_RT_BUILD_PROFILE", "OFF"},
{"COMPILER_RT_BUILD_XRAY", "OFF"},
},
SkipTest: true,
Script: `
mkdir -p "/work/system/lib/clang/` + major + `/lib/"
ln -s \
"../../../${ROSA_TRIPLE}" \
"/work/system/lib/clang/` + major + `/lib/"
ln -s \
"clang_rt.crtbegin-` + t.linuxArch() + `.o" \
"/work/system/lib/${ROSA_TRIPLE}/crtbeginS.o"
ln -s \
"clang_rt.crtend-` + t.linuxArch() + `.o" \
"/work/system/lib/${ROSA_TRIPLE}/crtendS.o"
`,
},
_python,
_muslHeaders,
_kernelHeaders,
)
})
native.MustRegister("early-runtimes", func(t Toolchain) (*Metadata, pkg.Artifact) {
meta := Metadata{
Name: "early-runtimes",
Description: "early LLVM runtimes: libunwind, libcxx, libcxxabi",
Dependencies: P{
_earlyCompilerRT,
},
}
_meta, source := t.MustLoad(_llvmSource)
meta.Version = _meta.Version
return &meta, t.NewPackage("early-runtimes", meta.Version, source, &PackageAttr{
Flag: TExclusive,
}, &CMakeHelper{
Append: []string{"runtimes"},
Cache: []KV{
{"ENABLE_LINKER_BUILD_ID", "ON"},
// libc++ not yet available
{"CMAKE_CXX_COMPILER_WORKS", "ON"},
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_ENABLE_RTTI", "ON"},
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
{"LLVM_LINK_LLVM_DYLIB", "ON"},
{"LLVM_ENABLE_RUNTIMES", "'libunwind;libcxx;libcxxabi'"},
{"LIBUNWIND_ENABLE_ASSERTIONS", "OFF"},
{"LIBUNWIND_USE_COMPILER_RT", "ON"},
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
{"LIBCXX_USE_COMPILER_RT", "ON"},
{"LIBCXX_CXX_ABI", "libcxxabi"},
{"LIBCXX_ENABLE_STATIC_ABI_LIBRARY", "OFF"},
{"LIBCXX_HARDENING_MODE", "fast"},
{"LIBCXX_HAS_ATOMIC_LIB", "OFF"},
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
{"LIBCXXABI_ENABLE_STATIC_UNWINDER", "OFF"},
{"LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL", "OFF"},
{"LLVM_ENABLE_ZLIB", "FORCE_ON"},
{"LLVM_ENABLE_ZSTD", "FORCE_ON"},
{"LLVM_ENABLE_LIBXML2", "OFF"},
},
SkipTest: true,
},
_python,
_zlib,
_zstd,
_earlyCompilerRT,
_kernelHeaders,
)
})
const (
version = "22.1.7"
checksum = "GFjsoTzJ72YWQuAaNmlO67IIkoZ8Z12u3n0dOEMSpltmyXUJp8e3cccWDrscXILZ"
)
native.MustRegister("llvm-project", func(t Toolchain) (*Metadata, pkg.Artifact) {
meta := Metadata{
Name: "llvm-project",
Description: "LLVM monorepo with Rosa OS patches",
Version: version,
ID: 1830,
}
return &meta, t.NewPatchedSource("llvm-"+version, newFromGitHub(
"llvm/llvm-project",
"llvmorg-"+version,
checksum,
), true, llvmPatches...)
})
native.MustRegister("llvm", func(t Toolchain) (*Metadata, pkg.Artifact) {
meta := Metadata{
Name: "llvm",
@@ -244,9 +83,11 @@ ln -s \
{"LIBCXX_ENABLE_STATIC_ABI_LIBRARY", "OFF"},
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
{"LIBCXX_HARDENING_MODE", "fast"},
{"LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY", "ON"},
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
{"LIBCXXABI_ENABLE_STATIC_UNWINDER", "OFF"},
{"LIBCXXABI_ENABLE_STATIC_UNWINDER", "ON"},
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
{"LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY", "ON"},
{"LLVM_INSTALL_BINUTILS_SYMLINKS", "ON"},
{"LLVM_INSTALL_UTILS", "ON"},
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
@@ -299,6 +140,10 @@ ln -s \
"CodeGen/PowerPC/ppc-tmmintrin.c",
"CodeGen/PowerPC/ppc-smmintrin.c",
"CodeGenCUDA/amdgpu-alias-undef-symbols.cu",
// clang: deadlocks with LIBCXXABI_ENABLE_STATIC_UNWINDER
"global-value-regex",
"global-hex-value-regex",
"check-globals",
// cxx: fails on musl
"close.dont-get-rid-of-buffer",
"re/re.traits",
@@ -339,8 +184,19 @@ ln -s \
}...)
}
return &meta, t.NewPackage("llvm", meta.Version, source, &PackageAttr{
Flag: TExclusive,
return &meta, t.New("llvm", meta.Version, source, &PackageAttr{
Exclusive: true,
Bin: []string{
"chmod",
"mkdir",
"rm",
"tr",
"awk",
},
ScriptEarly: `
rm -f /system/bin/clang++.cfg
`,
}, &CMakeHelper{
Append: []string{"llvm"},
@@ -350,6 +206,10 @@ ln -s ld.lld /work/system/bin/ld
ln -s clang /work/system/bin/cc
ln -s clang /work/system/bin/cpp
ln -s clang++ /work/system/bin/c++
cat << EOF > /work/system/bin/clang++.cfg
-static-libstdc++
-Wl,--exclude-libs,libunwind.a:libc++.a:libc++experimental.a:libc++abi.a
EOF
`,
// LLVM_LINK_LLVM_DYLIB causes llvm test suite to leak system
@@ -358,22 +218,13 @@ ln -s clang++ /work/system/bin/c++
// on 3-stage determinism to test later stages.
SkipTest: t.stage.isStage0(),
Test: `
chmod +w /bin && ln -s \
../system/bin/chmod \
../system/bin/mkdir \
../system/bin/rm \
../system/bin/tr \
../system/bin/awk \
/bin
ninja ` + jobsFlagE + ` check-all
`,
Test: "ninja " + jobsFlagE + " " + loadFlagE + " check-all",
},
_python,
_pythonEarly,
_perl,
_diffutils,
_bash,
_gawk,
_awk,
_coreutils,
_findutils,
+1 -1
View File
@@ -8,7 +8,7 @@ import (
)
func TestLLVMInputs(t *testing.T) {
const wantInputCount = 553
const wantInputCount = 470
_, llvm := rosa.Native().Std().MustLoad(rosa.H("llvm"))
var n int
+13 -9
View File
@@ -52,15 +52,16 @@ type MakeHelper struct {
var _ Helper = new(MakeHelper)
// extra returns make and other optional dependencies.
func (attr *MakeHelper) extra(flag int) P {
extra := P{_make}
if (attr == nil || !attr.OmitDefaults) && flag&TEarly == 0 {
extra = append(extra,
_gawk,
func (attr *MakeHelper) extra() P {
if attr == nil || !attr.OmitDefaults {
return P{
_make,
_awk,
_coreutils,
)
}
}
return extra
return P{_make}
}
// wantsChmod returns whether the build system needs to be generated.
@@ -89,7 +90,7 @@ func (attr *MakeHelper) wantsDir() (string, bool) {
if attr != nil && attr.InPlace {
return helperInPlace, false
}
return `"$(mktemp -d)"`, false
return "/cure/", true
}
// script generates the cure script.
@@ -160,7 +161,8 @@ func (attr *MakeHelper) script(t Toolchain, name string) string {
scriptMake := `
make \
` + jobsFlagE
` + jobsFlagE + ` \
` + loadFlagE
if len(attr.Make) > 0 {
scriptMake += " \\\n\t" + strings.Join(attr.Make, " \\\n\t")
}
@@ -170,6 +172,8 @@ make \
(!attr.SkipCheckEarly || !t.stage.isStage0()) {
scriptMake += attr.ScriptCheckEarly + `make \
` + jobsFlagE + ` \
` + loadFlagE + ` \
AM_COLOR_TESTS=always \
`
if len(attr.Check) > 0 {
scriptMake += strings.Join(attr.Check, " \\\n\t")
+50 -15
View File
@@ -5,10 +5,16 @@ import (
"strings"
)
var _meson = H("meson")
var (
_muon = H("muon")
_meson = H("meson")
)
// MesonHelper builds and tests a meson project.
type MesonHelper struct {
// Use muon instead of meson.
Muon bool
// Runs after setup.
ScriptCompileEarly string
// Runs after compile.
@@ -18,6 +24,8 @@ type MesonHelper struct {
// Flags passed to the setup command.
Setup []KV
// Test suites to skip.
SkipTests []string
// Whether to skip meson test.
SkipTest bool
// Run tests with interactive input/output.
@@ -27,7 +35,12 @@ type MesonHelper struct {
var _ Helper = new(MesonHelper)
// extra returns hardcoded meson runtime dependencies.
func (*MesonHelper) extra(int) P { return P{_meson} }
func (attr *MesonHelper) extra() P {
if !attr.isPython() {
return P{_muon}
}
return P{_meson}
}
// wantsChmod returns false.
func (*MesonHelper) wantsChmod() bool { return false }
@@ -41,6 +54,12 @@ func (*MesonHelper) scriptEarly() string { return "" }
// wantsDir requests a new directory in TMPDIR.
func (*MesonHelper) wantsDir() (string, bool) { return `"$(mktemp -d)"`, false }
// isPython returns whether the legacy python implementation is used.
func (attr *MesonHelper) isPython() bool {
return attr == nil ||
!attr.Muon || len(attr.SkipTests) != 0 || attr.InteractiveTest
}
// script generates the cure script.
func (attr *MesonHelper) script(t Toolchain, name string) string {
if attr == nil {
@@ -52,41 +71,57 @@ func (attr *MesonHelper) script(t Toolchain, name string) string {
scriptCompiled = "\n" + scriptCompiled
}
python := attr.isPython()
muon := "muon"
compile := " samu " + jobsFlagE
destdir := "-d"
if python {
muon = "meson"
compile = " compile " + jobsFlagE + " " + loadFlagE
destdir = "--destdir"
}
var scriptTest string
if !attr.SkipTest && t.opts&OptSkipCheck == 0 {
scriptTest = `
meson test \
` + muon + ` test \
` + jobsFlagE + ` \
-t 10`
if python {
scriptTest += ` \
--print-errorlogs`
} else {
scriptTest += " -Rv"
}
if attr.InteractiveTest {
scriptTest += ` \
--interactive`
}
for _, suite := range attr.SkipTests {
scriptTest += " \\\n\t--no-suite='" + suite + "'"
}
}
return `
cd "$(mktemp -d)"
meson setup \
` + muon + ` setup \
` + strings.Join(slices.Collect(func(yield func(string) bool) {
for _, v := range append([]KV{
{"wrap-mode", "nofallback"},
{"wrap_mode", "nofallback"},
{"prefix", "/system"},
{"buildtype", "release"},
}, attr.Setup...) {
s := "-" + v[0]
if len(v[0]) > 0 && v[0][0] != 'D' {
s = "-" + s
}
s := v[0]
if v[1] != "" {
s += "=" + v[1]
s = "-D" + s + "=" + v[1]
}
if !yield(s) {
return
}
}
}), " \\\n\t") + ` \
. '/usr/src/` + name + `'
meson compile` + scriptCompiled + scriptTest + `
meson install \
--destdir=/work
'/usr/src/` + name + `'
` + muon + compile + scriptCompiled + scriptTest + `
` + muon + ` install \
` + destdir + ` /work
` + attr.Script
}
+256 -113
View File
@@ -14,6 +14,7 @@ import (
"path/filepath"
"strconv"
"strings"
"syscall"
"unique"
"hakurei.app/internal/pkg"
@@ -30,8 +31,8 @@ type Remote struct {
c *http.Client
}
// NewRemote returns a populated [Remote]
func NewRemote(base string, pub ed25519.PublicKey, c *http.Client) (Remote, error) {
// NewRemote returns a populated [Remote].
func NewRemote(c *http.Client, base string, pub ed25519.PublicKey) (Remote, error) {
u, err := url.Parse(base)
return Remote{u, pub, c}, err
}
@@ -201,14 +202,261 @@ func (r Remote) Status(
), nil
}
// NewMirror returns an [http.Handler] for servicing mirror requests.
// Mirror services requests made by [Remote].
type Mirror struct {
// Cache on-filesystem format.
fsys fs.FS
// Signs payloads.
key ed25519.PrivateKey
// Verbose output.
msg message.Msg
}
// Populate fills an empty root with a static mirror snapshot.
func (m Mirror) Populate(root *os.Root) error {
if dents, err := fs.ReadDir(root.FS(), "."); err != nil {
return err
} else if len(dents) > 0 {
return syscall.ENOTEMPTY
}
for _, name := range []string{
dirArtifact,
dirOutcome,
dirStatus,
} {
if err := root.Mkdir(name, 0755); err != nil {
return err
}
}
var w *os.File
if dents, err := fs.ReadDir(m.fsys, "identifier"); err != nil {
return err
} else {
for _, dent := range dents {
name := dent.Name()
var buf [2 * len(pkg.Checksum{})]byte
if err = pkg.Decode(
(*pkg.Checksum)(buf[:len(pkg.Checksum{})]),
name,
); err != nil {
return err
}
if w, err = root.OpenFile(
filepath.Join(dirArtifact, name),
syscall.O_WRONLY|syscall.O_CREAT|syscall.O_EXCL,
0444,
); err != nil {
return err
}
err = m.writeArtifact(&buf, w, nil)
if err = errors.Join(err, w.Close()); err != nil {
return err
}
}
}
if dents, err := fs.ReadDir(m.fsys, "checksum"); err != nil {
return err
} else {
for _, dent := range dents {
name := dent.Name()
var buf pkg.Checksum
if err = pkg.Decode(&buf, name); err != nil {
return err
}
var fsys fs.FS
fsys, err = fs.Sub(m.fsys, filepath.Join("checksum", name))
if err != nil {
return err
}
if w, err = root.OpenFile(
filepath.Join(dirOutcome, name),
syscall.O_WRONLY|syscall.O_CREAT|syscall.O_EXCL,
0444,
); err != nil {
return err
}
m.msg.Verbosef("exporting outcome %s", name)
err = pkg.Write(fsys, ".", w)
if err = errors.Join(err, w.Close()); err != nil {
return err
}
}
}
if dents, err := fs.ReadDir(m.fsys, "status"); err != nil {
return err
} else {
for _, dent := range dents {
name := dent.Name()
var buf [2 * len(pkg.Checksum{})]byte
if err = pkg.Decode(
(*pkg.Checksum)(buf[:len(pkg.Checksum{})]),
name,
); err != nil {
return err
}
if w, err = root.OpenFile(
filepath.Join(dirStatus, name),
syscall.O_WRONLY|syscall.O_CREAT|syscall.O_EXCL,
0444,
); err != nil {
return err
}
err = m.writeStatus(&buf, w, nil)
if err = errors.Join(err, w.Close()); err != nil {
return err
}
}
}
return nil
}
// NewMirror returns a populated [Mirror] for servicing mirror requests.
func NewMirror(
msg message.Msg,
fsys fs.FS,
key ed25519.PrivateKey,
) http.Handler {
) Mirror {
return Mirror{fsys, key, msg}
}
// writeArtifact writes a signed dirArtifact response.
func (m Mirror) writeArtifact(
buf *[2 * len(pkg.Checksum{})]byte,
w io.Writer,
header http.Header,
) error {
ids := pkg.Encode((pkg.Checksum)(buf[:len(pkg.Checksum{})]))
if linkname, err := fs.ReadLink(m.fsys, filepath.Join(
"identifier",
ids,
)); err != nil {
return err
} else if err = pkg.Decode(
(*pkg.Checksum)(buf[len(pkg.Checksum{}):]),
filepath.Base(linkname),
); err != nil {
return err
}
m.msg.Verbosef("serving artifact %s", ids)
if header != nil {
header.Set(
"Content-Length",
strconv.Itoa(ed25519.SignatureSize+len(buf)),
)
}
_, err := w.Write(append(ed25519.Sign(m.key, buf[:]), buf[:]...))
return err
}
// writeOutcome writes a dirOutcome response.
func (m Mirror) writeOutcome(
buf *pkg.Checksum,
w io.Writer,
header http.Header,
) error {
checksums := pkg.Encode(*buf)
rel := filepath.Join("checksum", checksums)
if _, err := fs.Lstat(m.fsys, rel); err != nil {
return err
}
m.msg.Verbosef("serving outcome %s", checksums)
_fsys, err := fs.Sub(m.fsys, rel)
if err != nil {
return err
}
var gw *gzip.Writer
if gw, err = gzip.NewWriterLevel(w, gzip.BestCompression); err != nil {
return err
}
if header != nil {
header.Set("Content-Encoding", "gzip")
}
if err = pkg.Write(_fsys, ".", gw); err != nil {
_ = gw.Close()
return err
}
return gw.Close()
}
// writeStatus writes a signed dirStatus response.
func (m Mirror) writeStatus(
buf *[2 * len(pkg.Checksum{})]byte,
w io.Writer,
_ http.Header,
) error {
ids := pkg.Encode((pkg.Checksum)(buf[:len(pkg.Checksum{})]))
f, err := m.fsys.Open(filepath.Join(
"status",
ids,
))
if err != nil {
return err
}
s, ok := f.(io.Seeker)
if !ok {
return &fs.PathError{Op: "seek", Path: ids, Err: fs.ErrInvalid}
}
m.msg.Verbosef("serving status %s", ids)
h := sha512.New384()
if _, err = io.Copy(h, f); err != nil {
_ = f.Close()
return err
}
h.Sum(buf[len(pkg.Checksum{}):len(pkg.Checksum{})])
if _, err = w.Write(append(ed25519.Sign(m.key, buf[:]), buf[:]...)); err != nil {
_ = f.Close()
return err
} else if _, err = s.Seek(0, io.SeekStart); err != nil {
_ = f.Close()
return err
} else if _, err = io.Copy(w, f); err != nil {
_ = f.Close()
return err
}
return f.Close()
}
// writeF is a helper for writing a mirror response with error handling.
func writeF[B any](
m Mirror,
w http.ResponseWriter,
buf B,
f func(
buf B,
w io.Writer,
header http.Header,
) error,
) {
err := f(buf, w, w.Header())
if err == nil {
return
}
if errors.Is(err, os.ErrNotExist) {
w.WriteHeader(http.StatusNotFound)
return
}
m.msg.GetLogger().Println(err)
w.WriteHeader(http.StatusInternalServerError)
}
// Register configures an [http.ServeMux] for servicing mirror requests.
func (m Mirror) Register(mux *http.ServeMux) {
const identName = "ident"
var mux http.ServeMux
mux.HandleFunc("/"+dirArtifact+"/{"+identName+"}", func(
w http.ResponseWriter,
@@ -222,38 +470,7 @@ func NewMirror(
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ids := pkg.Encode((pkg.Checksum)(buf[:len(pkg.Checksum{})]))
if linkname, err := fs.ReadLink(fsys, filepath.Join(
"identifier",
ids,
)); err != nil {
if errors.Is(err, os.ErrNotExist) {
w.WriteHeader(http.StatusNotFound)
return
}
msg.GetLogger().Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
} else if err = pkg.Decode(
(*pkg.Checksum)(buf[len(pkg.Checksum{}):]),
filepath.Base(linkname),
); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
msg.Verbosef("serving artifact %s", ids)
w.Header().Set(
"Content-Length",
strconv.Itoa(ed25519.SignatureSize+len(buf)),
)
if _, err := w.Write(append(
ed25519.Sign(key, buf[:]),
buf[:]...,
)); err != nil {
msg.Verbose(err)
}
writeF(m, w, &buf, m.writeArtifact)
})
mux.HandleFunc("/"+dirOutcome+"/{"+identName+"}", func(
@@ -273,40 +490,7 @@ func NewMirror(
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
checksums := pkg.Encode(buf)
rel := filepath.Join("checksum", checksums)
if _, err := fs.Lstat(fsys, rel); err != nil {
if errors.Is(err, os.ErrNotExist) {
w.WriteHeader(http.StatusNotFound)
return
}
msg.GetLogger().Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
msg.Verbosef("serving outcome %s", pkg.Encode(buf))
_fsys, err := fs.Sub(fsys, rel)
if err != nil {
msg.GetLogger().Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
var gw *gzip.Writer
if gw, err = gzip.NewWriterLevel(w, gzip.BestCompression); err != nil {
msg.GetLogger().Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Encoding", "gzip")
if err = pkg.Write(_fsys, ".", gw); err != nil {
msg.Verbose(err)
}
if err = gw.Close(); err != nil {
msg.GetLogger().Println(err)
}
writeF(m, w, &buf, m.writeOutcome)
})
mux.HandleFunc("/"+dirStatus+"/{"+identName+"}", func(
@@ -321,47 +505,6 @@ func NewMirror(
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ids := pkg.Encode((pkg.Checksum)(buf[:len(pkg.Checksum{})]))
f, err := fsys.Open(filepath.Join(
"status",
ids,
))
if err != nil {
if errors.Is(err, os.ErrNotExist) {
w.WriteHeader(http.StatusNotFound)
return
}
msg.GetLogger().Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
s, ok := f.(io.Seeker)
if !ok {
msg.GetLogger().Println("backing filesystem does not support seek")
w.WriteHeader(http.StatusInternalServerError)
return
}
msg.Verbosef("serving status %s", ids)
h := sha512.New384()
if _, err = io.Copy(h, f); err != nil {
_ = f.Close()
msg.Verbose(err)
w.WriteHeader(http.StatusInternalServerError)
}
h.Sum(buf[len(pkg.Checksum{}):len(pkg.Checksum{})])
if _, err = w.Write(append(ed25519.Sign(key, buf[:]), buf[:]...)); err != nil {
msg.Verbose(err)
return
} else if _, err = s.Seek(0, io.SeekStart); err != nil {
msg.GetLogger().Println(err)
return
} else if _, err = io.Copy(w, f); err != nil {
msg.Verbose(err)
return
}
writeF(m, w, &buf, m.writeStatus)
})
return &mux
}
+7 -4
View File
@@ -4,6 +4,7 @@ import (
"crypto/ed25519"
"io/fs"
"log"
"net/http"
"net/http/httptest"
"os"
"testing"
@@ -30,7 +31,7 @@ func TestMirror(t *testing.T) {
msg.SwapVerbose(testing.Verbose())
var c *pkg.Cache
c, err = pkg.Open(t.Context(), msg, 0, 0, 0, base)
c, err = pkg.Open(t.Context(), msg, base, nil)
if err != nil {
t.Fatal(err)
}
@@ -52,14 +53,16 @@ func TestMirror(t *testing.T) {
}
wantChecksums := pkg.Encode(wantChecksum)
server := httptest.NewServer(rosa.NewMirror(msg, fstest.MapFS{
var mux http.ServeMux
rosa.NewMirror(msg, fstest.MapFS{
"identifier/" + ids: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantChecksums)},
"checksum/" + wantChecksums: {Mode: os.ModeDir | 0500},
}, priv))
}, priv).Register(&mux)
server := httptest.NewServer(&mux)
t.Cleanup(server.Close)
var extern pkg.External
extern, err = rosa.NewRemote("http://example.com:80", pub, server.Client())
extern, err = rosa.NewRemote(server.Client(), "http://example.com:80", pub)
if err != nil {
t.Fatal(err)
}
@@ -1,26 +0,0 @@
From 8a80d895dfd779373363c3a4b62ecce5a549efb2 Mon Sep 17 00:00:00 2001
From: "Haelwenn (lanodan) Monnier" <contact@hacktivis.me>
Date: Sat, 30 Mar 2024 10:17:10 +0100
Subject: tools/attr.c: Add missing libgen.h include for basename(3)
Fixes compilation issue with musl and modern C99 compilers.
See: https://bugs.gentoo.org/926294
---
tools/attr.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/attr.c b/tools/attr.c
index f12e4af..6a3c1e9 100644
--- a/tools/attr.c
+++ b/tools/attr.c
@@ -28,6 +28,7 @@
#include <errno.h>
#include <string.h>
#include <locale.h>
+#include <libgen.h>
#include <attr/attributes.h>
--
cgit v1.1
+4 -4
View File
@@ -1,7 +1,7 @@
diff --git a/test/attr.test b/test/attr.test
index 6ce2f9b..e9bde92 100644
--- a/test/attr.test
+++ b/test/attr.test
diff --git a/test/attr.run b/test/attr.run
index 27d17f6..a4d60c0 100644
--- a/test/attr.run
+++ b/test/attr.run
@@ -11,7 +11,7 @@ Try various valid and invalid names
$ touch f
+13 -13
View File
@@ -3,25 +3,25 @@ package attr {
website = "https://savannah.nongnu.org/projects/attr";
anitya = 137;
version# = "2.5.2";
version# = "2.6.0";
source = remoteTar {
url = "https://download.savannah.nongnu.org/releases/attr/"+
"attr-"+version+".tar.gz";
checksum = "YWEphrz6vg1sUMmHHVr1CRo53pFXRhq_pjN-AlG8UgwZK1y6m7zuDhxqJhD0SV0l";
checksum = "pp-NvD1cMIwZycNwZGW2ez-PbTEpHxrRnVH27csj9QdN4oEBkEbJOZX1IIvKnTWS";
compress = gzip;
};
patches = [
"libgen-basename.patch",
"musl-errno.patch",
];
early = `
ln -s ../../system/bin/perl /usr/bin
`;
patches = [ "musl-errno.patch" ];
bin = [ "perl" ];
populateUsrBin = true;
exec = make {};
inputs = [ perl ];
inputs = [
perl,
kernel-headers,
];
}
package acl {
@@ -29,11 +29,11 @@ package acl {
website = "https://savannah.nongnu.org/projects/acl";
anitya = 16;
version# = "2.3.2";
version# = "2.4.0";
source = remoteTar {
url = "https://download.savannah.nongnu.org/releases/acl/"+
"acl-"+version+".tar.gz";
checksum = "-fY5nwH4K8ZHBCRXrzLdguPkqjKI6WIiGu4dBtrZ1o0t6AIU73w8wwJz_UyjIS0P";
checksum = "U2eaAsWrhhzEfhyprwHQQG55bFPZxtsHk1Usnd9Jb_g-H__pJod4H3RTrL4ipXDw";
compress = gzip;
};
@@ -42,6 +42,6 @@ package acl {
skipCheck = true;
};
inputs = [ attr ];
inputs = [ attr, kernel-headers ];
runtime = [ attr ];
}
+31
View File
@@ -0,0 +1,31 @@
package awk {
description = "one true awk";
website = "https://github.com/onetrueawk/awk";
anitya = 16171;
version# = "20260426";
source = remoteGitHub {
suffix = "onetrueawk/awk";
tag = version;
checksum = "ewAvWLEHajhm7cA7v4DsKVk1c11niCLKIE5Q-8W_sxv1XXsbZlcOuWn1KOBYMxjo";
};
enterSource = true;
writable = true;
chmod = true;
exec = make {
omitDefaults = true;
inPlace = true;
skipConfigure = true;
make = [ "YACC='yacc -d -b awkgram'" ];
preCheck = "install -vD a.out /system/bin/awk\n";
install = "install -vD a.out /work/system/bin/awk";
};
inputs = [
m4,
byacc,
diffutils,
];
}
+6 -6
View File
@@ -5,15 +5,19 @@ package bison {
version# = "3.8.2";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/bison/bison-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/bison/bison-"+version+".tar.gz";
checksum = "BhRM6K7URj1LNOkIDCFDctSErLS-Xo5d9ba9seg10o6ACrgC1uNhED7CQPgIY29Y";
compress = gzip;
};
toyboxEarly = true;
exec = make {
omitDefaults = true;
check = [
"TESTSUITEFLAGS=" + jobsFlagE + "' " + skipGNUTests {
tests = [
// GNU-isms not implemented in toybox
168, 170, 623,
// clang miscompiles (SIGILL)
764,
];
@@ -22,9 +26,5 @@ package bison {
];
};
inputs = [
m4,
diffutils,
sed,
];
inputs = [ m4 ];
}
+24
View File
@@ -0,0 +1,24 @@
package byacc {
description = "Berkeley Yacc";
website = "https://invisible-island.net/byacc";
anitya = 233;
version# = "20260126";
source = remoteTar {
url = "https://invisible-island.net/archives/byacc/"+
"byacc-"+version+".tgz";
compress = gzip;
checksum = "3IXzewZmFUW3hkFKBuweR0hUSftlI2zE0lBZf16I8oK3mFEyj51FzVv1wvA12uoC";
};
// awk dependency loop
toyboxEarly = true;
// test suite assumes writable source
writable = true;
chmod = true;
exec = make {
omitDefaults = true;
};
}
+10 -10
View File
@@ -13,16 +13,16 @@ package cairo {
exec = meson {
setup = {
"Ddwrite": "enabled";
"Dfontconfig": "enabled";
"Dfreetype": "enabled";
"dwrite": "enabled";
"fontconfig": "enabled";
"freetype": "enabled";
"Dpng": "enabled";
"Dtee": "enabled";
"Dxcb": "enabled";
"Dxlib": "disabled";
"Dxlib-xcb": "disabled";
"Dzlib": "enabled";
"png": "enabled";
"tee": "enabled";
"xcb": "enabled";
"xlib": "disabled";
"xlib-xcb": "disabled";
"zlib": "enabled";
};
// runs the entire test suite in a single meson test
interactiveTest = true;
@@ -31,7 +31,7 @@ package cairo {
};
inputs = [
gawk,
awk,
zlib,
libpng,
@@ -1,13 +0,0 @@
diff --git a/Tests/BootstrapTest.cmake b/Tests/BootstrapTest.cmake
index 137de78bc1..b4da52e664 100644
--- a/Tests/BootstrapTest.cmake
+++ b/Tests/BootstrapTest.cmake
@@ -9,7 +9,7 @@ if(NOT nproc EQUAL 0)
endif()
message(STATUS "running bootstrap: ${bootstrap} ${ninja_arg} ${parallel_arg}")
execute_process(
- COMMAND ${bootstrap} ${ninja_arg} ${parallel_arg}
+ COMMAND ${bootstrap} ${ninja_arg} ${parallel_arg} -- -DCMAKE_USE_OPENSSL=OFF
WORKING_DIRECTORY "${bin_dir}"
RESULT_VARIABLE result
)
+4 -6
View File
@@ -3,18 +3,15 @@ package cmake {
website = "https://cmake.org";
anitya = 306;
version# = "4.3.3";
version# = "4.4.2";
source = remoteGitHubRelease {
suffix = "Kitware/CMake";
tag = "v"+version;
name = "cmake-"+version+".tar.gz";
checksum = "VS-b6cN4S9hfNv3JOUAbAfI9nh3EeuVwY_IVgUdgq6VKwvfchhXwvvFAUcpZG6Ez";
checksum = "IWlqJqJCZ6f-z-7Ft1U4ycvCX4riuihKale5NKWusiHemBgC3m5gCecrzikXoL7S";
compress = gzip;
};
patches = [
"bootstrap-test-no-openssl.patch",
"disable-broken-tests-musl.patch",
];
patches = [ "disable-broken-tests-musl.patch" ];
// test suite expects writable source tree
writable = true;
@@ -32,6 +29,7 @@ package cmake {
"--";
"-DCMAKE_USE_OPENSSL": "OFF";
"-DCMake_TEST_NO_NETWORK": "ON";
"-DCMake_TEST_BOOTSTRAP": "OFF";
};
check = [
+2 -2
View File
@@ -3,10 +3,10 @@ package curl {
website = "https://curl.se";
anitya = 381;
version# = "8.20.0";
version# = "8.21.0";
source = remoteTar {
url = "https://curl.se/download/curl-"+version+".tar.bz2";
checksum = "xyHXwrngIRGMasuzhn-I5MSCOhktwINbsWt1f_LuR-5jRVvyx_g6U1EQfDLEbr9r";
checksum = "lJSm8bVjS0OmsarEdbvejdQdvXsb7yGarlr6oMtA9FW1EXOga8zZxa1LPtfaq_qX";
compress = bzip2;
};
+4 -4
View File
@@ -19,9 +19,9 @@ package dbus {
exec = meson {
setup = {
"Depoll": "enabled";
"Dinotify": "enabled";
"Dx11_autolaunch": "disabled";
"epoll": "enabled";
"inotify": "enabled";
"x11_autolaunch": "disabled";
};
};
@@ -50,7 +50,7 @@ package xdg-dbus-proxy {
exec = meson {
setup = {
"Dman": "disabled";
"man": "disabled";
};
};
+1 -1
View File
@@ -18,7 +18,7 @@ package dtc {
exec = meson {
setup = {
"Dyaml": "disabled";
"yaml": "disabled";
};
};
+3 -2
View File
@@ -5,8 +5,9 @@ package fcft {
version# = "3.3.3";
source = remoteTar {
url = "https://codeberg.org/dnkl/fcft/archive/"+version+".tar.gz";
checksum = "bMj8OmqtoANRKZWbjHk4WfP09AxJYRbWGqUsm1gRJ_dOFg6gooNbgkDu597PLfz2";
url = "https://codeberg.org/dnkl/fcft/releases/download/"+version+
"/fcft-"+version+".tar.gz";
checksum = "pryAJA-d1OpY8KXbGFEHum9Wm6ME9XkPx9EM_OQ_ZEpOUpQnqlkzIq-cwS1ziMPk";
compress = gzip;
};
+3 -3
View File
@@ -3,12 +3,12 @@ package firmware {
website = "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git";
anitya = 141464;
version# = "20260519";
version# = "20260622";
source = remoteGitLab {
domain = "gitlab.com";
suffix = "kernel-firmware/linux-firmware";
ref = version;
checksum = "l-wBRTWclYnJsgV4qtUV1-UL5Y4nknAPre8CMe0dH7PxtAqbaeudEIM_Fnuj0TCV";
checksum = "gpytkDM58EVjaUuryOekcekh_rWsfuv3S7LQxopHlNlVGmMsuqNwfug4BjgTgizE";
};
// dedup creates temporary file
@@ -34,7 +34,7 @@ package firmware {
// requires pre-commit
skipCheck = true;
install = "make " + jobsFlagE + " DESTDIR=/work/system dedup";
install = "make " + jobsFlagE + " " + loadFlagE + " DESTDIR=/work/system dedup";
};
inputs = [
+2 -2
View File
@@ -3,12 +3,12 @@ package fontconfig {
website = "https://www.freedesktop.org/wiki/Software/fontconfig";
anitya = 827;
version# = "2.18.1";
version# = "2.18.2";
source = remoteGitLab {
domain = "gitlab.freedesktop.org";
suffix = "fontconfig/fontconfig";
ref = version;
checksum = "S3FJfh-PeZ2_YgNrUqL0H2G4Wf_ilj5HpIGV2oURnkK672AQHpWk526bNtRHwyJt";
checksum = "P8YoQunIynBhc3gdDyPkImw_GGYoy1U4aX0jTnpkgtLmU4nqIgUyeqCH3-rNzpTd";
};
exec = make {
+3 -2
View File
@@ -5,8 +5,9 @@ package foot {
version# = "1.27.0";
source = remoteTar {
url = "https://codeberg.org/dnkl/foot/archive/"+version+".tar.gz";
checksum = "E2XIPRD8t-WBBJUebIwChFT8K_85diwdalssUNwnuZBIynPa7rlXro5WCe9v3UlK";
url = "https://codeberg.org/dnkl/foot/releases/download/"+version+
"/foot-"+version+".tar.gz";
checksum = "22rG3rMuQI8Ae2XTcZgOJ-6AbF7Taex8XpgvD6Fyg1Mn5Va67FfUcK3tRaq61TFg";
compress = gzip;
};
+1 -1
View File
@@ -12,7 +12,7 @@ package fribidi {
exec = meson {
setup = {
"Ddocs": "false";
"docs": "false";
};
};
}
+4 -4
View File
@@ -14,10 +14,10 @@ package fuse {
exec = meson {
setup = {
"Ddefault_library": "both";
"Dtests": "true";
"Duseroot": "false";
"Dinitscriptdir": "/system/etc";
"default_library": "both";
"tests": "true";
"useroot": "false";
"initscriptdir": "/system/etc";
};
postCompile = "python3 -m pytest test/";
@@ -0,0 +1,35 @@
diff --git a/test/Makefile.am b/test/Makefile.am
index 88e15ef1f..bfc279fcb 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1726,7 +1726,7 @@ LOCALE_CHARSET_TESTS = \
SHLIB_TESTS = \
apiterm filefuncs fnmatch fork fork2 fts functab4 functab5 \
getfile indirectbuiltin2 inplace1 inplace2 inplace2bcomp inplace3 \
- inplace3bcomp ordchr ordchr2 readall readdir readdir_retest \
+ inplace3bcomp ordchr ordchr2 readall readdir_retest \
readdir_test readfile readfile2 revout revtwoway rwarray \
testext time
diff --git a/test/Makefile.in b/test/Makefile.in
index 2d4eeaa5a..7930af8d5 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -1986,7 +1986,7 @@ LOCALE_CHARSET_TESTS = \
SHLIB_TESTS = \
apiterm filefuncs fnmatch fork fork2 fts functab4 functab5 \
getfile indirectbuiltin2 inplace1 inplace2 inplace2bcomp inplace3 \
- inplace3bcomp ordchr ordchr2 readall readdir readdir_retest \
+ inplace3bcomp ordchr ordchr2 readall readdir_retest \
readdir_test readfile readfile2 revout revtwoway rwarray \
testext time
diff --git a/test/clos1way6.ok b/test/clos1way6.ok
index 5768617d3..be4d73e79 100644
--- a/test/clos1way6.ok
+++ b/test/clos1way6.ok
@@ -1,3 +1,3 @@
gawk: clos1way6.awk:5: warning: fflush: cannot flush: two-way pipe `cat - 1>&2; sleep 2' has closed write end
-test1
Bad file descriptor
+test1
@@ -0,0 +1,39 @@
diff --git a/test/testext-mpfr.ok b/test/testext-mpfr.ok
index 6a5f98147..adf8685e2 100644
--- a/test/testext-mpfr.ok
+++ b/test/testext-mpfr.ok
@@ -21,7 +21,7 @@ var_test: sym_update of ARGC failed - correctly
var_test: sym_update("testvar") succeeded
var_test() returned 1, test_var = 42
-test_errno() returned 1, ERRNO = No child processes
+test_errno() returned 1, ERRNO = No child process
fubar = 9
rumpus = -5
diff --git a/test/testext.ok b/test/testext.ok
index 3e0c1328c..11d150fe3 100644
--- a/test/testext.ok
+++ b/test/testext.ok
@@ -21,7 +21,7 @@ var_test: sym_update of ARGC failed - correctly
var_test: sym_update("testvar") succeeded
var_test() returned 1, test_var = 42
-test_errno() returned 1, ERRNO = No child processes
+test_errno() returned 1, ERRNO = No child process
fubar = 9
rumpus = -5
diff --git a/vms/vmstest.com b/vms/vmstest.com
index a042764b1..c47984e38 100644
--- a/vms/vmstest.com
+++ b/vms/vmstest.com
@@ -917,7 +917,7 @@ $ set noOn
$ AWKLIBPATH_dir
$ gawk -f _'test'.awk >_'test'.tmp 2>&1
$ if .not. $status then call exit_code '$status' _'test'.tmp
-$ gawk "{gsub(""no children"",""No child processes"")}1" -
+$ gawk "{gsub(""no children"",""No child process"")}1" -
_'test'.tmp >_'test'.tmp1
$ rm sys$disk:[]_'test'.tmp;*
$ mv sys$disk:[]_'test'.tmp1 sys$disk:[]_'test'.tmp
+26
View File
@@ -0,0 +1,26 @@
package gawk {
description = "an implementation of awk with GNU extensions";
website = "https://www.gnu.org/software/gawk";
anitya = 868;
block = "regressions introduced in 5.4.1, "+
"does not even pass its own test suite";
version# = "5.4.0";
source = remoteTar {
url = "https://mirrors.kernel.org/gnu/gawk/gawk-"+version+".tar.gz";
checksum = "m0RkIolC-PI7EY5q8pcx5Y-0twlIW0Yp3wXXmV-QaHorSdf8BhZ7kW9F8iWomz0C";
compress = gzip;
};
patches = [
"musl-errno.patch",
"broken-tests.patch",
];
exec = make {};
inputs = [
diffutils,
util-linux,
];
}
+4 -3
View File
@@ -3,10 +3,10 @@ package binutils {
website = "https://www.gnu.org/software/binutils";
anitya = 7981;
version# = "2.46.1";
version# = "2.47";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/binutils/binutils-"+version+".tar.bz2";
checksum = "ihCVohBxX-URAR-YFDdVrL3inLYsEVX8KbbQmcbHaShHgqqmtsvUue1h3LXSjW-d";
url = "https://mirrors.kernel.org/gnu/binutils/binutils-"+version+".tar.bz2";
checksum = "VjbMg5KtZ6VSeNc77Z5p8RKg9eZ56g29ViKbbsF3tcFhZu0Yurg0nZt7UwB577LM";
compress = bzip2;
};
@@ -82,6 +82,7 @@ ln -s system/lib /work/
mpc,
zlib,
zstd,
libucontext,
];
}
+9 -4
View File
@@ -3,24 +3,25 @@ package git {
website = "https://www.git-scm.com";
anitya = 5350;
version# = "2.54.0";
version# = "2.55.0";
source = remoteTar {
url = "https://www.kernel.org/pub/software/scm/git/"+
"git-"+version+".tar.gz";
checksum = "7vGKtFOJGqY8DO4e8UMRax7dLgImXKQz5MMalec6MlgYrsarffSJjgOughwRFpSH";
checksum = "lOer6jb8vZQk6Nd1rLZIgsYys8whLvjJq8XbmCdTATcPFAYuQcK1Rgj1Jj6a00W8";
compress = gzip;
};
early = `
ln -s ../../system/bin/perl /usr/bin/ || true
# test suite assumes apache
rm -f /system/bin/httpd
`;
// uses source tree as scratch space
enterSource = true;
env = [ "NO_RUST=YesPlease" ];
bin = [ "perl" ];
populateUsrBin = true;
exec = make {
inPlace = true;
generate = "make configure";
@@ -59,6 +60,8 @@ disable_test t1451-fsck-buffer
disable_test t4104-apply-boundary
disable_test t4200-rerere
disable_test t5515-fetch-merge-logic
disable_test t4124-apply-ws-rule
disable_test t3404-rebase-interactive
`;
check = [
@@ -69,6 +72,7 @@ disable_test t5515-fetch-merge-logic
install = `make \
` + jobsFlagE + ` \
` + loadFlagE + ` \
DESTDIR=/work \
NO_INSTALL_HARDLINKS=1 \
install`;
@@ -85,6 +89,7 @@ disable_test t5515-fetch-merge-logic
zlib,
curl,
libexpat,
kernel-headers,
];
runtime = [
+5 -3
View File
@@ -3,11 +3,11 @@ package glib {
website = "https://developer.gnome.org/glib";
anitya = 10024;
version# = "2.89.0";
version# = "2.89.3";
source = remoteGit {
url = "https://gitlab.gnome.org/GNOME/glib.git";
tag = version;
checksum = "4FXKhdS3pC98LevYa_h7piRylG86cZ_c9zAtGr78oHodU1ob8rBxGU0hoIZ4nzcA";
checksum = "eM9KrXwhwKiZferwrILKmDeq-IGnSjr0EKqV90EEVl0Ee82QVcyVSf2LDMROHcOF";
};
files = {
@@ -17,8 +17,10 @@ package glib {
exec = meson {
setup = {
"Ddefault_library": "both";
"default_library": "both";
};
// fails with ipv6 disabled
skipTests = [ "gio" ];
};
inputs = [
+2 -2
View File
@@ -3,11 +3,11 @@ package glslang {
website = "https://github.com/KhronosGroup/glslang";
anitya = 205796;
version# = "16.3.0";
version# = "16.4.0";
source = remoteGitHub {
suffix = "KhronosGroup/glslang";
tag = version;
checksum = "xyqDf8k3-D0_BXHGi0uLgMglnJ05Rf3j73QgbDs3sGtKNdBIQhY8JfqX1NcNoJQN";
checksum = "u67ps8Fv_75QDiusvKjzgttPPPxb5V7HsObb0q6OvqQfHh0UGN2_x8Y0RKb9JEie";
};
// test suite writes to source
+55 -55
View File
@@ -7,7 +7,7 @@ package m4 {
version# = "1.4.21";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/m4/m4-"+version+".tar.bz2";
url = "https://mirrors.kernel.org/gnu/m4/m4-"+version+".tar.bz2";
checksum = "pPa6YOo722Jw80l1OsH1tnUaklnPFjFT-bxGw5iAVrZTm1P8FQaWao_NXop46-pm";
compress = bzip2;
};
@@ -17,7 +17,10 @@ package m4 {
chmod +w tests/test-c32ispunct.sh && echo '#!/bin/sh' > tests/test-c32ispunct.sh
`;
exec = make {};
toyboxEarly = true;
exec = make {
omitDefaults = true;
};
inputs = [
diffutils,
@@ -33,7 +36,7 @@ package autoconf {
version# = "2.73";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/autoconf/autoconf-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/autoconf/autoconf-"+version+".tar.gz";
checksum = "yGabDTeOfaCUB0JX-h3REYLYzMzvpDwFmFFzHNR7QilChCUNE4hR6q7nma4viDYg";
compress = gzip;
};
@@ -68,7 +71,7 @@ package automake {
version# = "1.18.1";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/automake/automake-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/automake/automake-"+version+".tar.gz";
checksum = "FjvLG_GdQP7cThTZJLDMxYpRcKdpAVG-YDs1Fj1yaHlSdh_Kx6nRGN14E0r_BjcG";
compress = gzip;
};
@@ -102,10 +105,10 @@ package libtool {
website = "https://www.gnu.org/software/libtool";
anitya = 1741;
version# = "2.5.4";
version# = "2.6.2";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/libtool/libtool-"+version+".tar.gz";
checksum = "pa6LSrQggh8mSJHQfwGjysAApmZlGJt8wif2cCLzqAAa2jpsTY0jZ-6stS3BWZ2Q";
url = "https://mirrors.kernel.org/gnu/libtool/libtool-"+version+".tar.gz";
checksum = "roFqdjyoGjpK7CWWLJJrTS56LuOQcIdq6Tgr4yplacSwirFHoaiDe6CojIWYinWe";
compress = gzip;
};
@@ -132,7 +135,7 @@ package gzip {
version# = "1.14";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/gzip/gzip-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/gzip/gzip-"+version+".tar.gz";
checksum = "NWhjUavnNfTDFkZJyAUonL9aCOak8GVajWX2OMlzpFnuI0ErpBFyj88mz2xSjz0q";
compress = gzip;
};
@@ -150,11 +153,18 @@ package sed {
version# = "4.10";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/sed/sed-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/sed/sed-"+version+".tar.gz";
checksum = "TXTRFQJCyflb-bpBRI2S5Y1DpplwvT7-KfXtpqN4AdZgZ5OtI6yStn1-bkhDKx51";
compress = gzip;
};
writable = true;
early = `
test_disable() { chmod +w "$2" && echo "$1" > "$2"; }
test_disable '#!/bin/sh' testsuite/read-error-stale-errno.sh
`;
exec = make {};
inputs = [
@@ -171,7 +181,7 @@ package diffutils {
version# = "3.12";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/diffutils/diffutils-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/diffutils/diffutils-"+version+".tar.gz";
checksum = "9J5VAq5oA7eqwzS1Yvw-l3G5o-TccUrNQR3PvyB_lgdryOFAfxtvQfKfhdpquE44";
compress = gzip;
};
@@ -186,7 +196,9 @@ test_disable '#!/bin/sh' tests/cmp
`;
toyboxEarly = true;
exec = make {};
exec = make {
omitDefaults = true;
};
}
package patch {
@@ -196,7 +208,7 @@ package patch {
version# = "2.8";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/patch/patch-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/patch/patch-"+version+".tar.gz";
checksum = "MA0BQc662i8QYBD-DdGgyyfTwaeALZ1K0yusV9rAmNiIsQdX-69YC4t9JEGXZkeR";
compress = gzip;
};
@@ -209,26 +221,9 @@ test_disable '#!/bin/sh' tests/ed-style
test_disable '#!/bin/sh' tests/need-filename
`;
toyboxEarly = true;
exec = make {};
}
package gawk {
description = "an implementation of awk with GNU extensions";
website = "https://www.gnu.org/software/gawk";
anitya = 868;
version# = "5.4.0";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/gawk/gawk-"+version+".tar.gz";
checksum = "m0RkIolC-PI7EY5q8pcx5Y-0twlIW0Yp3wXXmV-QaHorSdf8BhZ7kW9F8iWomz0C";
compress = gzip;
};
toyboxEarly = true;
exec = make {
// dependency loop
skipCheck = true;
omitDefaults = true;
};
}
@@ -239,7 +234,7 @@ package grep {
version# = "3.12";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/grep/grep-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/grep/grep-"+version+".tar.gz";
checksum = "qMB4RjaPNRRYsxix6YOrjE8gyAT1zVSTy4nW4wKW9fqa0CHYAuWgPwDTirENzm_1";
compress = gzip;
};
@@ -264,7 +259,7 @@ package gettext {
version# = "1.0";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/gettext/gettext-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/gettext/gettext-"+version+".tar.gz";
checksum = "3MasKeEdPeFEgWgzsBKk7JqWqql1wEMbgPmzAfs-mluyokoW0N8oQVxPQoOnSdgC";
compress = gzip;
};
@@ -302,14 +297,18 @@ package findutils {
website = "https://www.gnu.org/software/findutils";
anitya = 812;
version# = "4.10.0";
source = remoteFile {
url = "https://ftpmirror.gnu.org/gnu/findutils/findutils-"+version+".tar.xz";
checksum = "ZXABdNBQXL7QjTygynRRTdXYWxQKZ0Wn5eMd3NUnxR0xaS0u0VfcKoTlbo50zxv6";
version# = "4.11.0";
source = remoteTar {
url = "https://mirrors.kernel.org/gnu/findutils/findutils-"+version+".tar.xz";
compress = xz;
checksum = "X-qsv9aUoBL583q-4iZcBI3_7Ufd3fSIqFmNLXWdEpUihlRfMpGGyAUt8SAvDKae";
};
writable = true;
chmod = true;
early = `
echo '#!/bin/sh' > gnulib-tests/test-c32ispunct.sh
echo 'int main(){return 0;}' > gnulib-tests/test-fstatat.c
echo 'int main(){return 0;}' > tests/xargs/test-sigusr.c
`;
@@ -317,7 +316,6 @@ echo 'int main(){return 0;}' > tests/xargs/test-sigusr.c
inputs = [
diffutils,
xz,
sed,
];
}
@@ -329,13 +327,14 @@ package bash {
version# = "5.3";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/bash/bash-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/bash/bash-"+version+".tar.gz";
checksum = "4LQ_GRoB_ko-Ih8QPf_xRKA02xAm_TOxQgcJLmFDT6udUPxTAWrsj-ZNeuTusyDq";
compress = gzip;
};
toyboxEarly = true;
exec = make {
omitDefaults = true;
configure = {
"without-bash-malloc";
};
@@ -350,7 +349,7 @@ package coreutils {
version# = "9.11";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/coreutils/coreutils-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/coreutils/coreutils-"+version+".tar.gz";
checksum = "t8UMed5wpFEoC56aa42_yidfOAaRGzOfj7MRtQkkqgGbpXiskNA8bd-EmVSQkZie";
compress = gzip;
};
@@ -363,12 +362,16 @@ test_disable() { chmod +w "$2" && echo "$1" > "$2"; }
test_disable '#!/bin/sh' gnulib-tests/test-c32ispunct.sh
test_disable '#!/bin/sh' tests/ls/hyperlink.sh
test_disable '#!/bin/sh' tests/misc/user.sh
test_disable '#!/bin/sh' tests/split/line-bytes.sh
test_disable '#!/bin/sh' tests/ls/stat-vs-dirent.sh
test_disable '#!/bin/sh' tests/dd/sparse.sh
test_disable 'int main(){return 0;}' gnulib-tests/test-chown.c
test_disable 'int main(){return 0;}' gnulib-tests/test-fchownat.c
test_disable 'int main(){return 0;}' gnulib-tests/test-lchown.c
`;
exec = make {
omitDefaults = true;
configure = {
"enable-single-binary": "symlinks";
};
@@ -389,7 +392,7 @@ package tar {
version# = "1.35";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/tar/tar-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/tar/tar-"+version+".tar.gz";
checksum = "zSaoSlVUDW0dSfm4sbL4FrXLFR8U40Fh3zY5DWhR5NCIJ6GjU6Kc4VZo2-ZqpBRA";
compress = gzip;
};
@@ -426,7 +429,7 @@ package texinfo {
version# = "7.3";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/texinfo/texinfo-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/texinfo/texinfo-"+version+".tar.gz";
checksum = "RRmC8Xwdof7JuZJeWGAQ_GeASIHAuJFQMbNONXBz5InooKIQGmqmWRjGNGEr5n4-";
compress = gzip;
};
@@ -440,7 +443,7 @@ package texinfo {
runtime = [
perl,
gawk,
awk,
];
}
@@ -451,7 +454,7 @@ package gperf {
version# = "3.3";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gperf/gperf-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/gperf/gperf-"+version+".tar.gz";
checksum = "RtIy9pPb_Bb8-31J2Nw-rRGso2JlS-lDlVhuNYhqR7Nt4xM_nObznxAlBMnarJv7";
compress = gzip;
};
@@ -468,7 +471,7 @@ package bc {
version# = "1.08.2";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/bc/bc-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/bc/bc-"+version+".tar.gz";
checksum = "8h6f3hjV80XiFs6v9HOPF2KEyg1kuOgn5eeFdVspV05ODBVQss-ey5glc8AmneLy";
compress = gzip;
};
@@ -491,7 +494,7 @@ package libiconv {
version# = "1.19";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/libiconv/libiconv-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/libiconv/libiconv-"+version+".tar.gz";
checksum = "UibB6E23y4MksNqYmCCrA3zTFO6vJugD1DEDqqWYFZNuBsUWMVMcncb_5pPAr88x";
compress = gzip;
};
@@ -504,17 +507,14 @@ package parallel {
website = "https://www.gnu.org/software/parallel";
anitya = 5448;
version# = "20260522";
version# = "20260722";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/parallel/parallel-"+version+".tar.bz2";
checksum = "ezg3NZMlY-q-478YXmjWmDrDlaL55T7aBCuv3B7Z3DkAlfZRQEKO8eumqbcxTIy6";
url = "https://mirrors.kernel.org/gnu/parallel/parallel-"+version+".tar.bz2";
checksum = "liG9pBSRqUPqDuRXmnJPoVh-G53lDKkkO8GGabSxQnSho4b9BD0EaJDdScgVhnwj";
compress = bzip2;
};
early = `
ln -s ../system/bin/bash /bin/
`;
bin = [ "bash" ];
exec = make {};
inputs = [
@@ -532,7 +532,7 @@ package libunistring {
version# = "1.4.2";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/libunistring/libunistring-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/libunistring/libunistring-"+version+".tar.gz";
checksum = "iW9BbfLoVlXjWoLTZ4AekQSu4cFBnLcZ4W8OHWbv0AhJNgD3j65_zqaLMzFKylg2";
compress = gzip;
};
@@ -559,7 +559,7 @@ package libtasn1 {
version# = "4.21.0";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/libtasn1/libtasn1-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/libtasn1/libtasn1-"+version+".tar.gz";
checksum = "9DYI3UYbfYLy8JsKUcY6f0irskbfL0fHZA91Q-JEOA3kiUwpodyjemRsYRjUpjuq";
compress = gzip;
};
@@ -574,7 +574,7 @@ package readline {
version# = "8.3";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/readline/readline-"+version+".tar.gz";
url = "https://mirrors.kernel.org/gnu/readline/readline-"+version+".tar.gz";
checksum = "r-lcGRJq_MvvBpOq47Z2Y1OI2iqrmtcqhTLVXR0xWo37ZpC2uT_md7gKq5o_qTMV";
compress = gzip;
};
+2 -1
View File
@@ -34,7 +34,8 @@ echo 'int main(){return 0;}' > tests/mini-dtls-fragments.c
"with-zstd": "link";
"": arch {
arm64 = "disable-hardware-acceleration";
// miscompilation on arm64
arm64 = "--disable-hardware-acceleration";
};
};
};
+29
View File
@@ -0,0 +1,29 @@
From 45929774c3d5c084cc478afba63c77cf67a68bd7 Mon Sep 17 00:00:00 2001
From: khr@golang.org <khr@golang.org>
Date: Wed, 18 Feb 2026 09:09:57 -0800
Subject: [PATCH] internal/runtime/gc/scan: require popcnt for x86
The GOAMD64=v1 test disables popcnt instructions, which is a feature
this package's amd64 assembly uses.
Fixes #77674
Change-Id: I7be9bb665838f5da50275f96ef3df398412bb44a
Reviewed-on: https://go-review.googlesource.com/c/go/+/746640
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Keith Randall <khr@golang.org>
---
diff --git a/src/internal/runtime/gc/scan/scan_amd64.go b/src/internal/runtime/gc/scan/scan_amd64.go
index c03021c7d4..544b237770 100644
--- a/src/internal/runtime/gc/scan/scan_amd64.go
+++ b/src/internal/runtime/gc/scan/scan_amd64.go
@@ -39,4 +39,5 @@ var avx512ScanPackedReqsMet = cpu.X86.HasAVX512VL &&
cpu.X86.HasGFNI &&
cpu.X86.HasAVX512BITALG &&
cpu.X86.HasAVX512DQ && // for kmovb, see #79871
- cpu.X86.HasAVX512VBMI
+ cpu.X86.HasAVX512VBMI &&
+ cpu.X86.HasPOPCNT
+135
View File
@@ -0,0 +1,135 @@
From 06f90ebfa6f3e0a744584513e2786988b26569da Mon Sep 17 00:00:00 2001
From: Damien Neil <dneil@google.com>
Date: Wed, 08 Jul 2026 11:11:48 -0700
Subject: [PATCH] os: properly handle trailing / in Root.MkdirAll
MkdirAll("dir/") should create "dir", not return an error.
Fixes #80308
Change-Id: I75458c30b6cb94be3a3d368f6024caef6a6a6964
---
diff --git a/src/os/root_noopenat.go b/src/os/root_noopenat.go
index 228b580..a84e952 100644
--- a/src/os/root_noopenat.go
+++ b/src/os/root_noopenat.go
@@ -158,6 +158,9 @@
if err := checkPathEscapes(r, name); err == errPathEscapes {
return &PathError{Op: "mkdirat", Path: name, Err: err}
}
+ if name == "" {
+ return &PathError{Op: "mkdirat", Path: name, Err: syscall.ENOENT}
+ }
prefix := r.root.name + string(PathSeparator)
if err := MkdirAll(prefix+name, perm); err != nil {
if pe, ok := err.(*PathError); ok {
diff --git a/src/os/root_openat.go b/src/os/root_openat.go
index d7c9334..92865e4 100644
--- a/src/os/root_openat.go
+++ b/src/os/root_openat.go
@@ -167,6 +167,12 @@
fi, e := r.Stat(fullname)
if e == nil && fi.Mode().IsDir() {
err = nil
+ } else if e == nil {
+ err = syscall.ENOTDIR
+ } else if !IsNotExist(e) {
+ // EPERM, ELOOP, etc.,
+ // probably more useful than EEXIST.
+ err = e
}
}
}
@@ -177,7 +183,12 @@
}
return struct{}{}, &PathError{Op: "mkdirat", Err: err}
}
- _, err := doInRoot(r, fullname, 0, openDirFunc, openLastComponentFunc)
+ flags := uint(doInRootCreatingDirectory)
+ switch runtime.GOOS {
+ case "linux", "windows":
+ flags = doInRootNoHandleTerminalSlash // see rootMkdir
+ }
+ _, err := doInRoot(r, fullname, flags, openDirFunc, openLastComponentFunc)
if err != nil {
if _, ok := err.(*PathError); !ok {
err = &PathError{Op: "mkdirat", Path: fullname, Err: err}
diff --git a/src/os/root_test.go b/src/os/root_test.go
index 5e0acf9..33a2f33 100644
--- a/src/os/root_test.go
+++ b/src/os/root_test.go
@@ -585,6 +585,11 @@
func TestRootMkdirAll(t *testing.T) {
for _, test := range rootTestCases {
+ if test.name == "directory does not exist" {
+ // Test expects error, mkdirall creates the missing directory.
+ // TestRootMultiMkdirAll covers this case better anyway, just skip.
+ continue
+ }
test.run(t, func(t *testing.T, target string, root *os.Root) {
wantError := test.wantError
if test.ltarget != "" {
@@ -593,7 +598,7 @@
wantError = true
}
- err := root.Mkdir(test.open, 0o777)
+ err := root.MkdirAll(test.open, 0o777)
if errEndsTest(t, err, wantError, "root.MkdirAll(%q)", test.open) {
return
}
@@ -3133,6 +3138,52 @@
})
}
+func TestRootMultiMkdirAllShallow(t *testing.T) {
+ runRootMultiTest(t, func(t *testing.T, test *rootMultiTest) (string, error) {
+ return testRootMultiMkdirAll(t, test, test.targetPath)
+ })
+}
+
+func TestRootMultiMkdirAllDeep(t *testing.T) {
+ runRootMultiTest(t, func(t *testing.T, test *rootMultiTest) (string, error) {
+ targetPath := test.targetPath
+ if len(targetPath) > 0 && os.IsPathSeparator(targetPath[len(targetPath)-1]) {
+ targetPath += "a/b/"
+ } else {
+ targetPath += "/a/b"
+ }
+ return testRootMultiMkdirAll(t, test, targetPath)
+ })
+}
+
+func testRootMultiMkdirAll(t *testing.T, test *rootMultiTest, targetPath string) (string, error) {
+ var mkdirAll = os.MkdirAll
+ if test.root != nil {
+ mkdirAll = test.root.MkdirAll
+ }
+
+ test.setOp("MkdirAll(%q, 0o777)", targetPath)
+ gotErr := mkdirAll(targetPath, 0o777)
+
+ switch {
+ case test.root != nil && test.target.lescapes():
+ // "mkdir ../target", or equivalent escaping path.
+ test.wantError(t, gotErr, os.ErrPathEscapes)
+ case test.root != nil && test.target.escapes():
+ // "mkdir ../target", or equivalent escaping path.
+ test.wantError(t, gotErr, errAny)
+ return "", errSkipRootConsistencyCheck
+ case test.root != nil && test.target.kind == testFileSymlink && test.target.target.kind == testFileAbsent && targetPath != test.targetPath:
+ // A minor inconsistency between Root.MkdirAll and os.MkdirAll:
+ // When an intermediate component of the tree being constructed is a
+ // dangling symlink, Root.MkdirAll will follow the symlink and create
+ // its target directory, while os.MkdirAll will fail with an error.
+ return "", errSkipRootConsistencyCheck
+ default:
+ }
+ return "", gotErr
+}
+
func TestRootMultiRename(t *testing.T) {
if runtime.GOOS == "wasip1" {
switch os.Getenv("GOWASIRUNTIME") {
+64
View File
@@ -0,0 +1,64 @@
package go {
description = "the Go programming language toolchain";
website = "https://go.dev";
anitya = 1227;
version# = "1.26.5";
source = remoteTar {
url = "https://go.dev/dl/go"+version+".src.tar.gz";
checksum = "13yt1u_NGOd62LO-WZ8W6CUXodOrEF5CdkiTTiH9E635IHn1luvlXYjsHpBXNFSw";
compress = gzip;
};
patches = [
// https://go.dev/issue/77674
"746640.patch",
// https://go.dev/issue/80308
"799064.patch",
];
env = [
"CC=cc",
"GOCACHE=/tmp/gocache",
"GOROOT_BOOTSTRAP=/system/go",
"TMPDIR=/dev/shm/go",
];
enterSource = true;
exec = generic {
inPlace = true;
build = `
mkdir /work/system/ "${TMPDIR}"
cp -r . /work/system/go
cd /work/system/go/src/
chmod -R +w ..
sed -i \
's,/lib/ld-musl-`+linuxArch+`.so.1,/system/bin/linker,' \
cmd/link/internal/`+arch+`/obj.go
rm \
os/root_unix_test.go \
runtime/crash_cgo_test.go \
cmd/cgo/internal/testsanitizers/tsan_test.go \
cmd/cgo/internal/testsanitizers/cshared_test.go
set +u
. ./make.bash "$@" --no-banner
set -u
`;
check = "bash run.bash --no-rebuild\n";
install = `
../bin/go tool dist banner # print build info
mkdir /work/system/bin
ln -s \
../go/bin/go \
../go/bin/gofmt \
/work/system/bin
`;
};
inputs = [ bash, go-bootstrap ];
}
+8 -3
View File
@@ -2,11 +2,11 @@ package hakurei-source {
description = "hakurei source tree";
exclude = true;
version# = "0.4.3";
version# = "0.4.5";
output = remoteTar {
url = "https://git.gensokyo.uk/rosa/hakurei/archive/"+
"v"+version+".tar.gz";
checksum = "1LqBJIcYcAFTVfydCahOm4hjjKhY953X9ars0eQj32hnpNncWFefuT6OJpZzIlZv";
checksum = "5bvbuIRcDIrtijogwqXn3y8h5f3rVS4ZSVhOig6Galfzt3g-O3Ufb-tHL1kQCQWK";
compress = gzip;
};
}
@@ -48,8 +48,13 @@ go build -trimpath -tags=rosa -o /work/system/libexec/hakurei -ldflags="-s -w
-X hakurei.app/internal/info.buildVersion=$(cat cmd/dist/VERSION)
-X hakurei.app/internal/info.hakureiPath=/system/bin/hakurei
-X hakurei.app/internal/info.hsuPath=/system/bin/hsu
" ./cmd/hakurei ./cmd/sharefs
echo "Building hsu for $(go env GOOS)/$(go env GOARCH)."
CGO_ENABLED=0 go build -trimpath -tags=rosa -o /work/system/libexec/hakurei -ldflags="-s -w
-buildid=
-X main.hakureiPath=/system/bin/hakurei
" ./...
" ./cmd/hsu
echo`;
check = `
echo '##### Testing hakurei.'

Some files were not shown because too many files have changed in this diff Show More