Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <[email protected]>
zeta-reconstruct
zeta-reconstruct — convert Arch Linux packages (binary .pkg.tar.zst and source PKGBUILD/.SRCINFO) into Zeta package format.
The tool is a translator. It never runs makepkg, never compiles anything, and never publishes packages. It only converts files and writes them to disk, warning on stderr whenever a dependency or edge case cannot be mapped cleanly.
Build
Requires Go 1.26 or newer. The only external dependency is github.com/klauspost/compress (zstd decoding); everything else uses the Go standard library.
go build ./cmd/zeta-reconstruct
This writes the zeta-reconstruct binary into the current directory. To place it next to the sources instead:
go build -o ./cmd/zeta-reconstruct/zeta-reconstruct ./cmd/zeta-reconstruct
Usage
$ zeta-reconstruct --help
usage: zeta-reconstruct <command> [flags] <input>
Commands:
arch-binary convert an Arch binary package (.pkg.tar.zst) to Zeta
arch-src convert a PKGBUILD/.SRCINFO source recipe to Zeta
Flags:
--list list registered frontends
-h, --help show this help
arch-binary flags:
--output <dir> output directory (default ".")
--repo <url> repository base URL (default "https://raw.githubusercontent.com/gretagen/zeta-packages/refs/heads/main")
arch-src flags:
--output <dir> output directory (default ".")
--arch <arch> target architecture (default "x86_64")
--list prints the registered frontends: arch-binary and arch-src.
zeta-reconstruct --list
zeta-reconstruct arch-binary <input.pkg.tar.zst> --output <dir> [--repo <url>]
zeta-reconstruct arch-src <PKGBUILD|.SRCINFO|dir> --output <dir> [--arch <arch>]
For arch-binary the input must end in .pkg.tar.zst. For arch-src the input may be a PKGBUILD, a .SRCINFO, or a directory containing either; a .SRCINFO is preferred when both are present.
Outputs
arch-binarywritespackages/<name>/<name>-<version>.tar.gzand apackage.luamanifest beside it, under the--outputdirectory.arch-srcwrites<name>.recipeand a generatedbuild.shinto the--outputdirectory.
Workflow
- The emitted
package.luais an archive-mode manifest consumed byzeta(the package manager).zetadownloads the tarball at the manifesturl, verifies itssha256, and installs it withstrip = 1. - The emitted
.recipeplusbuild.share consumed byzeta-makepkgto build the binary package from source. The recipe declaresbuild_system = "custom"andbuild_script = "build.sh"; zeta-makepkg fetches the source, extracts it, and runs the script undershwithDESTDIRset.
Field mapping: .PKGINFO → package.lua
.PKGINFO field |
package.lua field |
Notes |
|---|---|---|
pkgname |
name |
|
pkgver |
version |
verbatim, already in epoch+pkgrel form (e.g. 1.0-1) |
pkgdesc |
summary |
|
url |
n/a | not carried over; the manifest url is built from --repo plus packages/<name>/<name>-<version>.tar.gz |
depend |
deps |
each relation mapped through the Arch→Zeta name table; dropped deps are skipped with a warning |
| n/a | archive |
{ strip = 1 } |
| n/a | sha256 |
sha256 of the emitted tarball |
Arch metadata members that are not payload (.BUILDINFO, .MTREE, .INSTALL, .Changelog) are skipped during extraction.
Field mapping: .SRCINFO/PKGBUILD → .recipe
| source field | recipe field | Notes |
|---|---|---|
pkgname |
name |
v1 covers exactly one package per recipe |
pkgver |
version |
upstream version; pkgrel is dropped |
pkgdesc |
summary |
falls back to the package name when empty |
source[0] |
url |
the text after a name:: prefix if present, else the whole string; the URL scheme is never stripped |
sha256sums[0] |
sha256 |
the line is omitted entirely when the value is empty or SKIP; a non-hex64 value is dropped with a warning |
depends |
deps |
each relation mapped through the Arch→Zeta name table |
| n/a | build_system |
"custom" |
| n/a | build_script |
"build.sh" |
The generated build.sh reproduces the PKGBUILD's prepare() (if present), build() (if present), and package() functions with $pkgdir pointed at $DESTDIR. Function bodies are embedded from the PKGBUILD file; a .SRCINFO-only input yields stub functions.
Dependency mapping
Each Arch dependency relation is mapped in this order:
- An optdepend-style description (
name: description) is stripped back to the name. - If the name matches a Zeta package name verbatim (checked against the Zeta package index), it passes through unchanged. Version constraints are preserved; a bare Arch
=is normalized to==(Zeta's canonical form). - Otherwise a curated rename table is applied, with a warning.
- Otherwise, if the name is on the base-system drop list, it is dropped, with a warning.
- Otherwise it passes through with a warning (nothing is silently lost).
Renames
| Arch | Zeta |
|---|---|
zlib |
libz |
xz |
xz-utils |
freetype2 |
freetype |
libxkbcommon |
xkbcommon |
libice |
libICE |
libsm |
libSM |
libx11 … libxxf86vm |
libX11 … libXxf86vm |
The X11 family is pure case correction: Arch spells it lowercase (libx11, libxau, libxext, libxrender, libxft, and the rest of the libx* set), while the Zeta index uses libX*. Names like libxcb and libxml2 are already correct and are deliberately absent from the table.
Dropped (base system)
These packages are provided outside the package manager, so Zeta has no package for them:
glibc, gcc-libs, gcc, bash, coreutils, filesystem, linux-api-headers, systemd, util-linux, ncurses, readline, tzdata, ca-certificates.
Version and epoch
- Binary packages keep the
.PKGINFOpkgververbatim, epoch and pkgrel included (1.0-1, or1:1.0-1when an epoch exists). - Source recipes use
version = pkgver(the upstream version);pkgrelis dropped, matching how versions appear in the Zeta package index. - An epoch is never folded into the Zeta version. When a
:epoch is present, a warning is emitted and the version string keeps its epoch form.
Not yet supported (v1)
The following shapes are not yet supported in v1. They produce an explicit error, except where noted:
- Split packages (more than one
pkgname): error. - VCS sources:
git+,svn+,hg+,bzr+protocol prefixes,<vcs>::<url>fragments (e.g.git::https://…), and dynamicpkgver()functions: error. - Multiple sources (more than one
sourceentry): error. - Zero sources: error (a recipe requires a
url). - makedepends, optdepends, provides, conflicts, replaces: parsed but dropped with a warning; Zeta's formats have no fields for them.
- Bash-only constructs in PKGBUILD function bodies (arrays,
[[ ]],local, process substitution): the generatedbuild.shcarries a warning that it may need manual adjustment. - Gentoo ebuilds and void-src packages: not supported. The frontend registry interface is in place, so future converters can be added as new frontends, but no such converter ships in v1.