Cross-package tooling notes
A report script that only prints “what’s new since last run” must never be invoked with
>truncation, and ideally shouldn’t let the caller choose. Built 2026-07-22 (scripts/check_aur_feedback.sh): first run redirected with> ../FEEDBACK.txt, correctly printed all 429 then-current AUR comments across every maintained package. Second run (after fixing an unrelated pkgname-resolution bug) was invoked the same way,>again — its own dedup logic correctly suppressed re-printing the 396 comments already marked “seen” from run 1, which is exactly what dedup is supposed to do, but since>truncated the file first and nothing else on disk held a copy of run 1’s text, that entire history was gone with no way to reconstruct it (the comments still exist on AUR, but re-fetching them would just re-trigger the same dedup and print nothing). Any script with this “print only the diff since last time” shape needs the report file itself to be append-only across runs, not just the in-memory dedup state – otherwise dedup working correctly is exactly what destroys the history. Fix applied: the script now takes the output path itself (default../FEEDBACK.txt) and appends a dated## <timestamp>section internally, skipping the write entirely if there’s nothing new to report – there is no>-redirect invocation path left for a caller to get wrong.AUR RPC maintainer checks must include co-maintainers, not just primary maintainer.
scripts/compare_packages.shqueriesrpc/v5/search/<user>?by=maintainer, which only returns packages where<user>is the primary maintainer — packages held as co-maintainer are silently excluded, and show up as false “local dir not on AUR” diffs. Confirmed 2026-07-20:nagircbot,pacman-static, andtrojitaall looked like AUR-maintainer mismatches from theby=maintainersearch alone, butby=comaintainers(same endpoint, differentbyvalue) showed all three are legitimately co-maintained by this account (primary maintainers are other people) — not orphan or drift situations at all. Any future “is this package actually ours on AUR” check needs bothby=maintainerandby=comaintainersunioned before concluding something’s missing/mismatched.rpc/v5/info/<pkgname>also exposes this per-package via theCoMaintainersarray field (absent entirely if there are none).Dependency-resolution checks need
pacman -Si+ a real Provides scan, notpacman -T. Built 2026-07-26 (scripts/check_dependencies.sh, after findingmaintained/lxappearance-obconf-gtk3depended onlxappearance-gtk3, which never existed anywhere – seememory/lxappearance-obconf-gtk3.md). Three separate bugs surfaced while building the checker, in order:pacman -T(deptest) only checks installed packages, not the sync databases –dkms(real package in[extra], just not installed on this build host) came back “unsatisfied” even thoughpacman -Si dkmsfinds it immediately. Use-Sifor an install-state-independent existence check.pacman -Sialone still doesn’t seeProvides– virtual/group deps (sh,pkgconfig,java-runtime,ttf-font,initramfs,fuse,atk) and soname deps (libobrender.so, fromopenbox) are essentially never named after the package that actually provides them, so a plain-Silookup flagged nearly all of them as broken. There’s nopacman -S*query that does a provides-only lookup without an actual transaction; the fix wastar -xOfon every configured repo’s sync db (pacman-conf --repo-list,$(pacman-conf DBPath)sync/<repo>.db) parsed for raw%PROVIDES%fields directly.commneedsLC_ALL=Cto match aLC_ALL=C sort-ed input – this host’s locale isen_US.UTF-8, and a locale-defaultcommagainst C-locale-sorted files silently mis-diffs (“input is not in sorted order” printed to stderr, but the command still exits 0 and produces wrong output that looks plausible). Net effect for any future resolution primitive: verify it against both a known-installed-and-real name and a known-not-installed-but- real name before trusting its output, and assumeProvidesneeds handling explicitly – pacman’s own name-lookup commands don’t do it for you outside a real transaction. As of 2026-07-26 (right after the lxappearance-obconf-gtk3 fix), a full run across all 544 unique dependency entries in arch/ resolves cleanly – 0 BROKEN.
Policy notes, split out since they apply broadly rather than to one package:
HOST_INSTALL_POLICY.md(never install packages on this host to fix a build — chroots exist for that; GPG key imports for source verification are the one exception),PKGREL_VS_PKGVER.md(packaging- only fixes bumppkgrel, notpkgver),ARCHIVE_APPEND_ONLY.md(never remove/move anything out of the private repo’sarchive/dir).This machine can currently only build packages for x86_64, pentium4, i686, and i486 — it has local
extra-<arch>-buildarchbuild chroots for exactly these four. Any other arch that shows up in a PKGBUILD’sarch=()— notably aarch64, arm, armv6h, armv7h, riscv64 — cannot be built here yet; that would need either QEMU user-mode emulation (to run a foreign-arch chroot on this x86_64 host) or SSH access to a real build machine of that architecture, neither of which is set up. Therepo_build.shscript (seeREPO_PUBLISH_DESIGN.md) already treats this as expected: it skips and reports any arch with no localextra-<arch>-buildinstead of failing the whole build.Some existing PKGBUILDs contain pre-existing invalid-UTF-8 byte sequences in comments (e.g. libarchive-static’s
# Tomáš Mrázmaintainer-key comment, which is already mojibake’d to a raw Latin-1 0xE1 byte in git history). My Edit tool and any full-file rewrite (Perl scripts likeupdpkgsums,makepkg --printsrcinfo, etc.) treat the file as UTF-8 text and silently replace such invalid bytes with U+FFFD on save, corrupting them further even in lines I didn’t intend to touch.- After editing a PKGBUILD, diff the full file content against the last
git revision (
git -C <pkg> show HEAD:PKGBUILD) to catch unintended byte-level drift outside the lines you meant to change, not just the lines you meant to change. - Use
LC_ALL=C grep -a/ byte-level tools when inspecting such lines; UTF-8-locale grep can silently fail to match corrupted byte sequences.
- After editing a PKGBUILD, diff the full file content against the last
git revision (
archbuildscripts (extra-<arch>-build) pass args after--straight into their internalmakechrootpkg_argsarray without inserting a separator — so to get args through tomakepkginside the chroot you need a double--:sudo extra-i686-build -- -- --nobuild --skippgpcheck. A single--makesmakechrootpkgitself choke on the makepkg flags (“illegal option – -”).--nobuildis the cheap way to run justprepare()(extract + patch + any config/version reconciliation) inside a chroot without doing the full compile — much faster than a full build when you only need to check/update generated files like kernel configs.- The chroot’s working-copy build tree lives at
/var/lib/archbuild/<repo>-<arch>/<local-copy-user>/build/<pkgname>/src/...(default local-copy name is your own username) — files placed there byprepare()(e.g. a reconciled.config) can besudo cp’d back out andchown’d to your user. namcapinside these chroots is broken (ImportError: libalpm.so.14: cannot open shared object file) andcheckpkgalways says “target not found” since there’s no local repo — both are known-harmless environment issues, not build failures.
Intra-tree dependency ordering — fixed 2026-07-07 for x86_64.
extra-<arch>-buildchroots resolvedepends/makedependsonly against the official Arch mirrors (whateverpacman.confin the chroot points at) — never against other packages built earlier in the samerepo_release_all.shrun, and never in build-order at all (packages are processed in plain alphabetical order). Any package here whosedepends/makedependsnames another custom package from this tree (not an official Arch package — e.g. the Qt5/KDE5 rebuild stack, orarduino-builderneedingarduino-ctags) used to fail witherror: target not found: <pkg>regardless of run order. Seememory/kdstatemachineeditor.mdfor the original diagnosis.- Fix:
scripts/archlinuxaba-archbuild(symlinked asscripts/archlinuxaba-x86_64-build) is a copy of the system/usr/bin/archbuild(devtools32), changed in exactly one place: it resolvespacman_configfrom this project’s ownarch/config/pacman.conf.d/first (falling back to the system location), andarch/config/pacman.conf.d/archlinuxaba.confis a copy of the stockextra.confwith our own private repo (archlinuxaba,SigLevel = Optional TrustAll) added ahead of[core]/[extra]. This mirrors devtools32’s own*-with-build-supportconfig pattern (bootstrap/staging repos layered on top of the base config the same way). It uses its own separate chroot (/var/lib/archbuild/archlinuxaba-x86_64), so the stockextra-x86_64chroot is untouched. Never modifies anything under/usr— everything new lives underarch/. repo_build.shnow resolves the build command per-arch via a_build_cmdhelper:archlinuxaba-x86_64-buildfor x86_64, plainextra-<arch>-buildfor everything else (only x86_64 is wired up so far, per explicit scope).- Verified against a real case:
arduino-builderneedsarduino-ctags(a package in this tree, already published) — failed under plainextra-x86_64-build, succeeded underarchlinuxaba-x86_64-buildonce retried. - Caveat: this only helps once a dependency has actually been
built+published before the package that needs it is attempted —
repo_release_all.shstill processes the tree in plain alphabetical order with no dependency-graph awareness, so a package needing an alphabetically-*later* custom dependency will still fail on a single top-to-bottom pass and needs a manual retry afterward (seememory/gcc-ia16.md,memory/fvwm.mdfor pending examples).
- Fix:
This build box’s GPG keyring is missing some upstream signing keys referenced by
validpgpkeysin various PKGBUILDs, causing--skippgpcheck-less real builds (asrepo_build.shdoes, unlikebuild_all_archs.sh’s own test-build convenience flag) to fail source verification withunknown public key <ID>regardless of anything about the package’s own PKGBUILD/source correctness. First seen 2026-07-07 for key95FA6F43E21188C4acrossmaintained/arduinoandmaintained/arduino-builder. Unlike installing a package on the host (never do that — seememory/feedback_no_host_installs.md’s original, narrower rule), importing a signing key needed purely for source verification is a normal, expected part of doing the build and is fine to do on the host:gpg --recv-keys <ID>(fromhkps://keys.openpgp.orgorkeyserver.ubuntu.comif the PKGBUILD doesn’t specify one). Done for95FA6F43E21188C4on 2026-07-07 — both packages should be retried.A third missing-dependency class, distinct from environment drift and intra-tree ordering: real AUR-only dependencies this tree doesn’t maintain at all (e.g.
dbmodel-qt4needingqt4,adtpro-git/p2c- style needingcc65/gcc14). Unlike the KDE5/Qt5 stack (custom packages that live in this tree, just not resolvable mid-run — fixed byarchlinuxaba-x86_64-build, see above), these depend on packages that were never part ofarch/maintained/private/adapted/ownedin the first place. Building them would mean also building/vendoring a package this tree doesn’t own. Per the user (2026-07-07): note these and move on, don’t try to resolve them now — revisit once there’s an actual plan for out-of-tree AUR dependencies.CMake in this build environment refuses
cmake_minimum_requiredversions below 3.5 (Compatibility with CMake < 3.5 has been removed from CMake.), which will hit any older/unmaintained CMake-based package whoseCMakeLists.txtstill declares an ancient minimum version. First seen 2026-07-07 onkdiagram5(seememory/kdiagram5.md). CMake’s own suggested workaround is-DCMAKE_POLICY_VERSION_MINIMUM=3.5passed to thecmakeinvocation in the PKGBUILD’sbuild()— not applied yet to any package as part of this pass; expect this to recur across other older CMake-based packages in the tree.Modern GCC’s default warnings-as-errors trip older/unmaintained C/C++ sources on genuinely harmless issues like an unused-but-set variable (
error: variable 'X' set but not used [-Werror=unused-but-set-variable=]). Seen 2026-07-07 onmodest(memory/modest.md) andnewsboat-og(memory/newsboat-og.md). Not fixed for either; would need a source fix or relaxing that specific-Werrorin the PKGBUILD’s CFLAGS. Expect this to recur on other old C/C++ packages in the tree.Long-running builds (e.g. kernel compiles via
archbuild) started as a plain backgrounded Bash tool call die with the session (SIGHUP) if the session is closed early. To survive session termination, launch them in a detachedscreensession instead:screen -dmS <name> bash <script>.sh(or-e^Xyfor a custom escape sequence). Check on it later withscreen -r <name>or by tailing the chroot’s own build log at/var/lib/archbuild/<repo>-<arch>/<user>/logdest/<pkg>-<ver>-<arch>-build.log.Danger: manually replicating
repo_build.sh’s git-status-driven post-build cleanup (git status --porcelain -- .→rm -rfevery??entry not matching*.pkg.tar.*/.sig) can delete a brand-new source file you just added, not just real build byproducts. That cleanup’s own assumption is “an untracked file after a successful build is either a release artifact or something makepkg generated” — true when running it via the real pipeline on an already-committed package tree, but this project’s own standing rule is nevergit commit(seeCLAUDE.md). So a genuinely new file you add to amaintained/package (a new local patch, a new config) — something you fully intend to keep — will always show as??untracked, indistinguishable from a downloaded tarball or a.logfile, for as long as this session lives. Hit this for real 2026-07-16 onakonadi-notes: a newly-writtenakonadi-notes-24.08.3-kmime-26.04-api.patchgot deleted by exactly this cleanup snippet run by hand right after a successful publish. Recovered only because a scratch copy of the diff still existed to regenerate it from.- How to apply: before running (or hand-replicating) this cleanup
after a build, check
git status --porcelain -- .yourself first and make sure every??entry it’s about to remove is something you actually expect to be disposable (a downloaded source tarball, a*.logfile, a VCS clone dir) — not a patch/config file you just added as the actual fix. When in doubt, copy the new file somewhere safe (or note its content) before letting any cleanup step run near it. - Confirmed 2026-07-31 that this isn’t just a manual-replication
risk — the real, automated
repo_release.sh→repo_build.shpipeline does this too, every time, to every new uncommitted patch file. Onkdiagram5: wrotekdiagram-2.8.0-ecm-project-version.patch, wired it intoprepare(), ran the normalrepo_release.sh maintained/kdiagram5(not a hand-replicated cleanup), build succeeded, and the patch (plus the unrelated pre-existingPKGBUILD~backup) was silentlyrm -rf’d by this exact cleanup step since neither was git-tracked. Recovered only because the patch content was still in this session’s own context to rewrite verbatim (checksum matched, confirming an exact recreation) — a fresh session with no memory of the patch’s content would have lost it for good. Since this project’s assistant never runsgit commit(seeCLAUDE.md), every single new patch file written in any session is on a countdown to deletion the moment the next successfulrepo_release.sh/repo_build.shrun touches that package directory — there is no “safe” window. Until/unless this cleanup step gets a*.patchexception (not done as of this note — would need explicit user sign-off, since a stray downloaded.patchsource file some PKGBUILDs also legitimately fetch viasource=()complicates a blanket exclusion), treat any newly-written patch as needing the user togit commitit (or add it to.gitignore’s inverse / otherwise mark it tracked) before the first build, not after.
- How to apply: before running (or hand-replicating) this cleanup
after a build, check
repo_publish.sh’s filename-derived arch/pkgname parsing had no validation, and it silently corrupted the remote repo layout twice. Found 2026-07-26 while investigating a user-reported bogus directoryos/x86_64pkg.tar.zst/on the repo host. Root cause:_pkg_arch()/_pkg_name()stripped an expected.pkg.tar.<ext>suffix and then took “whatever’s after the last-” as arch/pkgname, with no check that the strip actually matched anything. Two real incidents from this: (1)m68k-elf-gcc, built via a separate ad-hoc/data/INSTALL/-based flow (not this repo’sarch/tree) with a misconfiguredPKGEXTmissing its leading dot, produced...x86_64pkg.tar.zst– the unguarded strip left it untouched, and${_base##*-}grabbed the wholex86_64pkg.tar.zsttail as “arch”, publishing into a bogus top-level dir with its own orphanedrepo-adddatabase. (2)zoom, built by a separate concurrent session, produced a filename missing its-<pkgrel>-segment (zoom-7.1.5.4332_orig_x86_64.pkg.tar.xz), so the only hyphen left after the (successful, this time) extension strip put7.1.5.4332_orig_x86_64in as “arch”. Both bogus dirs sat unnoticed on the repo host for over a week (m68k-elf-gcc: 2026-07-16 to 2026-07-26; zoom: 2026-07-22 to 2026-07-26) since nothing about publishing failed loudly –mkdir -p/repo-addhappily created a whole new “repo” at the bogus path. Fixed:_pkg_stripped_base()now aborts (non-zero exit,ERROR:to stderr) if the.pkg.tar.*strip didn’t change anything, and_pkg_arch()additionally rejects any result containing a.(real arch names never have one; both incidents above did). Both stale directories were removed from the repo host after confirming a correct copy of m68k-elf-gcc already existed inos/x86_64/(zoom had no other copy – removing its bogus dir removed the package from the repo entirely, done with explicit user confirmation). Lesson for any future filename-parsing helper: validate that an expected-pattern strip actually matched before trusting what’s left over, don’t just chain more stripping operations on a possibly-untouched string.archive/reorganized to be per-arch, 2026-07-26. Was previously one flat directory shared across all archs (deliberate original design – filenames embed pkgver+arch so they can’t collide there either way). User asked for it to mirroros/’s per-arch layout instead._archive_old()inrepo_publish.shalready received the package’s arch as_pkgarch; changed it to create/move into${ARCHIVE_DIR}/${_pkgarch}/instead of flat${ARCHIVE_DIR}/. The existing 73 files were migrated in place on the repo host with a one-off script that reused the same_pkg_arch()parsing logic (not a second implementation) to classify each file, thenmkdir -p+mvper arch – verified file count (73) and total byte size (830534379) matched exactly before and after, nothing lost. Result:archive/{any,i686,pentium4,x86_64}/.**Routine per-package publishes go through
repo_diff_local_remote.shrepo_release_changed.sh, not a hand-chainedextra-x86_64-build->repo_sign.sh->repo_publish.shsequence – even for just one or two UPD-flagged packages.** Went off this rail 2026-07-27 while updatingi686-elf-binutils/x86_64-elf-binutils(2.45/2.46.0 -> 2.47): after editing both PKGBUILDs, ranextra-x86_64-builddirectly to test-build, thenrepo_sign.shandrepo_publish.shby hand for each. That produced a correct result (both published fine, verified against the remote repo and site afterward), but skipped the actual sanctioned tooling:repo_diff_local_remote.shwould have confirmed both read as CHANGED once the PKGBUILDs were bumped, andrepo_release_changed.shbuilds+signs+publishes exactly that detected set (also handles the “already up to date, skip” and multi-package cases uniformly, and keeps theREPO_BUILD_ONLY_ARCHconvention and per-package logfiles underrepo_release_logs/consistent with every other routine cycle).repo_release.sh <pkgdir>(single-package build->sign->publish) is the right manual escape hatch when a package needs individual attention outside the diff-driven flow (e.g. re-testing after a build fix) – reaching for the three lower-level scripts directly should be rarer still, reserved for cases where evenrepo_release.sh’s ordering doesn’t fit (e.g. republishing an already-built artifact without rebuilding it).