Files
darkforge/src/dpack

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
# 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:

# Arch Linux
sudo pacman -S base-devel bubblewrap curl git

# Ubuntu / Debian
sudo apt install build-essential bubblewrap curl git binutils

Building

cd src/dpack
cargo build --release

The binary is at target/release/dpack. Install it:

# On Linux
sudo install -m755 target/release/dpack /usr/local/bin/

# For development/testing (from the repo root)
cargo run --release -- install zlib

Usage

# 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:

[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 <repo>/<name>/<name>.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:

[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.

[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

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