Files

134 lines
7.0 KiB
Markdown

# 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-binary` writes `packages/<name>/<name>-<version>.tar.gz` and a `package.lua` manifest beside it, under the `--output` directory.
- `arch-src` writes `<name>.recipe` and a generated `build.sh` into the `--output` directory.
### Workflow
- The emitted `package.lua` is an archive-mode manifest consumed by `zeta` (the package manager). `zeta` downloads the tarball at the manifest `url`, verifies its `sha256`, and installs it with `strip = 1`.
- The emitted `.recipe` plus `build.sh` are consumed by `zeta-makepkg` to build the binary package from source. The recipe declares `build_system = "custom"` and `build_script = "build.sh"`; zeta-makepkg fetches the source, extracts it, and runs the script under `sh` with `DESTDIR` set.
## 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:
1. An optdepend-style description (`name: description`) is stripped back to the name.
2. 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).
3. Otherwise a curated rename table is applied, with a warning.
4. Otherwise, if the name is on the base-system drop list, it is dropped, with a warning.
5. 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 `.PKGINFO` `pkgver` verbatim, epoch and pkgrel included (`1.0-1`, or `1:1.0-1` when an epoch exists).
- Source recipes use `version = pkgver` (the upstream version); `pkgrel` is 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 dynamic `pkgver()` functions: error.
- **Multiple sources** (more than one `source` entry): 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 generated `build.sh` carries 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.