# Container engine helpers for Omarchy package build system container_engine_supported() { [[ "$CONTAINER_ENGINE" == "docker" || "$CONTAINER_ENGINE" == "podman" ]] } if [[ -z "${CONTAINER_ENGINE:-}" ]]; then for engine in docker podman; do if command -v "$engine" >/dev/null 2>&1 && "$engine" info >/dev/null 2>&1; then CONTAINER_ENGINE="$engine" break fi done fi export CONTAINER_ENGINE # Rootless Podman otherwise maps the image's builder uid 1000 to a subordinate # host uid. keep-id makes files written through bind mounts belong to the user # who invoked the build. CONTAINER_RUN_ARGS=() if [[ "$CONTAINER_ENGINE" == "podman" ]]; then CONTAINER_RUN_ARGS+=("--userns=keep-id:uid=1000,gid=1000") fi check_engine() { if [[ -n "$CONTAINER_ENGINE" ]] && ! container_engine_supported; then print_error "Unsupported CONTAINER_ENGINE: $CONTAINER_ENGINE (use docker or podman)" exit 1 fi if [[ -z "$CONTAINER_ENGINE" ]]; then print_error "No working container engine found (tried Docker, then Podman)" if command -v docker >/dev/null 2>&1; then print_warning "Docker is installed but unavailable. Start it with: sudo systemctl start docker" elif command -v podman >/dev/null 2>&1; then print_warning "Podman is installed but 'podman info' failed" else print_warning "Install Docker or Podman" fi exit 1 fi if ! command -v "$CONTAINER_ENGINE" >/dev/null 2>&1; then print_error "$CONTAINER_ENGINE is not installed" exit 1 fi if ! "$CONTAINER_ENGINE" info >/dev/null 2>&1; then if [[ "$CONTAINER_ENGINE" == "docker" ]]; then print_error "Docker daemon is not running or is not accessible" print_warning "Start Docker with: sudo systemctl start docker" else print_error "Podman is not available to the current user" fi exit 1 fi } docker_native_arch() { case "$(uname -m)" in x86_64) echo x86_64 ;; aarch64 | arm64) echo aarch64 ;; *) return 1 ;; esac } setup_qemu() { local target_arch="${1:-aarch64}" if [[ "$CONTAINER_ENGINE" == "podman" ]]; then local registration="/proc/sys/fs/binfmt_misc/qemu-$target_arch" local packaged_registration="/usr/lib/binfmt.d/qemu-$target_arch-static.conf" local flags="" if [[ -r "$registration" ]]; then flags=$(sed -n 's/^flags: //p' "$registration") fi if [[ "$flags" == *F* && "$flags" == *C* ]]; then print_success "QEMU $target_arch emulation is registered" return 0 fi print_error "Rootless Podman requires QEMU binfmt registration with the F and C flags" print_info "F keeps the emulator available inside containers; C lets container sudo preserve credentials." print_info "Configure it once with:" echo " sudo pacman -S --needed qemu-user-static qemu-user-static-binfmt" echo " sudo mkdir -p /etc/binfmt.d" echo " sed 's/:FP$/:FPC/' $packaged_registration | sudo tee /etc/binfmt.d/qemu-$target_arch-static.conf >/dev/null" echo " sudo systemctl restart systemd-binfmt" exit 1 fi # Register emulators for builds whose target differs from the host, with # the F and C flags (tonistiigi/binfmt always sets both). The image tag pins # the QEMU version every emulated build runs under; multiarch/qemu-user-static # stopped at QEMU 7.2, which breaks qmake's compiler probe on current gcc. # Keep ci/runner-cloud-init.yaml on the same tag. Uninstall first: install # leaves an existing registration (an older emulator) in place and exits 0. local platform_arch case "$target_arch" in aarch64) platform_arch=arm64 ;; x86_64) platform_arch=amd64 ;; *) platform_arch="$target_arch" ;; esac if ! "$CONTAINER_ENGINE" run --rm --privileged docker.io/tonistiigi/binfmt:qemu-v10.2.3-68 --uninstall "qemu-$target_arch" --install "$platform_arch" >/dev/null 2>&1; then print_error "Failed to set up QEMU emulation" exit 1 fi print_success "QEMU emulation enabled" } build_docker_image() { local build_dir="$1" local arch="${2:-x86_64}" local mirror="${3:-edge}" local platform="" local image_tag="omarchy-pkg-builder:latest-$arch-$mirror" case "$arch" in x86_64) platform="linux/amd64" ;; aarch64) platform="linux/arm64" ;; *) print_error "Unsupported architecture: $arch" exit 1 ;; esac print_info "Building container image for $arch ($platform) using $mirror mirror..." if [[ "$CONTAINER_ENGINE" == "docker" ]]; then "$CONTAINER_ENGINE" buildx build \ --platform "$platform" \ --build-arg MIRROR="$mirror" \ --load \ -t "$image_tag" \ -f "$build_dir/Dockerfile" \ "$build_dir" else "$CONTAINER_ENGINE" build \ --platform "$platform" \ --build-arg MIRROR="$mirror" \ -t "$image_tag" \ -f "$build_dir/Dockerfile" \ "$build_dir" fi } get_platform_arg() { local arch="$1" case "$arch" in x86_64) echo "--platform=linux/amd64" ;; aarch64) echo "--platform=linux/arm64" ;; *) return 1 ;; esac } make_dir_writable() { local dir="$1" if (( EUID == 0 )); then chmod -R 777 "$dir" else # chown can succeed on part of the tree and fail on the rest (files a # previous container left behind as another uid); the old `|| chmod` # fallback only ran when chown failed outright, leaving those files # unwritable. Always follow with chmod so the whole tree is usable. sudo chown -R "$(id -u):$(id -g)" "$dir" 2>/dev/null || true chmod -R 777 "$dir" fi }