# dpack — DarkForge Package Manager A source-based package manager for DarkForge Linux, positioned between CRUX's `pkgutils` and Gentoo's `emerge` in complexity. Written in Rust. ## Features - **TOML package definitions** — clean, readable package recipes - **Dependency resolution** — topological sort with circular dependency detection - **Build sandboxing** — bubblewrap (bwrap) isolation with PID/network namespaces - **Installed package database** — file-based TOML tracking in `/var/lib/dpack/db/` - **Full build orchestration** — download → checksum → extract → sandbox build → stage → commit → register - **CRUX Pkgfile converter** — convert CRUX ports to dpack format - **Gentoo ebuild converter** — best-effort conversion of Gentoo ebuilds (handles ~80% of cases) - **Shared library conflict detection** — ELF binary scanning via readelf/objdump - **Reverse dependency tracking** — warns before removing packages that others depend on ## Requirements **Build-time (compiling dpack itself):** dpack is written in Rust and can be built on any platform with a Rust toolchain: - Rust 1.75+ with Cargo (install via https://rustup.rs) - A C linker (gcc or clang) — needed by some Rust dependencies - Works on Linux and macOS for development, but runtime features require Linux ```bash # macOS (Homebrew) brew install rustup && rustup-init # Arch Linux sudo pacman -S rust # Ubuntu / Debian curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` **Runtime (using dpack to build/install packages):** dpack must run on a Linux system (it uses Linux-specific features): - Linux kernel 5.4+ (for namespace support) - `bash` (build scripts are bash) - `curl` or `wget` (source tarball downloads) - `git` (for git-source packages) - `tar` (source extraction) - `readelf` or `objdump` (shared library scanning — part of binutils) - bubblewrap (`bwrap`) for sandboxed builds (optional — falls back to direct execution) - A C/C++ compiler (gcc or clang) and make (for building packages) On the DarkForge system itself, all runtime dependencies are provided by the base system. On another Linux distro for testing: ```bash # Arch Linux sudo pacman -S base-devel bubblewrap curl git # Ubuntu / Debian sudo apt install build-essential bubblewrap curl git binutils ``` ## Building ```bash cd src/dpack cargo build --release ``` The binary is at `target/release/dpack`. Install it: ```bash # On Linux sudo install -m755 target/release/dpack /usr/local/bin/ # For development/testing (from the repo root) cargo run --release -- install zlib ``` ## Usage ```bash # Install a package (resolves deps, builds in sandbox, installs, updates db) dpack install zlib # Install multiple packages dpack install openssl curl git # Remove a package (warns about reverse deps, removes files) dpack remove zlib # Upgrade packages (compares installed vs repo versions) dpack upgrade # upgrade all outdated packages dpack upgrade openssl git # upgrade specific packages # Search for packages dpack search compression # Show package info dpack info zlib # List installed packages dpack list # Check for file conflicts and shared library issues dpack check # Check for available updates (compares installed vs repo + upstream) dpack check-updates # Convert foreign package formats dpack convert /path/to/Pkgfile # CRUX → dpack TOML (stdout) dpack convert /path/to/curl-8.19.0.ebuild -o curl.toml # Gentoo → dpack TOML (file) ``` ## Configuration dpack reads its configuration from `/etc/dpack.conf` (TOML format). If the file doesn't exist, sensible defaults are used. Example `/etc/dpack.conf`: ```toml [flags] cflags = "-march=znver5 -O2 -pipe -fomit-frame-pointer" cxxflags = "-march=znver5 -O2 -pipe -fomit-frame-pointer" ldflags = "-Wl,-O1,--as-needed" makeflags = "-j32" [paths] db_dir = "/var/lib/dpack/db" repo_dir = "/var/lib/dpack/repos" source_dir = "/var/cache/dpack/sources" build_dir = "/var/tmp/dpack/build" [sandbox] enabled = true allow_network = false bwrap_path = "/usr/bin/bwrap" [[repos]] name = "core" path = "/var/lib/dpack/repos/core" priority = 0 [[repos]] name = "extra" path = "/var/lib/dpack/repos/extra" priority = 10 [[repos]] name = "desktop" path = "/var/lib/dpack/repos/desktop" priority = 20 [[repos]] name = "gaming" path = "/var/lib/dpack/repos/gaming" priority = 30 ``` ## Package Definition Format Package definitions are TOML files stored at `//.toml`: ```toml [package] name = "zlib" version = "1.3.1" description = "Compression library implementing the deflate algorithm" url = "https://zlib.net/" license = "zlib" [source] url = "https://zlib.net/zlib-${version}.tar.xz" sha256 = "38ef96b8dfe510d42707d9c781877914792541133e1870841463bfa73f883e32" [dependencies] run = [] build = ["gcc", "make"] [dependencies.optional] static = { description = "Build static library", default = true } minizip = { description = "Build minizip utility", deps = [] } [build] system = "autotools" configure = "./configure --prefix=/usr" make = "make" install = "make DESTDIR=${PKG} install" [build.flags] cflags = "" # empty = use global defaults ldflags = "" ``` ### Variables available in build commands - `${PKG}` — staging directory (DESTDIR) - `${version}` — package version (expanded in source URL) ### Build systems The `system` field is a hint: `autotools`, `cmake`, `meson`, `cargo`, or `custom`. ### Git sources Instead of downloading a tarball, dpack can clone a git repository directly. This is useful for building from the latest development branch or a specific commit: ```toml [source] url = "" # can be empty for git sources sha256 = "SKIP" # integrity verified by git git = "https://github.com/FreeCAD/FreeCAD.git" # clone URL branch = "main" # checkout this branch # Or pin to a tag (supports ${version} expansion): # tag = "v${version}" # Or pin to a specific commit: # commit = "abc123def456" ``` When `git` is set, dpack clones the repository (with `--depth 1` for branches/tags) into the build directory. The `branch`, `tag`, and `commit` fields control what gets checked out (in priority order: commit > tag > branch > default). ### Upstream update checking Packages can specify an `update_check` URL in the `[source]` section. When you run `dpack check-updates`, it queries these URLs and compares the result against your installed version. ```toml [source] url = "https://example.com/foo-${version}.tar.xz" sha256 = "..." update_check = "https://api.github.com/repos/owner/repo/releases/latest" ``` Supported URL patterns: - **GitHub releases API** — parses `tag_name` from the JSON response - **GitHub/Gitea tags API** — parses the first tag name - **Plain URL** — the response body is treated as the version string ## Running Tests ```bash cargo test ``` Tests cover: TOML parsing, dependency resolution (simple, diamond, circular), database operations (register, unregister, persistence, file ownership, conflicts), and converter parsing. ## Architecture ``` src/ ├── main.rs # CLI (clap) — install, remove, upgrade, search, info, list, convert, check ├── lib.rs # Library re-exports ├── config/ │ ├── mod.rs # Module root │ ├── package.rs # PackageDefinition TOML structs + parsing + validation │ └── global.rs # DpackConfig (flags, paths, sandbox, repos) ├── resolver/ │ ├── mod.rs # DependencyGraph, topological sort, reverse deps │ └── solib.rs # Shared library conflict detection (ELF scanning) ├── sandbox/ │ └── mod.rs # BuildSandbox (bubblewrap + direct backends) ├── converter/ │ ├── mod.rs # Format auto-detection │ ├── crux.rs # CRUX Pkgfile parser │ └── gentoo.rs # Gentoo ebuild parser ├── db/ │ └── mod.rs # PackageDb (file-based TOML, installed tracking) └── build/ └── mod.rs # BuildOrchestrator (download → build → install pipeline) ``` ## Repository ``` git@git.dannyhaslund.dk:danny8632/dpack.git ```