aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremmett1 <me@emmett1.my>2026-05-29 23:40:06 +0800
committeremmett1 <me@emmett1.my>2026-05-29 23:40:06 +0800
commit49717b9544bacbcd38a10b791adcb4a4aa2e9162 (patch)
treed032595b7f70de43df9e485ce7da196bb125aee3
parent53900763c5574fe60beb877dda57ea76941f7cec (diff)
downloadautils-49717b9544bacbcd38a10b791adcb4a4aa2e9162.tar.gz
autils-49717b9544bacbcd38a10b791adcb4a4aa2e9162.zip
updates
-rw-r--r--INSTALL.sh11
-rw-r--r--Makefile30
-rw-r--r--README.md215
-rwxr-xr-xapkg73
-rwxr-xr-xapkg-bin233
-rwxr-xr-x[-rw-r--r--]apkg-genabuild0
-rwxr-xr-xapkg-outdated32
-rwxr-xr-xapkg-reposync73
-rw-r--r--man/apkg-chroot.842
-rw-r--r--man/apkg-clean.836
-rw-r--r--man/apkg-deps.833
-rw-r--r--man/apkg-foreign.829
-rw-r--r--man/apkg-genabuild.835
-rw-r--r--man/apkg-orphan.829
-rw-r--r--man/apkg-purge.832
-rw-r--r--man/apkg-redundantdeps.835
-rw-r--r--man/apkg.8368
-rw-r--r--man/apkg.conf.md45
-rw-r--r--man/apkg.md72
-rw-r--r--man/make-man.sh32
-rw-r--r--man/man5/apkg.conf.586
-rw-r--r--man/man8/apkg.8181
-rw-r--r--man/man8/revdep.834
-rw-r--r--man/reposync.851
-rw-r--r--man/revdep.838
-rw-r--r--man/revdep.md29
-rw-r--r--man/updateconf.849
-rwxr-xr-xreposync63
28 files changed, 1087 insertions, 899 deletions
diff --git a/INSTALL.sh b/INSTALL.sh
deleted file mode 100644
index d569215..0000000
--- a/INSTALL.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-BINDIR=${DESTDIR}${BINDIR:-/usr/bin}
-CONFDIR=${DESTDIR}${CONFDIR:-/etc}
-
-mkdir -p ${BINDIR} ${CONFDIR}
-
-install -m755 apkg ${BINDIR}
-install -m755 apkg-* ${BINDIR}
-install -m755 revdep updateconf reposync ${BINDIR}
-install -m644 doc/apkg.conf.readme ${CONFDIR}/apkg.conf
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..303714f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,30 @@
+PREFIX ?= /usr
+BINDIR ?= $(PREFIX)/bin
+MANDIR ?= $(PREFIX)/share/man/man8
+
+SCRIPTS = apkg \
+ apkg-chroot \
+ apkg-clean \
+ apkg-deps \
+ apkg-foreign \
+ apkg-genabuild \
+ apkg-orphan \
+ apkg-purge \
+ apkg-redundantdeps \
+ reposync \
+ revdep \
+ updateconf
+
+.PHONY: all install uninstall
+
+all:
+ @echo "Run 'make install' to install autils."
+
+install:
+ mkdir -p $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)
+ install -m755 $(SCRIPTS) $(DESTDIR)$(BINDIR)
+ install -m644 man/*.8 $(DESTDIR)$(MANDIR)
+
+uninstall:
+ for f in $(SCRIPTS); do rm -f $(DESTDIR)$(BINDIR)/$$f; done
+ for f in man/*.8; do rm -f $(DESTDIR)$(MANDIR)/$$(basename $$f); done
diff --git a/README.md b/README.md
index 82f1cf0..8cb5623 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,215 @@
# autils
-Alice Linux Utilities
+
+Alice Linux Utilities — a collection of POSIX shell scripts for source-based package management on [Alice Linux](https://codeberg.org/emmett1/alicelinux).
+
+## Overview
+
+**apkg** is the core package manager. It reads an `abuild` recipe (a POSIX shell snippet defining the package name, version, sources, and optional build hooks), downloads and verifies source tarballs, auto-detects one of 6 supported build systems, compiles the software, post-processes the result (strip binaries, compress man pages, install runit services), packages it into the `.spm` format, and installs or upgrades the package via the **spm**(8) backend.
+
+A set of `apkg-*` helper scripts handle binary package management, dependency analysis, repo syncing, orphan detection, cleanup, and more. Standalone utilities cover reverse-dependency checking (`revdep`), configuration file merging (`updateconf`), and environment-driven git repository synchronization (`reposync`).
+
+## Installation
+
+```sh
+make install
+```
+
+Installs all scripts into `/usr/bin` and man pages into `/usr/share/man/man8`.
+Override with `DESTDIR`, `PREFIX`, `BINDIR`, or `MANDIR`. Individual scripts are
+self-contained and can be run directly from the source tree for testing.
+
+## Quick start
+
+```sh
+# Build and install a package (from inside its recipe directory)
+cd /path/to/repo/mypkg
+apkg -i
+
+# Install with automatic dependency resolution
+apkg -I firefox
+
+# Search available packages
+apkg -s icon
+
+# List outdated packages on the system
+apkg -l
+
+# Full system upgrade
+apkg -U
+
+# Remove a package and its unneeded dependencies
+apkg-purge -p mypkg
+
+# Find broken library links after an upgrade
+revdep
+
+# Merge .new config files after an upgrade
+updateconf
+```
+
+## Tools
+
+### Core
+
+| Tool | Description |
+|---|---|
+| `apkg` | Build packages from source, resolve dependencies, install/upgrade/remove, search repos, system upgrade |
+| `spm` | Low-level `.spm` package installer (external, not in this repo) |
+
+### Helpers
+
+| Script | Purpose |
+|---|---|
+| `apkg-chroot` | Enter a chroot with `/dev`, `/proc`, `/sys`, `/run` bind-mounted |
+| `apkg-clean` | List stale `.spm` files and orphaned source tarballs (pipe to `xargs rm`) |
+| `apkg-deps` | Show runtime library dependencies of an installed package via `ldd` |
+| `apkg-foreign` | List installed packages not found in any configured repo |
+| `apkg-genabuild` | Scaffold an `abuild` recipe file from a source URL |
+| `apkg-orphan` | List installed packages that have no dependents installed |
+| `apkg-purge` | Remove a package and its dependencies that are no longer needed by others (`-p` to actually remove) |
+| `apkg-redundantdeps` | Detect transitive dependencies explicitly listed in `depends` files (`-f` to fix) |
+
+### Standalone utilities
+
+| Tool | Description |
+|---|---|
+| `revdep` | Scan system binaries and libraries for missing library links (run after major upgrades) |
+| `updateconf` | Interactive `.new` config file merge tool — diff, keep, discard, or edit |
+| `reposync` | Git repo sync driven by `REPOSYNC_*` environment variables (no `/etc/apkg.conf` dependency) |
+
+## The abuild recipe
+
+An `abuild` file is a POSIX shell snippet sourced by apkg. The directory containing it must have the same name as the `name` variable.
+
+A minimal recipe:
+
+```sh
+name=mypkg
+version=1.2.3
+release=1
+source="https://example.com/$name-$version.tar.gz"
+```
+
+### Source formats
+
+The `source` variable accepts five formats:
+
+| Format | Description |
+|---|---|
+| `https://example.com/pkg-1.0.tar.gz` | A remote URL |
+| `mypkg-1.0.tar.gz::https://example.com/v1.0.tar.gz` | Custom local filename for a remote URL |
+| `https://example.com/pkg.tar.gz::noextract` | Download but do not unpack |
+| `my-file` | A local file in the recipe directory |
+| (empty) | Create a dummy/meta package with only `/usr` |
+
+### Optional recipe variables
+
+| Variable | Purpose |
+|---|---|
+| `build_opt` | Extra flags appended to the auto-detected build system |
+| `build_type` | Force a specific build system (`meson_build`, `configure_build`, `cmake_build`, `python_build`, `perlmodule_build`, `makefile_build`) |
+| `build_dir` | Subdirectory within the extracted source to enter before building |
+| `sv` | Runit service files to install into `/etc/sv` |
+| `skip_patch` | Skip automatic `.patch` / `.diff` application |
+| `patch_opt` | Options for `patch` (default: `-p1`) |
+| `keep_static` | Keep `*.a` static libraries |
+| `keep_libtool` | Keep `*.la` libtool archives |
+| `keep_locale` | Keep locale files |
+| `keep_doc` | Keep documentation |
+| `no_strip` | Skip ELF binary stripping |
+
+### Build hooks
+
+If a `build()` function is defined, it replaces the auto-detected build system entirely. Use `$SRC` (source extraction directory) and `$PKG` (fakeroot staging directory) to compile and install files. Several `DESTDIR`-style variables are pre-exported: `DESTDIR`, `DEST_DIR`, `INSTALLROOT`, `install_root`, `INSTALL_ROOT`.
+
+```sh
+build() {
+ ./configure --prefix=/usr
+ make
+ make DESTDIR=$PKG install
+}
+```
+
+Without `build()`, optional `prebuild()` and `postbuild()` hooks run before and after the auto-detected build system.
+
+### Other recipe files
+
+| File | Purpose |
+|---|---|
+| `depends` | Dependencies, one per line (`#` for comments) |
+| `preinstall` | Script run before the package is built (only during `-i` or `-u`) |
+| `postinstall` | Script run after the package is installed or upgraded |
+| `.shasum` | Source checksums (auto-generated, regenerate with `apkg -g`) |
+| `.files` | Package file list (auto-generated, regenerate with `apkg -k`) |
+
+## Build systems
+
+When no `build()` function is defined, apkg auto-detects the build system by checking for these files in order:
+
+1. **meson.build** — `meson setup` with LTO, PIE, `wrap_mode=nodownload`, `buildtype=plain`
+2. **configure** — `./configure --prefix=/usr --sysconfdir=/etc ...`
+3. **CMakeLists.txt** — `cmake` with `Release` build type, prefers `ninja`
+4. **setup.py** — `python3 setup.py build && install --root=$PKG`
+5. **Makefile.PL** — `perl Makefile.PL && make && make install`
+6. **Makefile / makefile / GNUmakefile** — raw `make` with standard prefix variables
+
+See `doc/defaultbuildopts` for the exact flags used by each build system.
+
+### Post-build processing
+
+After compilation, apkg automatically:
+- Compresses man pages (man1–man8, gzip) and info pages
+- Removes common conflict files (`fonts.dir`, `fonts.scale`, `perllocal.pod`, `charset.alias`)
+- Removes static libraries (`*.a`), libtool archives (`*.la`), locales, and docs (unless kept via `keep_*`)
+- Strips ELF binaries (`--strip-all`), shared objects (`--strip-unneeded`), and static archives (`--strip-debug`)
+- Merges `/bin`, `/sbin`, `/usr/sbin` into `/usr/bin` if `APKG_BINMERGE` is set
+
+## Triggers
+
+After install or upgrade, apkg can automatically refresh system caches when the package provides relevant files:
+
+- **fontconfig** — `fc-cache -sf`
+- **GDK-Pixbuf** — `gdk-pixbuf-query-loaders --update-cache`
+- **GIO modules** — `gio-querymodules /usr/lib/gio/modules`
+- **GSettings schemas** — `glib-compile-schemas /usr/share/glib-2.0/schemas`
+- **GTK2/GTK3 input methods** — `gtk-query-immodules-2.0/3.0 --update-cache`
+- **Icon themes** — `gtk-update-icon-cache`
+- **udev hardware database** — `udevadm hwdb --update`
+- **X font indices** — `mkfontdir` / `mkfontscale`
+- **Desktop MIME cache** — `update-desktop-database`
+- **Shared MIME database** — `update-mime-database /usr/share/mime`
+
+Run `apkg -t` to trigger these manually for all installed packages.
+
+## Environment variables
+
+### apkg
+
+| Variable | Default | Purpose |
+|---|---|---|
+| `APKG_REPO` | `$PWD` | Space-separated repo directories (first match wins) |
+| `APKG_PACKAGE_DIR` | `$PWD` | Where built `.spm` files are stored |
+| `APKG_SOURCE_DIR` | `$PWD` | Source tarball cache directory |
+| `APKG_WORK_DIR` | `$PWD` | Build working tree (extraction + fakeroot) |
+| `APKG_ROOT` | `/` | Alternative install root |
+| `APKG_NOPROMPT` | (unset) | Skip confirmation prompt (for scripting) |
+| `APKG_KEEP_WORKDIR` | (unset) | Keep build tree on failure (for debugging) |
+| `APKG_ALIAS` | (unset) | Dependency substitution: `real:alias` pairs |
+| `APKG_MASK` | (unset) | Packages to skip during `-l` and `-U` |
+| `APKG_BINMERGE` | (unset) | Merge bin/sbin dirs into `/usr/bin` |
+| `APKG_LOG` | (unset) | Enable build logging |
+| `APKG_LOG_DIR` | (unset) | Log file directory (filename: `$name.log`) |
+
+### reposync
+
+| Variable | Format | Purpose |
+|---|---|---|
+| `REPOSYNC_<name>` | `url\|branch\|path` | Define a git repo to sync |
+
+## Bugs
+
+Issue tracker: [codeberg.org/emmett1/autils/issues](https://codeberg.org/emmett1/autils/issues)
+
+## License
+
+See [LICENSE](./LICENSE).
diff --git a/apkg b/apkg
index e3dd428..74373d6 100755
--- a/apkg
+++ b/apkg
@@ -5,12 +5,13 @@
# \ \_\ \_\\ \_\ \ \_\ \_\\ \_____\
# \/_/\/_/ \/_/ \/_/\/_/ \/_____/
#
-# APKG - Alice Package Manager (C) 2023-2025 Emmett1
+# APKG - Alice Package Manager (C) 2023-2026 Emmett1
#
fetch_src() {
[ "$source" ] || return 0
for i in $source; do
+ unset resume
i=${i%::noextract}
case $i in
*::*) sn=${i%::*};;
@@ -239,8 +240,9 @@ build_src() {
fi
elif [ -d $name-$version ]; then
build_dir=$name-$version
- elif [ -d "$(ls -1 --group-directories-first | head -n1)" ]; then
- build_dir=$(ls -1 --group-directories-first | head -n1)
+ elif [ -d "$(ls -1d */ 2>/dev/null | head -n1)" ]; then
+ build_dir=$(ls -1d */ 2>/dev/null | head -n1)
+ build_dir=${build_dir%/}
fi
# cd into extracted source directory
@@ -291,13 +293,14 @@ build_src() {
esac
rm -rf $m
done
- for i in $(find $PKG/usr/share/man -type f); do
- [ $i = ${i%%.gz} ] || continue
- gzip -9 $i
+ find $PKG/usr/share/man -type f | while IFS= read -r i; do
+ [ "$i" = "${i%%.gz}" ] || continue
+ gzip -9 "$i"
done
- for i in $(find $PKG/usr/share/man -type l) ; do
- ln -s $(readlink $i).gz ${i%.gz}.gz
- rm $i
+ find $PKG/usr/share/man -type l | while IFS= read -r i; do
+ [ "$i" = "${i%%.gz}" ] || continue
+ ln -s "$(readlink "$i").gz" "${i%.gz}.gz"
+ rm "$i"
done
fi
@@ -333,9 +336,14 @@ build_src() {
# strip binaries and libraries
if [ ! "$no_strip" ]; then
- find $PKG | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs ${CROSS_COMPILE}strip --strip-all 2>/dev/null
- find $PKG | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs ${CROSS_COMPILE}strip --strip-unneeded 2>/dev/null
- find $PKG | xargs file | grep "current ar archive" | cut -f 1 -d : | xargs ${CROSS_COMPILE}strip --strip-debug 2>/dev/null
+ find $PKG -type f -exec file {} + | while read -r line; do
+ f=${line%%: *}
+ case $line in
+ *ELF*executable*) ${CROSS_COMPILE}strip --strip-all "$f" 2>/dev/null;;
+ *ELF*shared\ object*) ${CROSS_COMPILE}strip --strip-unneeded "$f" 2>/dev/null;;
+ *current\ ar\ archive*) ${CROSS_COMPILE}strip --strip-debug "$f" 2>/dev/null;;
+ esac
+ done
fi
# usrmerge
@@ -369,28 +377,17 @@ build_src() {
ret 1
fi
- # temporary: for backward compatibility
- if [ "$(grep '#MARKER' /usr/bin/spm)" ]; then
- cd $PKG
- spm -b $packagefile || {
- msg "Failed packaging $packagefile"
- ret 1
- }
- else
- cd $APKG_PACKAGE_DIR
- spm -b $PKG && {
- mv package.spm $packagefile
- } || {
- msg "Failed packaging $packagefile"
- ret 1
- }
- fi
+ cd $PKG
+ spm -b $packagefile || {
+ msg "Failed packaging $packagefile"
+ ret 1
+ }
+ cd - >/dev/null
- if [ ! -f "$apkg_list" ] || [ "$apkg_build" -nt "$apkg_list" ]; then
+ if [ ! -f "$apkg_list" ] || [ -n "$(find "$apkg_build" -newer "$apkg_list")" ]; then
pkg_updatefiles
fi
- cd $HERE
remove_workdir
}
@@ -429,11 +426,11 @@ checkdep() {
[ -s $SPM_PKGDB/$ii ] && continue
fi
# if deps already in process list, skip, cycle deps detected
- printf "%s\n" $process | tr ' ' '\n' | grep -qx $ii && continue
+ printf "%s\n" $process | tr ' ' '\n' | grep -Fxq "$ii" && continue
# skip if itself in depends list
[ "$ii" = "$1" ] && continue
# skip if pkg already in deps list
- printf "%s\n" $DEPS | tr ' ' '\n' | grep -x $ii && continue
+ printf "%s\n" $DEPS | tr ' ' '\n' | grep -Fx "$ii" && continue
# check deps
checkdep $ii
done
@@ -444,7 +441,7 @@ checkdep() {
pkg_deplist() {
for i in $@; do
# if already have in list deps, dont check again
- if [ ! $(printf "%s\n" $DEPS | tr ' ' '\n' | grep -x $i) ]; then
+ if [ ! $(printf "%s\n" $DEPS | tr ' ' '\n' | grep -Fx "$i") ]; then
checkdep $i
fi
done
@@ -462,7 +459,7 @@ pkg_dependents() {
for r in $APKG_REPO; do
rr="$rr $r/*/depends"
done
- grep -x $1 $rr 2>/dev/null | rev | cut -d / -f 2 | rev
+ grep -Fx "$1" $rr 2>/dev/null | rev | cut -d / -f 2 | rev
}
pkg_depends() {
@@ -487,7 +484,7 @@ pkg_outdate() {
verbose=1 pkg_allinstalled | while read -r n v; do
if [ "$mask" ]; then
[ "$APKG_MASK" ] && {
- printf "%s\n" "$APKG_MASK" | tr ' ' '\n' | grep -xq $n && continue
+ printf "%s\n" "$APKG_MASK" | tr ' ' '\n' | grep -Fxq "$n" && continue
}
fi
[ "$(pkg_path $n)" ] || continue
@@ -515,7 +512,7 @@ pkg_sysup() {
msg "Solving dependencies..."
for p in $(pkg_deplist $od); do
[ -s $SPM_PKGDB/$p ] || ni="$ni $p"
- printf "%s\n" $od | tr ' ' '\n' | grep -qx $p && pu="$pu $p"
+ printf "%s\n" $od | tr ' ' '\n' | grep -Fxq "$p" && pu="$pu $p"
done
if [ "$ni" ]; then
newpkg=$(printf "%s\n" $ni | tr ' ' '\n' | wc -l)
@@ -551,7 +548,7 @@ pkg_search() {
}
}
-pkg_depinstalll() {
+pkg_depinstall() {
needroot
for p in $@; do
if [ -s $SPM_PKGDB/$p ]; then
@@ -822,7 +819,7 @@ updateopts() {
parseopts() {
while [ "$1" ]; do
case $1 in
- -I) pkg_depinstalll "$(parsesubopt "$@")"; exit 0;;
+ -I) pkg_depinstall "$(parsesubopt "$@")"; exit 0;;
-D) pkg_deplist "$(parsesubopt "$@")"; exit 0;;
-r) pkg_remove "$(parsesubopt "$@")"; exit 0;;
-p) pkg_path "$(parsesubopt "$@")"; exit 0;;
diff --git a/apkg-bin b/apkg-bin
deleted file mode 100755
index 75bac29..0000000
--- a/apkg-bin
+++ /dev/null
@@ -1,233 +0,0 @@
-#!/bin/sh
-# apkg-bin - a simple binary package manager helper script
-
-REMOTE="${REMOTE:-https://emmett1.my/pub/alice/packages}"
-PKGDIR="${PKGDIR:-/var/cache/apkg-bin}"
-REPODB="${REPODB:-REPO}"
-DBFILE="$PKGDIR/$REPODB"
-
-usage() {
- echo "Usage: $0 [options]"
- echo " g <path> Generate database from package dir"
- echo " S Sync database from remote server"
- echo " l List packages"
- echo " s <pattern> Search packages"
- echo " a <pkg> Show package info"
- echo " d <pkg...> Download package(s)"
- echo " i <pkg...> Install package(s)"
- echo " u <pkg...> Upgrade/reinstall package(s)"
- echo " c Clean mismatched/unknown packages"
- exit 0
-}
-
-msg() {
- m=${pkg%#*}
- echo "[${m:-...}] $*"
-}
-
-pkg_existence() {
- need_db
- [ "$(cut -d '#' -f1 "$DBFILE" | grep -x "$1" | uniq)" ] || return 1
- return 0
-}
-
-get_pkg() {
- for p in $@; do
- pkg_existence $p && pkg="$pkg $p" || msg "No package found matching: $p"
- done
-}
-
-get_entry() {
- entry=$(grep ^$1# "$DBFILE" | sort -V -t'#' -k2 | tail -n1)
-}
-
-need_db() {
- [ -f "$DBFILE" ] || { msg "Run '$0 S' first to sync database."; exit 1; }
-}
-
-need_root() {
- [ $(id -u) = 0 ] || { msg "This option need root access."; exit 1; }
-}
-
-fetch_pkg() {
- get_entry $1
- expected_sha=$(echo "$entry" | cut -d'|' -f4)
- pkg=$(echo "$entry" | cut -d'|' -f1)
-
- mkdir -p "$PKGDIR"
- if [ -f "$PKGDIR/$pkg" ]; then
- msg "$PKGDIR/$pkg found."
- else
- url="$REMOTE/$(echo "$pkg" | sed 's/#/%23/g')"
- msg "Downloading $url..."
- curl -fsSLo "$PKGDIR/$pkg" "$url" || { msg "Download failed: $pkg" >&2; return 1; }
- fi
-
- actual_sha=$(sha256sum "$PKGDIR/$pkg" | awk '{print $1}')
- if [ "$expected_sha" = "$actual_sha" ]; then
- msg "Verification PASSED: $pkg"
- else
- msg "Verification FAILED: $pkg" >&2
- rm -f "$pkg"
- return 1
- fi
-
- if [ "$mode" ]; then
- spm $mode "$PKGDIR/$pkg"
- fi
-}
-
-generate_db() {
- [ -d "$1" ] || { msg "Invalid path: $1"; exit 1; }
- > "$1/$REPODB"
- msg "Generating database, please wait..."
- for f in "$1"/*.spm; do
- [ -f "$f" ] || continue
- size=$(stat -c%s "$f")
- mtime=$(stat -c%Y "$f")
- sha=$(sha256sum "$f" | awk '{print $1}')
- name=$(basename "$f")
- echo "$name|$size|$mtime|$sha" >> "$1/$REPODB"
- done
- msg "Database generated at $1/$REPODB"
-}
-
-sync_db() {
- need_root
- mkdir -p "${DBFILE%/*}"
- msg "Downloading database $REMOTE/$REPODB"
- curl -fsSo "$DBFILE" "$REMOTE/$REPODB" || { msg "Failed to sync $REPODB"; exit 1; }
- msg "Database synced to $DBFILE"
-}
-
-list_pkg() {
- need_db
- cut -d'|' -f1 "$DBFILE" | sed 's/#/ /g;s/.spm//g'
-}
-
-search_pkg() {
- need_db
- cut -d '|' -f1 "$DBFILE" | grep -i "$1" | sed 's/#/ /g;s/.spm//g'
- exit 0
-}
-
-info_pkg() {
- need_db
- get_pkg $@
- for p in $pkg; do
- get_entry $p
- name=$p
- verrel=$(echo "$entry" | cut -d '#' -f2 | sed 's/\.spm.*//')
- size=$(echo "$entry" | cut -d '|' -f2)
- mtime=$(echo "$entry" | cut -d '|' -f3)
- sha=$(echo "$entry" | cut -d '|' -f4)
-
- # convert size
- if [ "$size" -lt 1024 ]; then
- hsize="${size} B"
- elif [ "$size" -lt 1048576 ]; then
- hsize="$(awk "BEGIN{printf \"%.1f\", $size/1024}") KB"
- else
- hsize="$(awk "BEGIN{printf \"%.1f\", $size/1048576}") MB"
- fi
-
- # convert date
- hdate=$(date -d @"$mtime" '+%Y-%m-%d %H:%M:%S')
-
- echo "Package: $name"
- echo "Version: $verrel"
- echo "Size: $hsize"
- echo "Date: $hdate"
- echo "SHA256: $sha"
- done
-}
-
-download_pkg() {
- need_db
- get_pkg $@
- for p in $pkg; do
- fetch_pkg $p
- done
-}
-
-install_pkg() {
- need_root
- need_db
- get_pkg $@
- for p in $pkg; do
- [ "$(spm -a | grep -x $p)" ] && {
- msg "Package '$p' is installed, skipped."
- } || {
- pkg2="$pkg2 $p"
- }
- done
- for p in $pkg2; do
- mode='-i' fetch_pkg $p
- done
-}
-
-upgrade_pkg() {
- need_root
- need_db
- get_pkg $@
- for p in $pkg; do
- [ "$(spm -a | grep -x $p)" ] || {
- msg "Package '$p' not installed, skipped."
- } && {
- pkg2="$pkg2 $p"
- }
- done
- for p in $pkg2; do
- mode='-u' fetch_pkg $p
- done
-}
-
-clean_pkg() {
- need_db
- need_root
- msg "Checking local packages in $PKGDIR..."
- known_pkgs=$(cut -d '|' -f1 "$DBFILE")
- for f in "$PKGDIR"/*.spm; do
- [ -f "$f" ] || continue
- fname=${f##*/}
- if echo "$known_pkgs" | grep -qx "$fname"; then
- entry=$(grep "^$fname|" "$DBFILE")
- expected_size=$(echo "$entry" | cut -d'|' -f2)
- expected_sha=$(echo "$entry" | cut -d'|' -f4)
- actual_size=$(stat -c%s "$f")
- actual_sha=$(sha256sum "$f" | awk '{print $1}')
- if [ "$expected_size" != "$actual_size" ] || [ "$expected_sha" != "$actual_sha" ]; then
- msg "Mismatch: $fname (removed)"
- rm -f "$f"
- fi
- else
- msg "Unknown package: $fname (removed)"
- rm -f "$f"
- fi
- done
- msg "Cleanup done."
-}
-
-main() {
- if [ ! "$1" ]; then
- usage
- else
- case $1 in
- g) generate_db $2 ;;
- S) sync_db ;;
- l) list_pkg ;;
- s) search_pkg $2 ;;
- a) shift; info_pkg $@ ;;
- d) shift; download_pkg $@ ;;
- i) shift; install_pkg $@ ;;
- u) shift; upgrade_pkg $@ ;;
- c) clean_pkg ;;
- *) usage ;;
- esac
- exit 0
- fi
-}
-
-main $@
-
-exit 0
diff --git a/apkg-genabuild b/apkg-genabuild
index 1882ec7..1882ec7 100644..100755
--- a/apkg-genabuild
+++ b/apkg-genabuild
diff --git a/apkg-outdated b/apkg-outdated
deleted file mode 100755
index 9963f08..0000000
--- a/apkg-outdated
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh
-
-[ "$1" ] || {
- echo "script to check outdated package from repology"
- echo " usage: $0 <port path> <port path> ..."
- echo
- exit 1
-}
-
-while [ "$1" ]; do
- unset curver port
- [ -f $1/abuild ] && port=$(realpath $1)
- [ "$port" ] || { shift; continue; }
- repo=${port%/*}; repo=${repo##*/}
- pname=${1##*/}
- curver=$(grep ^version= $port/abuild | awk -F = '{print $2}')
- [ "$curver" ] || { shift; continue; }
- if [ -s $1/outdated ]; then
- pname=$(tail -n1 $1/outdated)
- else
- case $pname in
- python-*) pname=python:${pname#python-};;
- esac
- fi
- newver=$(curl -s -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36" https://repology.org/badge/latest-versions/$pname.svg | grep middle | sed 's/.*middle">//;s/<.*//;s/,//' | tr ' ' '\n' | tail -n1)
- if [ "$newver" = "-" ]; then
- echo "$repo/${1##*/} 404 ($curver)"
- elif [ "$curver" != "$newver" ]; then
- echo "$repo/${1##*/} $newver ($curver)"
- fi
- shift
-done
diff --git a/apkg-reposync b/apkg-reposync
deleted file mode 100755
index 6b275c1..0000000
--- a/apkg-reposync
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/sh
-
-APKG_CONF="${APKG_CONF:-/etc/apkg.conf}"
-temp_repos_file=$(mktemp)
-write_permission=0
-
-die() {
- [ "$1" ] && echo "error: $1"
- rm -f "$temp_repos_file"
- exit 1
-}
-
-find_default_remote() {
- cd "${1}" || die "cannot cd to <${1}> the repo"
- default_remote=$(git branch --list "$(git branch --show-current)" \
- "--format=%(upstream:remotename)")
-}
-
-find_current_branch() {
- cd "${1}" || die "cannot cd to the <${1}> repo"
- current_branch=$(git remote show "${default_remote}" | sed -n '/HEAD branch/s/.*: //p')
-}
-
-check_write_permissions() {
- random_file=$(find "${1}" -type f -print0 | shuf -z -n 1)
- test -w "$random_file" || write_permission=$((write_permission+1))
-}
-
-source_and_sanity_checks() {
-[ ! -e "$(realpath "${APKG_CONF}")" ] && die "There is no configuration file in ${APKG_CONF}! Exiting..."
-
-. "${APKG_CONF}"
-
-[ -z "${APKG_REPO}" ] && die "There are no repos configured in $APKG_CONF, exiting..."
-
-for r in ${APKG_REPO}; do
-printf "%s\n" "$r" >> "$temp_repos_file"
-check_write_permissions "$r"; done
-[ "$write_permission" = 0 ] || die "You need to execute the script as root!"
-printf "%s\n" "Configured repos:" && awk ' {print $0} ' "$temp_repos_file"
-grep -q "alicelinux/repos/core" "$temp_repos_file" || die "No official repos configured in $APKG_CONF"
-}
-
-sync_official() {
- # This assumes the current repo structure.
- dir_for_official_repo=$(grep alicelinux/repos/core "$temp_repos_file")
- [ -d "$dir_for_official_repo" ] || die "No $dir_for_official_repo exists, exiting..."
- dir_for_official_repo=$(echo "$dir_for_official_repo" | sed "s/repos\/core//")
- printf "%s\n" "[~> Syncing official repos in <$dir_for_official_repo> ...]"
- find_default_remote "$dir_for_official_repo"
- find_current_branch "$dir_for_official_repo"
- git pull "$default_remote" "$current_branch" || die "Cannot pull from $default_remote/$current_branch for the ofixial repos"
- [ "$?" = 0 ] && printf "%s\n" "[~> Successfully synced the <official> repo!]"
-}
-
-sync_or_skip() {
- # Remove all official repo lines from the temp_repos_file
- unofficial_repos=$(grep -v alicelinux/repos "$temp_repos_file" | tr "\n" " ")
- for r in $unofficial_repos; do
- if [ -d "$r"/.git ]; then
- find_default_remote "$r"
- find_current_branch "$r"
- git pull "$default_remote" "$current_branch" || die "Cannot pull from $default_remote/$current_branch"
- else
- printf "%s\n" "[~>Repo in <$r> is not a git repo, skipping...]"
- fi
- done
-}
-
-source_and_sanity_checks
-sync_official
-sync_or_skip
-[ "$?" = 0 ] && echo "[~> Repo(s) succesfully synced!]" && rm -f "temp_repos_file"
diff --git a/man/apkg-chroot.8 b/man/apkg-chroot.8
new file mode 100644
index 0000000..65bdd1d
--- /dev/null
+++ b/man/apkg-chroot.8
@@ -0,0 +1,42 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH APKG-CHROOT 8
+.SH NAME
+apkg-chroot \- enter a chroot environment for package building
+.SH DESCRIPTION
+.LP
+\fBapkg-chroot\fR enters a chroot environment suitable for package building and
+system maintenance. It mounts the required virtual filesystems (\fI/dev\fR,
+\fI/proc\fR, \fI/sys\fR, \fI/run\fR), copies the host's \fI/etc/resolv.conf\fR,
+and executes a command inside the chroot (default: \fI/bin/sh\fR). All mounts are
+cleaned up on exit.
+.SH USAGE
+.LP
+\f(CRapkg-chroot <chroot-dir> [command]\fR
+.PP
+If \fIcommand\fR is not specified, \fB/bin/sh\fR is launched.
+The script must be run as root.
+.SH ENVIRONMENT
+.TP
+\fBHOME\fR
+Set to \fI/root\fR inside the chroot.
+.TP
+\fBTERM\fR
+Passed through from the host.
+.TP
+\fBPATH\fR
+Set to \fI/bin:/usr/bin:/sbin:/usr/sbin\fR.
+.SH EXAMPLES
+.LP
+\f(CRapkg-chroot /mnt/alice\fR - Enter a chroot and launch an interactive shell.
+.PP
+\f(CRapkg-chroot /mnt/alice apkg -i mypkg\fR - Run apkg inside the chroot.
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+.SH REPORTING BUGS
+.LP
+Please report bugs and issues in the project issue tracker: \c
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
diff --git a/man/apkg-clean.8 b/man/apkg-clean.8
new file mode 100644
index 0000000..6cca0f2
--- /dev/null
+++ b/man/apkg-clean.8
@@ -0,0 +1,36 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH APKG-CLEAN 8
+.SH NAME
+apkg-clean \- clean up unreferenced package and source files
+.SH DESCRIPTION
+.LP
+\fBapkg-clean\fR scans the package and source directories and prints paths to
+files that are no longer referenced by any current package recipe. Output is
+intended to be piped to \fBxargs rm\fR for cleanup.
+.SH OPTIONS
+.TP
+\fB-p\fR
+Print unreferenced package files (\fI*.spm\fR) only.
+.TP
+\fB-s\fR
+Print unreferenced source files only.
+.TP
+\fB-h\fR
+Print help message.
+.SH EXAMPLES
+.LP
+\f(CRapkg-clean\fR - Print all unreferenced files (packages and sources).
+.PP
+\f(CRapkg-clean | xargs rm -v\fR - Remove all unreferenced package and source files.
+.PP
+\f(CRapkg-clean -p | xargs rm\fR - Remove only unreferenced package files.
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+.SH REPORTING BUGS
+.LP
+Please report bugs and issues in the project issue tracker: \c
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
diff --git a/man/apkg-deps.8 b/man/apkg-deps.8
new file mode 100644
index 0000000..20098f9
--- /dev/null
+++ b/man/apkg-deps.8
@@ -0,0 +1,33 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH APKG-DEPS 8
+.SH NAME
+apkg-deps \- show runtime library dependencies of an installed package
+.SH DESCRIPTION
+.LP
+\fBapkg-deps\fR examines the runtime library dependencies of an installed package.
+It uses \fBldd\fR to find shared libraries required by the package's binaries and
+libraries, then maps those libraries back to the packages that provide them.
+Useful for discovering implicit runtime dependencies that may not be listed
+in the package's formal dependency list.
+.SH USAGE
+.LP
+\f(CRapkg-deps <package>\fR
+.PP
+The package must already be installed on the system.
+.SH OUTPUT
+.LP
+Lists packages that provide shared libraries used by the specified package,
+excluding the package itself and common base packages (gcc, musl, binutils, glibc).
+.SH EXAMPLES
+.LP
+\f(CRapkg-deps mypkg\fR - Show runtime library dependencies for mypkg.
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+.SH REPORTING BUGS
+.LP
+Please report bugs and issues in the project issue tracker: \c
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
diff --git a/man/apkg-foreign.8 b/man/apkg-foreign.8
new file mode 100644
index 0000000..0a2fbe9
--- /dev/null
+++ b/man/apkg-foreign.8
@@ -0,0 +1,29 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH APKG-FOREIGN 8
+.SH NAME
+apkg-foreign \- list installed packages not found in any repository
+.SH DESCRIPTION
+.LP
+\fBapkg-foreign\fR lists all installed packages that are not present in any
+configured repository. These "foreign" packages may have been installed
+from an external source or whose build recipes have since been removed.
+.SH USAGE
+.LP
+\f(CRapkg-foreign\fR
+.PP
+The script takes no arguments and produces one package name per line.
+.SH EXAMPLES
+.LP
+\f(CRapkg-foreign\fR - List all foreign packages.
+.PP
+\f(CRapkg-foreign | wc -l\fR - Count the number of foreign packages.
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+.SH REPORTING BUGS
+.LP
+Please report bugs and issues in the project issue tracker: \c
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
diff --git a/man/apkg-genabuild.8 b/man/apkg-genabuild.8
new file mode 100644
index 0000000..69124b7
--- /dev/null
+++ b/man/apkg-genabuild.8
@@ -0,0 +1,35 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH APKG-GENABUILD 8
+.SH NAME
+apkg-genabuild \- generate an abuild recipe template from a source URL
+.SH DESCRIPTION
+.LP
+\fBapkg-genabuild\fR generates an \fIabuild\fR template file from a source URL.
+It attempts to parse the package name and version from the URL and creates
+a directory with a skeleton \fIabuild\fR recipe.
+.SH USAGE
+.LP
+\f(CRapkg-genabuild <url> [name]\fR
+.PP
+If \fIname\fR is not provided, it is derived from the URL.
+Special handling is included for GitHub tag archives, PyPI packages, and
+CPAN/Perl packages, which get the appropriate prefix (\fIpython-\fR or \fIperl-\fR).
+.SH OUTPUT
+.LP
+Creates a directory named after the package containing an \fIabuild\fR file
+with \fIname\fR, \fIversion\fR, \fIrelease\fR, and \fIsource\fR fields populated.
+.SH EXAMPLES
+.LP
+\f(CRapkg-genabuild https://example.com/pkg-1.2.3.tar.gz\fR - Generate template for a tarball.
+.PP
+\f(CRapkg-genabuild https://github.com/user/repo/archive/v1.0.tar.gz\fR - Generate template from a GitHub tag archive.
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+.SH REPORTING BUGS
+.LP
+Please report bugs and issues in the project issue tracker: \c
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
diff --git a/man/apkg-orphan.8 b/man/apkg-orphan.8
new file mode 100644
index 0000000..26b132c
--- /dev/null
+++ b/man/apkg-orphan.8
@@ -0,0 +1,29 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH APKG-ORPHAN 8
+.SH NAME
+apkg-orphan \- list orphan packages with no dependents installed
+.SH DESCRIPTION
+.LP
+\fBapkg-orphan\fR lists orphan packages: packages that are installed and
+exist in a repository, but have no other installed package depending on them.
+These may be safe to remove.
+.SH USAGE
+.LP
+\f(CRapkg-orphan\fR
+.PP
+The script takes no arguments and produces one package name per line.
+.SH EXAMPLES
+.LP
+\f(CRapkg-orphan\fR - List all orphaned packages.
+.PP
+\f(CRapkg-orphan | while read p; do apkg -r "$p"; done\fR - Remove all orphaned packages.
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+.SH REPORTING BUGS
+.LP
+Please report bugs and issues in the project issue tracker: \c
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
diff --git a/man/apkg-purge.8 b/man/apkg-purge.8
new file mode 100644
index 0000000..cbc92cf
--- /dev/null
+++ b/man/apkg-purge.8
@@ -0,0 +1,32 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH APKG-PURGE 8
+.SH NAME
+apkg-purge \- remove a package and its unused dependencies
+.SH DESCRIPTION
+.LP
+\fBapkg-purge\fR removes a package and all its dependencies that are no longer
+required by any other installed package. This is a "deep" removal compared to
+\fBapkg -r\fR which only removes the specified package.
+.SH OPTIONS
+.TP
+\fB-p\fR
+Purge (remove from system). Without this flag, the script prints what would be
+removed without taking action (dry-run mode).
+.TP
+\fB-h\fR
+Print help message.
+.SH EXAMPLES
+.LP
+\f(CRapkg-purge mypkg\fR - Show what would be removed when purging mypkg.
+.PP
+\f(CRapkg-purge -p mypkg\fR - Actually purge mypkg and its now-unused dependencies.
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+.SH REPORTING BUGS
+.LP
+Please report bugs and issues in the project issue tracker: \c
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
diff --git a/man/apkg-redundantdeps.8 b/man/apkg-redundantdeps.8
new file mode 100644
index 0000000..5169e07
--- /dev/null
+++ b/man/apkg-redundantdeps.8
@@ -0,0 +1,35 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH APKG-REDUNDANTDEPS 8
+.SH NAME
+apkg-redundantdeps \- find and fix redundant dependencies
+.SH DESCRIPTION
+.LP
+\fBapkg-redundantdeps\fR finds redundant entries in package dependency files.
+A dependency is considered redundant if it is already pulled in by another
+listed dependency (transitive dependency). This helps keep \fIdepends\fR files
+clean by listing only direct dependencies.
+.SH OPTIONS
+.TP
+\fB-f\fR
+Fix mode: remove the redundant dependencies from the \fIdepends\fR files.
+Without this flag, the script prints redundant entries without modifying anything.
+.TP
+\fB-h\fR
+Print help message.
+.SH EXAMPLES
+.LP
+\f(CRapkg-redundantdeps mypkg\fR - Check mypkg for redundant dependencies.
+.PP
+\f(CRapkg-redundantdeps\fR - Check all packages in configured repos.
+.PP
+\f(CRapkg-redundantdeps -f mypkg\fR - Remove redundant dependencies from mypkg.
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+.SH REPORTING BUGS
+.LP
+Please report bugs and issues in the project issue tracker: \c
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
diff --git a/man/apkg.8 b/man/apkg.8
new file mode 100644
index 0000000..b810666
--- /dev/null
+++ b/man/apkg.8
@@ -0,0 +1,368 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH APKG 8
+.SH NAME
+apkg \- Alice Linux package build and install tool
+.SH DESCRIPTION
+.LP
+\fBapkg\fR is the package manager for Alice Linux. It builds packages from source
+using \fIabuild\fR recipe files and installs them through the \fBspm\fR(8) backend.
+
+It operates in two modes: when given a package name, it locates the recipe in
+\fBAPKG_REPO\fR and processes it; when run from inside a package directory, it
+uses the \fIabuild\fR file in the current directory directly.
+
+The build pipeline is: fetch sources \f[R] checksum verification \f[R] extract
+\f[R] auto-detect build system \f[R] patch \f[R] compile \f[R] post-process
+(strip, compress man pages, remove conflicts) \f[R] package into \fI.spm\fR
+format \f[R] install/upgrade via \fBspm\fR.
+
+.SH OPTIONS
+.TP
+\fB\-h\fR
+Print help and exit.
+.TP
+\fB\-i\fR \fI<pkg...>\fR
+Build and install package(s). Skips packages already installed. Does not
+resolve dependencies; use \fB\-I\fR for that.
+.TP
+\fB\-I\fR \fI<pkg...>\fR
+Install package(s) with all dependencies resolved recursively. Prompts for
+confirmation unless \fBAPKG_NOPROMPT\fR is set.
+.TP
+\fB\-u\fR \fI<pkg...>\fR
+Upgrade (rebuild and reinstall) package(s). Skips packages not currently installed.
+.TP
+\fB\-U\fR
+System upgrade. Checks all installed packages for outdated versions, resolves
+dependencies for the full upgrade set, installs new packages first, then
+upgrades existing ones. Respects \fBAPKG_MASK\fR.
+.TP
+\fB\-f\fR
+Force rebuild even if an existing \fI.spm\fR package file is found.
+.TP
+\fB\-r\fR \fI<pkg...>\fR
+Remove (uninstall) package(s) via \fBspm \-r\fR. Requires root.
+.TP
+\fB\-o\fR \fI<pkg...>\fR
+Download sources only; do not build or install.
+.TP
+\fB\-d\fR \fI<pkg>\fR
+List direct dependencies of a package (from its \fIdepends\fR file).
+Respects \fBAPKG_ALIAS\fR.
+.TP
+\fB\-D\fR \fI<pkg...>\fR
+List all dependencies recursively in install order (dependencies before
+dependents). Detects and skips dependency cycles.
+.TP
+\fB\-j\fR \fI<pkg>\fR
+List reverse dependencies \-- packages that list the given package in their
+\fIdepends\fR file.
+.TP
+\fB\-p\fR \fI<pkg>\fR
+Print the filesystem path to the package's recipe directory. Searches each
+directory in \fBAPKG_REPO\fR in order; the first match wins.
+.TP
+\fB\-s\fR \fI<pattern>\fR
+Search for packages by name across all configured repos. With \fB\-v\fR, also
+prints the version from the \fIabuild\fR file.
+.TP
+\fB\-S\fR \fI<pattern>\fR
+Search package file lists (the \fI.files\fR files in each repo) for a pattern.
+Prints the repo path and matching filename.
+.TP
+\fB\-a\fR
+List all installed packages. With \fB\-v\fR, also prints the installed version.
+.TP
+\fB\-l\fR
+List outdated packages by comparing each installed package's version against
+the version available in the repo. Respects \fBAPKG_MASK\fR.
+.TP
+\fB\-g\fR \fI<pkg>\fR
+Generate or update the \fI.shasum\fR checksum file for the package's source files.
+Uses \fBsha3sum\fR by default.
+.TP
+\fB\-k\fR \fI<pkg>\fR
+Regenerate the \fI.files\fR file listing from the built \fI.spm\fR package.
+.TP
+\fB\-t\fR \fI<pkg...>\fR
+Run post-install triggers: fontconfig cache, GDK-Pixbuf loaders, GIO modules,
+GSettings schemas, GTK2/GTK3 input method modules, icon theme cache, udev
+hardware database, X font indices, desktop MIME cache, and shared MIME database.
+Only triggers that are relevant to the package's installed files are executed.
+With no arguments, triggers all installed packages.
+.TP
+\fB\-v\fR
+Verbose output. Affects \fB\-s\fR (show versions), \fB\-a\fR (show versions),
+and \fB\-l\fR (internal use).
+
+.SH ABUILD RECIPE FORMAT
+.LP
+An \fIabuild\fR file is a POSIX shell snippet sourced by \fBapkg\fR. The
+directory containing it must be named identically to the \fBname\fR variable.
+
+.SS Required variables
+.TP
+\fBname\fR
+Package name. Must match the parent directory name.
+.TP
+\fBversion\fR
+Upstream version string. Used in source URLs via \fB$name\fR and \fB$version\fR.
+.TP
+\fBrelease\fR
+Integer starting at 1. Increment on each rebuild; reset to 1 when \fBversion\fR
+changes.
+
+.SS Optional variables
+.TP
+\fBsource\fR
+Whitespace-separated list of source files. Five formats are accepted:
+.RS
+.IP \- 2
+\fI<url>\fR \-- a source tarball URL (e.g. \fIhttps://example.com/$name-$version.tar.gz\fR)
+.IP \- 2
+\fI<filename>::<url>\fR \-- custom local filename for the downloaded source
+.IP \- 2
+\fI<url>::noextract\fR \-- download but do not unpack
+.IP \- 2
+\fI<filename>\fR \-- a local file in the recipe directory (not downloaded)
+.IP \- 2
+\fI<filename>::noextract\fR \-- a local file, not extracted
+.RE
+.IP
+If \fBsource\fR is empty, a dummy (meta) package is created containing only
+\fI/usr\fR.
+.TP
+\fBbuild_opt\fR
+Extra flags passed to the build system (appended after the defaults).
+.TP
+\fBsv\fR
+Runit service files to install into \fI/etc/sv\fR. Accepts names like \fIrun\fR,
+\fIfinish\fR, \fI<name>.run\fR, \fI<name>.finish\fR.
+.TP
+\fBbuild_type\fR
+Force a specific build system. Normally auto-detected; set to one of:
+\fImeson_build\fR, \fIconfigure_build\fR, \fIcmake_build\fR, \fIpython_build\fR,
+\fIperlmodule_build\fR, \fImakefile_build\fR.
+.TP
+\fBbuild_dir\fR
+Subdirectory within the extracted source to enter before building.
+.TP
+\fBskip_patch\fR
+If set to 1, skip automatic patch application (so \fIbuild()\fR can call
+\fBapply_patch\fR manually).
+.TP
+\fBpatch_opt\fR
+Options passed to \fBpatch\fR(1). Default: \fB\-p1\fR.
+.TP
+\fBkeep_static\fR
+If set, keep \fI*.a\fR static libraries (removed by default).
+.TP
+\fBkeep_libtool\fR
+If set, keep \fI*.la\fR libtool archives (removed by default).
+.TP
+\fBkeep_locale\fR
+If set, keep locale files in \fI/usr/share/locale\fR and \fI/usr/lib/locale\fR.
+.TP
+\fBkeep_doc\fR
+If set, keep documentation in \fI/usr/share/doc\fR and \fI/usr/doc\fR.
+.TP
+\fBno_strip\fR
+If set, skip ELF binary and library stripping.
+
+.SS Build function hooks
+.LP
+If a \fBbuild()\fR function is defined, it is called directly (in \fBset \-ex\fR
+mode) and the auto-detection pipeline is bypassed. \fB$SRC\fR and \fB$PKG\fR
+point to the source extraction and fakeroot directories respectively. Several
+\fBDESTDIR\fR-style variables are pre-exported for common build systems:
+\fBDESTDIR\fR, \fBDEST_DIR\fR, \fBINSTALLROOT\fR, \fBinstall_root\fR, and
+\fBINSTALL_ROOT\fR.
+
+If no \fBbuild()\fR function is present, \fBprebuild()\fR (if any) runs first,
+then the auto-detected build system, then \fBpostbuild()\fR (if any).
+
+.SS Other files in the recipe directory
+.TP
+\fBdepends\fR
+One dependency per line. Lines starting with \fB#\fR are comments.
+.TP
+\fBpreinstall\fR
+Executable script run before the package is built (only during \fB\-i\fR or
+\fB\-u\fR).
+.TP
+\fBpostinstall\fR
+Executable script run after the package is installed or upgraded.
+.TP
+\fB.shasum\fR
+Auto-generated checksum file. Regenerate with \fB\-g\fR.
+.TP
+\fB.files\fR
+Auto-generated sorted file list from the package contents. Regenerate with
+\fB\-k\fR.
+
+.SH BUILD SYSTEMS
+.LP
+When no \fBbuild()\fR function is defined, the build type is auto-detected by
+checking for these files in order:
+.IP 1. 3
+\fBmeson.build\fR \-- \fBmeson setup\fR with LTO and PIE enabled,
+\fBwrap_mode=nodownload\fR, \fBbuildtype=plain\fR
+.IP 2. 3
+\fBconfigure\fR \-- \fB./configure --prefix=/usr --sysconfdir=/etc ...\fR
+.IP 3. 3
+\fBCMakeLists.txt\fR \-- \fBcmake\fR with \fBRelease\fR build type,
+\fBninja\fR preferred over \fBmake\fR
+.IP 4. 3
+\fBsetup.py\fR \-- \fBpython3 setup.py build && install --root=$PKG\fR
+.IP 5. 3
+\fBMakefile.PL\fR \-- \fBperl Makefile.PL && make && make install\fR
+.IP 6. 3
+\fBMakefile\fR, \fBmakefile\fR, or \fBGNUmakefile\fR \-- \fBmake\fR with
+standard prefix/sysconfdir variables
+
+.SS Post-build processing
+.LP
+After compilation, \fBapkg\fR automatically:
+.IP \- 2
+Compresses man pages (gzip, keeps only man[1-8] sections) and info pages
+.IP \- 2
+Removes common conflict files (\fIfonts.dir\fR, \fIfonts.scale\fR,
+\fIperllocal.pod\fR, \fIcharset.alias\fR)
+.IP \- 2
+Removes static libraries (\fI*.a\fR), libtool archives (\fI*.la\fR),
+locales, and docs unless the corresponding \fBkeep_*\fR variable is set
+.IP \- 2
+Strips ELF executables (\fB\-\-strip-all\fR), shared objects
+(\fB\-\-strip-unneeded\fR), and static archives (\fB\-\-strip-debug\fR)
+unless \fBno_strip\fR is set
+.IP \- 2
+Merges \fI/bin\fR, \fI/sbin\fR, \fI/usr/sbin\fR into \fI/usr/bin\fR if
+\fBAPKG_BINMERGE\fR is set
+.IP \- 2
+Installs runit service files from the \fBsv\fR variable into \fI/etc/sv\fR
+
+.SH ENVIRONMENT
+.TP
+\fBAPKG_REPO\fR
+Space-separated list of directories containing package recipes. Searched in
+order; the first match wins. Default: current directory.
+.TP
+\fBAPKG_PACKAGE_DIR\fR
+Directory where built \fI.spm\fR packages are stored. Default: current directory.
+.TP
+\fBAPKG_SOURCE_DIR\fR
+Directory for downloaded source tarballs. Default: current directory.
+.TP
+\fBAPKG_WORK_DIR\fR
+Directory for build working trees (subdirectories \fIapkg-src-<name>\fR and
+\fIapkg-pkg-<name>\fR are created and cleaned automatically). Default: current
+directory.
+.TP
+\fBAPKG_ROOT\fR
+Alternative root directory for installation (e.g. for cross-compilation or
+staged installs). Sets \fBSPM_ROOT\fR. Default: \fI/\fR.
+.TP
+\fBAPKG_KEEP_WORKDIR\fR
+If set, do not remove the work directory on build failure (useful for debugging).
+.TP
+\fBAPKG_NOPROMPT\fR
+If set, skip the confirmation prompt in \fB\-I\fR and \fB\-U\fR operations.
+.TP
+\fBAPKG_ALIAS\fR
+Space-separated list of \fIreal:alias\fR pairs for dependency substitution
+(e.g. \fIopenssl:libressl\fR makes packages depending on openssl pull libressl).
+.TP
+\fBAPKG_MASK\fR
+Space-separated list of packages to exclude from \fB\-l\fR and \fB\-U\fR.
+.TP
+\fBAPKG_BINMERGE\fR
+If set, merge \fI/bin\fR, \fI/sbin\fR, and \fI/usr/sbin\fR into
+\fI/usr/bin\fR during packaging.
+.TP
+\fBAPKG_LOG\fR
+If set, enable build logging.
+.TP
+\fBAPKG_LOG_DIR\fR
+Directory for build log files (log filename is \fI$name.log\fR).
+.TP
+\fBCFLAGS\fR, \fBCXXFLAGS\fR
+Compiler flags used by the cmake build system.
+.TP
+\fBCROSS_COMPILE\fR
+Prefix for the \fBstrip\fR command (e.g. \fIx86_64-linux-musl-\fR).
+.TP
+\fBCARGO_HOME\fR, \fBGOCACHE\fR
+Set inside the build environment for Rust and Go builds respectively.
+
+.SH FILES
+.TP
+\fI/var/lib/spm/db/\fR
+SPM package database. Each installed package has a file here whose first line
+is the installed version-release string.
+
+.SH EXAMPLES
+.LP
+Build and install a package:
+.RS
+\f(CRapkg \-i mypkg\fR
+.RE
+.LP
+Install with automatic dependency resolution:
+.RS
+\f(CRapkg \-I firefox\fR
+.RE
+.LP
+Full system upgrade:
+.RS
+\f(CRapkg \-U\fR
+.RE
+.LP
+Search for packages:
+.RS
+\f(CRapkg \-s icon\fR
+.RE
+.LP
+Find which package owns a file:
+.RS
+\f(CRapkg \-S libpng.so\fR
+.RE
+.LP
+List outdated packages:
+.RS
+\f(CRapkg \-l\fR
+.RE
+.LP
+Force rebuild:
+.RS
+\f(CRapkg \-f jupp\fR
+.RE
+.LP
+Check direct dependencies:
+.RS
+\f(CRapkg \-d mypkg\fR
+.RE
+
+.SH SEE ALSO
+.BR apkg-chroot (8),
+.BR apkg-clean (8),
+.BR apkg-deps (8),
+.BR apkg-foreign (8),
+.BR apkg-genabuild (8),
+.BR apkg-orphan (8),
+.BR apkg-purge (8),
+.BR apkg-redundantdeps (8),
+.BR reposync (8),
+.BR revdep (8),
+.BR updateconf (8),
+.BR spm (8)
+
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+
+.SH REPORTING BUGS
+.LP
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
diff --git a/man/apkg.conf.md b/man/apkg.conf.md
deleted file mode 100644
index d4aa590..0000000
--- a/man/apkg.conf.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# NAME
-
-**apkg.conf** - configuration file for apkg
-
-# DESCRIPTION
-
-**apkg.conf** is the configuration file for the **apkg** package manager for the alice linux distribution.
-It resides by default under `/etc` in an alice linux installation.
-The contents are sourced by the **apkg** program and are in the posix shell `key="value"` format.
-
-# CONFIGURATION KEYS
-
-- `APKG_NOPROMPT` If set, it enables non-interactive use by disabling user confirmation prompt.
-- `APKG_PACKAGE_DIR` Directory where the compiled packages will reside.
-- `APKG_SOURCE_DIR` Directory that will hold the downloaded sources.
-- `APKG_WORK_DIR` Directory where the actual building process will take place. This happens in subdirectories which are cleaned after completion.
-- `APKG_LOG` If set, it enables the creation of a log for the program output.
-- `export CFLAGS="<cflags>"` Default <cflags> are *-O3 -march=x86-64 -pipe*
-- `export CXXFLAGS="$CFLAGS"`
-- `export NINJAJOBS="<-x>"` Replace <-x> with the number of jobs the ninja build system with use. Without this it will use the maximum amount of threads the processor suports.
-- `export MAKEFLAGS="-jx"` Replace <x> with the number of jobs the make build system with use.
-
-EXAMPLES
-
-```
-### example of a valid apkg.conf ###
-export CFLAGS="-O3 -march=x86-64 -pipe"
-export CXXFLAGS="$CFLAGS"
-export MAKEFLAGS="-j12"
-export NINJAJOBS="12"
-APKG_REPO="/var/lib/alicelinux/repos/core /var/lib/alicelinux/repos/extra /var/lib/alicelinux/repos/xorg /var/lib/alicelinux/repos/wayland"
-APKG_PACKAGE_DIR=/var/cache/pkg
-APKG_SOURCE_DIR=/var/cache/src
-APKG_WORK_DIR=/var/cache/work
-```
-
-# AUTHORS
-
-emmett1 <emmett1.2miligrams@protonmail.com> Author of the program and creator of alice linux.
-
-mobinmob <mobinmob@disroot.org> Author of the man page.
-
-# REPORTING BUGS
-
-**apkg** is in a working stage but also under heavy development. Please report and bugs/issues in the project issue tracker: https://codeberg.org/emmett1/autils/issues
diff --git a/man/apkg.md b/man/apkg.md
deleted file mode 100644
index a692d1e..0000000
--- a/man/apkg.md
+++ /dev/null
@@ -1,72 +0,0 @@
-# NAME
-
-**apkg** - package building tool and package manager for alice linux
-
-# SYNOPSIS
-
-**apkg** [-i] [-I] [-d] [-D] [-j] [-u] [-r] [-t] [-U ] [-f] [-o] [-p] [-s] [-g] [-h] [*pkg(s)*]
-
-# DESCRIPTION
-
-**apkg** is the package build tool and package installer, along with **spm** for the alice linux distribution.
-It is written in posix shell with the goal to be simple and effective. It can consume package building templates in the abuild format
-and automate the building and installing of packages.
-
-# OPTIONS
-
-Arguments for apkg are as follows:
-
-- **-h** Print help.
-- **-i** *<pkg(s)>* Install package(s) without taking dependencies into account. Building will fail if the dependencies are not present in the system.
-- **-I** *<pkg(s)>* Install package(s) with dependencies.
-- **-d** *<pkg>* List only direct package dependencies
-- **-D** *<pkg(s)>* List all dependencies for package(s)
-- **-j** *<pkg>* List all reverse dependencies for the package (packages that depend on it).
-- **-u** *<pkg(s)>* Upgrade package(s)
-- **-r** *<pkg(s)>* Remove package(s)
-- **-t** *<pkg(s)>* Run scripts for package(s) that update cache or dbs (mime, font cache e.t.c)
-- **-U** Update system
-- **-f** Force rebuild a package.
-- **-o** *<pkg(s)>* Only download source for package(s), do not build and install
-- **-p** *<pkg(s)>* Print full path to the package build template directory
-- **-s** *<pattern>* Search for packages
-- **-g** *<pkg>* Update or generate checksum(s) for the package source files.
-
-# ENVIRONMENT VARIABLES
-
-- `APKG_ROOT` Overrides default root location (/), where sw is installed
-- `APKG_CONF` Overrides default location for the configuration file apkg.conf. The default is under /etc on an installed alice linux system.
-- `APKG_NOPROMPT` If set, it enabled non-interactive use by disabling user confirmation prompt.
-- `APKG_REPO` Double-quoted, space-separated list for the local directories that contain build templates.
-- `APKG_PACKAGE_DIR` Directory where the compiled packages will reside.
-- `APKG_SOURCE_DIR` Directory that will hold the downloaded sources.
-- `APKG_WORK_DIR` Directory where the actual building process will take place. This happens in subdirectories which are cleaned after completion.
-- `APKG_LOG` If set, it enables the creation of a log for the program output.
-
-**Note:** Usually, APKG_REPO, APKG_PACKAGE_DIR, APKG_SOURCE_DIR and APKG_WORK_DIR are declared in the apkg.conf configuration file. For more information, please see apkg.conf(5).
-
-# FILES
-
-- **apkg.conf(5)** is the default configuration file, it resides by default under /etc.
-- **abuild** is the name of the package templates that apkg uses, along with relevant files in order to
-build and installed packages. For example, one can look to the alice linux repos, under https://codeberg.org/emmett1/alicelinux/src/branch/main/repos
-
-# EXAMPLES
-
-`apkg -i linux` - Install the *linux* package
-
-`apkg -f jupp` - Force rebuild the *jupp* package. If someone tries with just `-i`, `apkg` will produce the following message
-if the package is already installed: `[...] Package 'jupp' already installed.`
-
-`apkg -s icon` - Search for packages names that contain "icon", it will produce a list with one
-package per line.
-
-# AUTHORS
-
-emmett1 <emmett1.2miligrams@protonmail.com> Author of the program and creator of alice linux.
-
-mobinmob <mobinmob@disroot.org> Author of the man page.
-
-# REPORTING BUGS
-
-**apkg** is in a working stage but also under heavy development. Please report and bugs/issues in the project issue tracker: https://codeberg.org/emmett1/autils/issues
diff --git a/man/make-man.sh b/man/make-man.sh
deleted file mode 100644
index dd0a8c5..0000000
--- a/man/make-man.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh
-
-# This script is derives from the original, written for Obarun Linux distribution by Eric Vidal.
-# The original is released under BSD Zero Clause licence (BSD0), and can be found at https://git.obarun.org/Obarun/66/-/blob/master/doc/make-man.sh?ref_type=heads.
-
-
-man8='apkg revdep'
-man5='apkg.conf'
-
-for i in 5 8;do
- if [ ! -d man${i} ]; then
- mkdir -p -m 0755 man"${i}" || exit 1
- fi
-done
-
-for i in ${man5}; do
- lowdown -s -Tman "${i}".md -o man5/"${i}".5 || exit 1
- var=$( sed -n -e '/^.TH/p' < man5/"${i}".5)
- var=$(printf '%s' "$var" | tr '7' '5')
- sed -i "s!^.TH.*!${var}!" man5/"${i}".5 || exit 1
- sed -i '4,8d' man5/"${i}".5 || exit 1
-done
-
-for i in ${man8}; do
- lowdown -s -Tman "${i}".md -o man8/"${i}".8 || exit 1
- var=$( sed -n -e '/^.TH/p' < man8/"${i}".8)
- var=$(printf '%s' "$var" | tr '7' '8')
- sed -i "s!^.TH.*!${var}!" man8/"${i}".8 || exit 1
- sed -i '4,8d' man8/"${i}".8 || exit 1
-done
-
-exit 0
diff --git a/man/man5/apkg.conf.5 b/man/man5/apkg.conf.5
deleted file mode 100644
index e4bb96d..0000000
--- a/man/man5/apkg.conf.5
+++ /dev/null
@@ -1,86 +0,0 @@
-.\" -*- mode: troff; coding: utf-8 -*-
-.TH "" "5" ""
-.SH NAME
-It resides by default under \f(CR/etc\fR in an alice linux installation.
-The contents are sourced by the \fBapkg\fR program and are in the posix shell \f(CRkey=\(dqvalue\(dq\fR format.
-.SH CONFIGURATION KEYS
-.IP "\(bu" 3
-\f(CRAPKG_NOPROMPT\fR If set, it enables non-interactive use by disabling user confirmation prompt.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRAPKG_PACKAGE_DIR\fR Directory where the compiled packages will reside.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRAPKG_SOURCE_DIR\fR Directory that will hold the downloaded sources.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRAPKG_WORK_DIR\fR Directory where the actual building process will take place. This happens in subdirectories which are cleaned after completion.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRAPKG_LOG\fR If set, it enables the creation of a log for the program output.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRexport CFLAGS=\(dq<cflags>\(dq\fR Default are \fI-O3 -march=x86-64 -pipe\fR
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRexport CXXFLAGS=\(dq$CFLAGS\(dq\fR
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRexport NINJAJOBS=\(dq<-x>\(dq\fR Replace <-x> with the number of jobs the ninja build system with use. Without this it will use the maximum amount of threads the processor suports.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRexport MAKEFLAGS=\(dq-jx\(dq\fR Replace with the number of jobs the make build system with use.
-.LP
-EXAMPLES
-.LP
-.EX
-### example of a valid apkg.conf ###
-export CFLAGS=\(dq-O3 -march=x86-64 -pipe\(dq
-export CXXFLAGS=\(dq$CFLAGS\(dq
-export MAKEFLAGS=\(dq-j12\(dq
-export NINJAJOBS=\(dq12\(dq
-APKG_REPO=\(dq/var/lib/alicelinux/repos/core /var/lib/alicelinux/repos/extra /var/lib/alicelinux/repos/xorg /var/lib/alicelinux/repos/wayland\(dq
-APKG_PACKAGE_DIR=/var/cache/pkg
-APKG_SOURCE_DIR=/var/cache/src
-APKG_WORK_DIR=/var/cache/work
-.EE
-.SH AUTHORS
-.LP
-emmett1 \c
-.MT emmett1.2miligrams@protonmail.com
-.ME
-Author of the program and creator of alice linux.
-.PP
-mobinmob \c
-.MT mobinmob@disroot.org
-.ME
-Author of the man page.
-.SH REPORTING BUGS
-.LP
-\fBapkg\fR is in a working stage but also under heavy development. Please report and bugs/issues in the project issue tracker: \c
-.UR https://codeberg.org/emmett1/autils/issues
-.UE
diff --git a/man/man8/apkg.8 b/man/man8/apkg.8
deleted file mode 100644
index 2727207..0000000
--- a/man/man8/apkg.8
+++ /dev/null
@@ -1,181 +0,0 @@
-.\" -*- mode: troff; coding: utf-8 -*-
-.TH "" "8" ""
-.SH NAME
-.SH DESCRIPTION
-.LP
-\fBapkg\fR is the package build tool and package installer, along with \fBspm\fR for the alice linux distribution.
-It is written in posix shell with the goal to be simple and effective. It can consume package building templates in the abuild format
-and automate the building and installing of packages.
-.SH OPTIONS
-.LP
-Arguments for apkg are as follows:
-.IP "\(bu" 3
-\fB-h\fR Print help.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-i\fR \fI\fR Install package(s) without taking dependencies into account. Building will fail if the dependencies are not present in the system.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-I\fR \fI\fR Install package(s) with dependencies.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-d\fR \fI\fR List only direct package dependencies
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-D\fR \fI\fR List all dependencies for package(s)
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-j\fR \fI\fR List all reverse dependencies for the package (packages that depend on it).
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-u\fR \fI\fR Upgrade package(s)
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-r\fR \fI\fR Remove package(s)
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-t\fR \fI\fR Run scripts for package(s) that update cache or dbs (mime, font cache e.t.c)
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-U\fR Update system
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-f\fR Force rebuild a package.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-o\fR \fI\fR Only download source for package(s), do not build and install
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-p\fR \fI\fR Print full path to the package build template directory
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-s\fR \fI\fR Search for packages
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-g\fR \fI\fR Update or generate checksum(s) for the package source files.
-.SH ENVIRONMENT VARIABLES
-.IP "\(bu" 3
-\f(CRAPKG_ROOT\fR Overrides default root location (/), where sw is installed
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRAPKG_CONF\fR Overrides default location for the configuration file apkg.conf. The default is under /etc on an installed alice linux system.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRAPKG_NOPROMPT\fR If set, it enabled non-interactive use by disabling user confirmation prompt.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRAPKG_REPO\fR Double-quoted, space-separated list for the local directories that contain build templates.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRAPKG_PACKAGE_DIR\fR Directory where the compiled packages will reside.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRAPKG_SOURCE_DIR\fR Directory that will hold the downloaded sources.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRAPKG_WORK_DIR\fR Directory where the actual building process will take place. This happens in subdirectories which are cleaned after completion.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\f(CRAPKG_LOG\fR If set, it enables the creation of a log for the program output.
-.LP
-\fBNote:\fR Usually, APKG\fIREPO, APKG\fRPACKAGE\fIDIR, APKG\fRSOURCE\fIDIR and APKG\fRWORK_DIR are declared in the apkg.conf configuration file. For more information, please see apkg.conf(5).
-.SH FILES
-.IP "\(bu" 3
-\fBapkg.conf(5)\fR is the default configuration file, it resides by default under /etc.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fBabuild\fR is the name of the package templates that apkg uses, along with relevant files in order to
-build and installed packages. For example, one can look to the alice linux repos, under \c
-.UR https://codeberg.org/emmett1/alicelinux/src/branch/main/repos
-.UE
-.SH EXAMPLES
-.LP
-\f(CRapkg -i linux\fR - Install the \fIlinux\fR package
-.PP
-\f(CRapkg -f jupp\fR - Force rebuild the \fIjupp\fR package. If someone tries with just \f(CR-i\fR, \f(CRapkg\fR will produce the following message
-if the package is already installed: \f(CR[...] Package 'jupp' already installed.\fR
-.PP
-\f(CRapkg -s icon\fR - Search for packages names that contain \(lqicon\(rq, it will produce a list with one
-package per line.
-.SH AUTHORS
-.LP
-emmett1 \c
-.MT emmett1.2miligrams@protonmail.com
-.ME
-Author of the program and creator of alice linux.
-.PP
-mobinmob \c
-.MT mobinmob@disroot.org
-.ME
-Author of the man page.
-.SH REPORTING BUGS
-.LP
-\fBapkg\fR is in a working stage but also under heavy development. Please report and bugs/issues in the project issue tracker: \c
-.UR https://codeberg.org/emmett1/autils/issues
-.UE
diff --git a/man/man8/revdep.8 b/man/man8/revdep.8
deleted file mode 100644
index 52d32fd..0000000
--- a/man/man8/revdep.8
+++ /dev/null
@@ -1,34 +0,0 @@
-.\" -*- mode: troff; coding: utf-8 -*-
-.TH "" "8" ""
-.SH NAME
-it can discover programs that need to be rebuilt after library upgrades or are missing libraries.
-It should probably run after any big upgrade, especially those that feature lib version bumps.
-.SH OPTIONS
-.IP "\(bu" 3
-\fB-h\fR Show program help.
-.if n \
-.sp -1
-.if t \
-.sp -0.25v
-.IP "\(bu" 3
-\fB-v\fR Verbose output of the operation.
-.SH NOTE
-.LP
-\fBrevdep\fR does not automatically rebuild broken packages or their dependencies. You need to
-use apkg for these operations.
-.SH REPORTING BUGS
-.LP
-\fBapkg\fR is in a working stage but also under heavy development. Please report and bugs/issues in the project issue tracker: \c
-.UR https://codeberg.org/emmett1/autils/issues
-.UE
-.SH AUTHORS
-.LP
-emmett1 \c
-.MT emmett1.2miligrams@protonmail.com
-.ME
-Author of the program and creator of alice linux.
-.PP
-mobinmob \c
-.MT mobinmob@disroot.org
-.ME
-Author of the man page.
diff --git a/man/reposync.8 b/man/reposync.8
new file mode 100644
index 0000000..bed67c3
--- /dev/null
+++ b/man/reposync.8
@@ -0,0 +1,51 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH REPOSYNC 8
+.SH NAME
+reposync \- synchronize git-based package repositories
+.SH DESCRIPTION
+.LP
+\fBreposync\fR synchronizes git-based package repositories using environment
+variables for configuration. It does not depend on an \fIapkg.conf\fR file.
+.SH OPTIONS
+.TP
+\fB-n\fR
+Dry-run: print actions without executing them.
+.TP
+\fB-l\fR
+Enable logging to \fI/var/log/reposync.log\fR.
+.TP
+\fB-f\fR
+Force sync: remove existing repo directories before cloning fresh.
+.TP
+\fB-h\fR
+Print usage message.
+.SH ENVIRONMENT VARIABLES
+.LP
+Repository configuration is provided via variables with the \fBREPOSYNC_\fR prefix.
+Each variable's value uses the pipe-delimited format:
+\fI<url>|<branch>|<local-path>\fR.
+.PP
+For example:
+.PP
+\f(CRREPOSYNC_CORE="https://codeberg.org/emmett1/alicelinux.git|main|/var/lib/alicelinux"\fR
+.PP
+\f(CRREPOSYNC_EXTRA="https://codeberg.org/emmett1/alicelinux.git|extra|/var/lib/alicelinux/extra"\fR
+.SH EXAMPLES
+.LP
+\f(CRreposync\fR - Sync all repos configured via REPOSYNC_* variables.
+.PP
+\f(CRreposync -n\fR - Dry-run to see what actions would be taken.
+.PP
+\f(CRreposync -l\fR - Sync with logging enabled.
+.PP
+\f(CRreposync -f\fR - Force fresh clones of all repositories.
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+.SH REPORTING BUGS
+.LP
+Please report bugs and issues in the project issue tracker: \c
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
diff --git a/man/revdep.8 b/man/revdep.8
new file mode 100644
index 0000000..be93f32
--- /dev/null
+++ b/man/revdep.8
@@ -0,0 +1,38 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH REVDEP 8
+.SH NAME
+revdep \- discover broken library dependencies
+.SH DESCRIPTION
+.LP
+\fBrevdep\fR scans system binaries and shared libraries for missing library links.
+It can discover programs that need to be rebuilt after library upgrades or are
+missing libraries. It should probably be run after any big upgrade, especially
+those that feature library version bumps.
+.SH OPTIONS
+.TP
+\fB-h\fR
+Show program help.
+.TP
+\fB-v\fR
+Verbose output of the operation.
+.SH NOTE
+.LP
+\fBrevdep\fR does not automatically rebuild broken packages or their dependencies.
+You need to use \fBapkg\fR for these operations.
+.SH REPORTING BUGS
+.LP
+\fBapkg\fR is in a working stage but also under heavy development. Please report
+bugs and issues in the project issue tracker: \c
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+Author of the program and creator of Alice Linux.
+.PP
+mobinmob \c
+.MT mobinmob@disroot.org
+.ME
+Author of the man page.
diff --git a/man/revdep.md b/man/revdep.md
deleted file mode 100644
index 6f23ee3..0000000
--- a/man/revdep.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# NAME
-
-**revdep** - utility to discover and rebuild reverse deps
-
-# DESCRIPTION
-
-**revdep** is a utility inspired by the gentoo program revdep-rebuild. It is written in posix shell and
-it can discover programs that need to be rebuilt after library upgrades or are missing libraries.
-It should probably run after any big upgrade, especially those that feature lib version bumps.
-
-# OPTIONS
-
-- **-h** Show program help.
-- **-v** Verbose output of the operation.
-
-# NOTE
-
-**revdep** does not automatically rebuild broken packages or their dependencies. You need to
-use apkg for these operations.
-
-# REPORTING BUGS
-
-**apkg** is in a working stage but also under heavy development. Please report and bugs/issues in the project issue tracker: https://codeberg.org/emmett1/autils/issues
-
-# AUTHORS
-
-emmett1 <emmett1.2miligrams@protonmail.com> Author of the program and creator of alice linux.
-
-mobinmob <mobinmob@disroot.org> Author of the man page.
diff --git a/man/updateconf.8 b/man/updateconf.8
new file mode 100644
index 0000000..d73e4e1
--- /dev/null
+++ b/man/updateconf.8
@@ -0,0 +1,49 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.TH UPDATECONF 8
+.SH NAME
+updateconf \- interactive .new configuration file merge tool
+.SH DESCRIPTION
+.LP
+\fBupdateconf\fR is an interactive tool for handling \fI.new\fR configuration
+files. When packages are upgraded, new default configuration files are installed
+with a \fI.new\fR suffix to avoid overwriting locally modified files.
+\fBupdateconf\fR helps merge, discard, or keep these files.
+.SH USAGE
+.LP
+\f(CRupdateconf\fR
+.PP
+Must be run as root. The script scans \fI/etc\fR for files ending in \fI.new\fR
+and presents each one interactively.
+.SH INTERACTIVE PROMPT
+.LP
+For each \fI.new\fR file, a unified diff between the current and new version is
+shown, and the user is prompted:
+.TP
+\fBU\fR
+Update: replace the current file with the new one.
+.TP
+\fBD\fR
+Discard: delete the \fI.new\fR file, keeping the current version.
+.TP
+\fBE\fR
+Edit: open the current file in the editor (\fB$EDITOR\fR, defaults to \fIvi\fR).
+.TP
+\fBK\fR
+Keep: keep both files, no changes.
+.SH ENVIRONMENT
+.TP
+\fBEDITOR\fR
+Editor to use (default: \fIvi\fR).
+.SH EXAMPLES
+.LP
+\f(CRupdateconf\fR - Run the interactive config file updater.
+.SH AUTHORS
+.LP
+emmett1 \c
+.MT me@emmett1.my
+.ME
+.SH REPORTING BUGS
+.LP
+Please report bugs and issues in the project issue tracker: \c
+.UR https://codeberg.org/emmett1/autils/issues
+.UE
diff --git a/reposync b/reposync
index 60be131..268e92b 100755
--- a/reposync
+++ b/reposync
@@ -1,19 +1,15 @@
#!/bin/sh -e
#
-# script to sync repos
-# required /etc/reposync.conf
-#
-# /etc/reposync.conf format:
-# <git url>|<branch>|<local path to sync>
+# repo sync script (env-based: REPOSYNC_*)
#
log() {
msg="$1"
if [ "$LOG" ]; then
- echo "$(date +'%Y-%m-%d %H:%M:%S') $msg" | tee -a "$LOGFILE"
- else
- echo "$msg"
- fi
+ echo "$(date +'%Y-%m-%d %H:%M:%S') $msg" | tee -a "$LOGFILE"
+ else
+ echo "$msg"
+ fi
}
run_cmd() {
@@ -29,27 +25,21 @@ syncrepo() {
url=$1
branch=$2
path=$3
-
- # if url is empty, do nothing
- if [ ! "$url" ]; then
- exit 0
- fi
-
- # if $path empty, your format is wrong
- if [ ! "$path" ]; then
- echo "/etc/reposync.conf format: <git url>|<branch>|<local path to sync>"
- exit
- fi
-
- if [ "$FORCE" ]; then
- if [ -d "$path" ]; then
- log "=> Force removing repo directory $path..."
- run_cmd "rm -rf \"$path\""
- fi
+
+ [ -z "$url" ] && return 0
+
+ if [ -z "$path" ]; then
+ log "error: invalid repo format (missing path)"
+ return 1
+ fi
+
+ if [ "$FORCE" ] && [ -d "$path" ]; then
+ log "=> Force removing repo directory $path..."
+ run_cmd "rm -rf \"$path\""
fi
if [ ! -d "$path/.git" ]; then
- log "=> Sync repo $path..."
+ log "=> Cloning repo into $path..."
run_cmd "mkdir -p \"$path\""
run_cmd "git clone --branch \"$branch\" --single-branch \"$url\" \"$path\""
else
@@ -68,6 +58,7 @@ usage() {
exit 1
}
+# --- args ---
while [ "$1" ]; do
case "$1" in
-n) DRY_RUN=1;;
@@ -78,20 +69,28 @@ while [ "$1" ]; do
shift
done
+# --- checks ---
command -v git >/dev/null 2>&1 || {
echo "error: git is not installed." >&2
exit 1
}
LOGFILE="/var/log/reposync.log"
-CONFFILE="/etc/reposync.conf"
-if [ ! -f "$CONFFILE" ]; then
- echo "error: config file not found: $CONFFILE" >&2
- exit 1
+REPOS=$(env | grep '^REPOSYNC_' | sort || true)
+
+if [ -z "$REPOS" ]; then
+ echo "error: no REPOSYNC_* variables found." >&2
+ exit 1
fi
-grep -Ev '^#|^$' "$CONFFILE" | while IFS='|' read -r url branch path _; do
+echo "$REPOS" | while IFS='=' read -r name value; do
+ IFS='|' read -r url branch path _ <<EOF
+$value
+EOF
+
+ [ -z "$url" ] && continue
+
syncrepo "$url" "$branch" "$path"
done