Skip to content

Instantly share code, notes, and snippets.

@isac322
Created May 28, 2026 13:52
Show Gist options
  • Select an option

  • Save isac322/614b8ef24c5fa746ca7be9d0399df02d to your computer and use it in GitHub Desktop.

Select an option

Save isac322/614b8ef24c5fa746ca7be9d0399df02d to your computer and use it in GitHub Desktop.
devscripts AUR PKGBUILD (2.26.9-1) — improved over upstream AUR with correct depends/optdepends split, full po4a translated manpages, debian/links aliases, /etc/cowpoke.conf, accurate license, and Arch docbook-xsl path resolution. End-to-end built + namcap verified.
# Maintainer: Byeonghoon Yoo <bhyoo@bhyoo.com>
#
# Upstream tracker: https://tracker.debian.org/pkg/devscripts
# Upstream VCS: https://salsa.debian.org/debian/devscripts
pkgname=devscripts
pkgver=2.26.9
pkgrel=1
pkgdesc='Scripts to make the life of a Debian package maintainer easier'
arch=('any')
url='https://tracker.debian.org/pkg/devscripts'
# Per debian/copyright: a mix of GPL-1+, GPL-2[-or-later], GPL-3[-or-later],
# Artistic-1.0-Perl, Artistic-2.0, ISC, MIT/Expat, and public-domain stanzas.
# The full per-file mapping is installed at
# /usr/share/licenses/${pkgname}/copyright.
license=(
'GPL-1.0-or-later'
'GPL-2.0-only'
'GPL-2.0-or-later'
'GPL-3.0-only'
'GPL-3.0-or-later'
'Artistic-1.0-Perl'
'Artistic-2.0'
'ISC'
'MIT'
)
# Arch's `checkbashisms` (extra) ships /usr/bin/checkbashisms + manpage +
# completion that were split out of devscripts upstream. devscripts itself
# also ships them, so we own them here and swap with the standalone package.
provides=("checkbashisms=${pkgver}")
conflicts=('checkbashisms')
backup=('etc/cowpoke.conf')
# Hard runtime dependencies. Anything Debian-only (apt, sensible-utils,
# python3-apt, ...) is intentionally NOT listed; affected sub-commands
# degrade rather than block installation. Tools whose absence breaks the
# build (because `make` invokes them through help2man during manpage
# generation) or which are hard-imported on the core uscan/bts/debrebuild
# code paths MUST stay here.
depends=(
# Core toolchain
'perl'
'python'
'dpkg' # dpkg-parsechangelog, dpkg-vendor, Dpkg::* perl modules
'file'
'gnupg' # gpg, gpgv, gpg-agent
'patchutils'
'wdiff'
# Perl modules (extra)
'perl-file-homedir'
'perl-io-string'
'perl-json' # use JSON in lib/Devscripts/Uscan/Ctype/*.pm
'perl-libwww'
'perl-lwp-protocol-https' # required so uscan can download from HTTPS upstreams
'perl-moo'
'perl-string-shellquote' # debrebuild dies at BEGIN time without it
'perl-uri' # use URI in bts.pl and lib/Devscripts/Uscan/Downloader.pm
'perl-yaml-libyaml'
# Perl modules (AUR)
'perl-config-inifiles'
'perl-file-dirlist'
'perl-file-touch'
# Python modules (extra)
'python-debian'
'python-junit-xml' # deb-check-file-conflicts imports junit_xml
'python-magic'
'python-pyxdg'
'python-requests'
# Python modules (AUR)
'python-unidiff' # debdiff-apply imports unidiff
)
# base-devel (pkgconf, make, gcc, patch, file, sed, gawk, ...) is implicit
# during AUR builds and intentionally omitted from makedepends.
makedepends=(
'bash-completion' # provides pkg-config completionsdir
'docbook-xml'
'docbook-xsl'
'libxslt' # xsltproc
'help2man'
'po4a'
'perl-pod-parser' # po4a's Pod input plugin needs Pod::Parser
'python-setuptools'
)
optdepends=(
# Stand-alone tools used by individual sub-commands
'curl: download helper used by uscan and dget'
'wget: download helper used by uscan and dget'
'diffstat: pretty-print debdiff output'
'lzip: handle .tar.lz upstream tarballs'
'man-db: lookup helper used by some commands'
'patch: required by edit-patch / add-patch'
'quilt: required by edit-patch and debdiff-apply when working with quilt series'
'equivs: required by mk-build-deps'
'git: required by debcommit against a git repository'
'subversion: required by debcommit and svnpath against a subversion repository'
'strace: used by debpkg-trace'
'unzip: handle .zip upstream tarballs'
# Perl modules lazily required by specific commands
'perl-authen-sasl: SMTP authentication in bts send'
'perl-encode-locale: required at runtime by who-permits-upload'
'perl-term-size: terminal-width output in grep-excuses'
'perl-timedate: provides Date::Parse for plotchangelog'
# Python modules lazily required by specific commands
'python-dateutil: more lenient date parsing in debbisect'
'python-parsedatetime: natural-language date parsing in debbisect'
# AUR packages
'lintian: lint Debian packages, used by debuild'
'sbuild: required by sbuild integration helpers'
'dctrl-tools: grep-dctrl helpers used by rmadison and friends'
'python-apt: required at runtime by debootsnap and reproducible-check (AUR; orphaned)'
'python-debianbts: optional BTS access for debftbfs (AUR)'
)
# Debian native source. The tarball expands into 'work/' (dgit convention),
# not into '<pkgname>-<pkgver>/'.
_srcdir=work
source=("${pkgname}-${pkgver}.tar.xz::https://deb.debian.org/debian/pool/main/d/${pkgname}/${pkgname}_${pkgver}.tar.xz")
sha256sums=('61429335d33a3e744966185bda49e7a354705c0e59600f17d50c1e656d39066e')
prepare() {
cd "${_srcdir}"
# Debian's scripts/Makefile calls `setup.py install --install-layout=deb`,
# which installs python modules under /usr/lib/python3/dist-packages.
# Arch uses /usr/lib/python3.X/site-packages, so drop the flag and fall
# back to setuptools' default layout.
sed -i 's/--install-layout=deb//' scripts/Makefile
# scripts/Makefile, doc/Makefile AND po4a/Makefile hardcode the Debian
# SGML path /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl
# which Arch's docbook-xsl does not provide. Resolve the equivalent Arch
# path at build time, then sweep every occurrence in the source tree.
local arch_docbook_xsl
arch_docbook_xsl=$(printf '%s' /usr/share/xml/docbook/xsl-stylesheets-*-nons/manpages/docbook.xsl)
if [[ ! -f "${arch_docbook_xsl}" ]]; then
# Fallback to the namespace-aware variant.
arch_docbook_xsl=$(printf '%s' /usr/share/xml/docbook/xsl-stylesheets-*/manpages/docbook.xsl)
fi
if [[ ! -f "${arch_docbook_xsl}" ]]; then
echo "error: could not locate Arch docbook-xsl manpages stylesheet" >&2
return 1
fi
grep -rl '/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl' . 2>/dev/null \
| xargs -r sed -i "s|/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl|${arch_docbook_xsl}|g"
# debootsnap and reproducible-check top-level `import apt`, so the
# help2man invocations that run them with `--help` need python-apt at
# build time. python-apt is only available in AUR (orphaned) and pulls
# in a non-trivial cascade, so we drop both manpages from the
# auto-generated set. The scripts themselves are still installed; runtime
# use requires the optional python-apt dependency.
sed -i \
-e '/^[[:space:]]*debootsnap\.1[[:space:]]*\\\?$/d' \
-e '/^[[:space:]]*reproducible-check\.1[[:space:]]*\\\?$/d' \
scripts/Makefile
}
build() {
cd "${_srcdir}"
# Arch ships Perl auxiliary scripts (po4a-translate, pod2man, podchecker,
# ...) under /usr/bin/{site,vendor,core}_perl. Those directories are
# added to PATH via /etc/profile.d/perlbin.sh in interactive shells, but
# makepkg's build environment cannot rely on that — extend PATH
# explicitly so `make` finds these helpers.
export PATH="/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:${PATH}"
make PREFIX=/usr
}
# Upstream ships an extensive autopkgtest/unit-test suite, but it pulls in
# many additional Debian-only tools (apt, autodep8, autopkgtest, shunit2,
# pyftpdlib, python3-apt, ...). Running it from inside makepkg would require
# building a Debian-style chroot, so the check phase is deliberately omitted.
# Manual validation: install the package and run `uscan --help`, etc.
package() {
cd "${_srcdir}"
make PREFIX=/usr DESTDIR="${pkgdir}" install
# ---------------------------------------------------------------------
# Install manpages that upstream's plain `make install` ignores.
# On Debian, dh_installman walks scripts/ and po4a/<lang>/ automatically;
# we do not have that helper, so the pure Makefile install path skips
# them. Without this block users would have no man pages for uscan, bts,
# debrebuild, debchange, etc.
# ---------------------------------------------------------------------
# English man pages (static + generated by `make all`).
install -d "${pkgdir}/usr/share/man/man1" \
"${pkgdir}/usr/share/man/man5"
find scripts -maxdepth 1 -type f -name '*.1' \
-exec install -m0644 -t "${pkgdir}/usr/share/man/man1" {} +
find scripts -maxdepth 1 -type f -name '*.5' \
-exec install -m0644 -t "${pkgdir}/usr/share/man/man5" {} +
# Translated man pages produced by po4a. Layout in build tree:
# po4a/<lang>/<name>.<lang>.<sect>
# Install as /usr/share/man/<lang>/man<sect>/<name>.<sect> (drop the
# .<lang>. infix).
local lang sect manfile target
for lang in de fr pt; do
[[ -d "po4a/${lang}" ]] || continue
for sect in 1 5 7; do
shopt -s nullglob
local matches=( "po4a/${lang}"/*.${lang}.${sect} )
shopt -u nullglob
[[ ${#matches[@]} -gt 0 ]] || continue
install -d "${pkgdir}/usr/share/man/${lang}/man${sect}"
for manfile in "${matches[@]}"; do
target=$(basename "${manfile}")
target=${target/.${lang}./.}
install -m0644 "${manfile}" "${pkgdir}/usr/share/man/${lang}/man${sect}/${target}"
done
done
done
# /usr/share/bash-completion/completions/bts is also shipped by Arch's
# `bash-completion` package. Drop our copy to avoid a file conflict; the
# bash-completion package's version still completes against our `bts`.
rm -f "${pkgdir}/usr/share/bash-completion/completions/bts"
# Recreate the alias symlinks that Debian's debian/links + dh_link would
# create. Plain `make install` does not produce them.
ln -sf debi "${pkgdir}/usr/bin/debc"
ln -sf debchange "${pkgdir}/usr/bin/dch"
ln -sf pts-subscribe "${pkgdir}/usr/bin/pts-unsubscribe"
ln -sf deb2apptainer "${pkgdir}/usr/bin/deb2singularity"
# English manpage aliases.
ln -sf debchange.1 "${pkgdir}/usr/share/man/man1/dch.1"
ln -sf pts-subscribe.1 "${pkgdir}/usr/share/man/man1/pts-unsubscribe.1"
ln -sf deb2apptainer.1 "${pkgdir}/usr/share/man/man1/deb2singularity.1"
# Translated manpage aliases (de + fr only per debian/links; pt has no
# translation upstream for these aliases).
local lang
for lang in de fr; do
[[ -d "${pkgdir}/usr/share/man/${lang}/man1" ]] || continue
ln -sf debchange.1 "${pkgdir}/usr/share/man/${lang}/man1/dch.1"
ln -sf pts-subscribe.1 "${pkgdir}/usr/share/man/${lang}/man1/pts-unsubscribe.1"
ln -sf deb2apptainer.1 "${pkgdir}/usr/share/man/${lang}/man1/deb2singularity.1"
ln -sf edit-patch.1 "${pkgdir}/usr/share/man/${lang}/man1/add-patch.1"
done
# Upstream cowpoke ships a default config; debian/install puts it in /etc.
install -Dm0644 cowpoke.conf "${pkgdir}/etc/cowpoke.conf"
# Example documentation symlink (devscripts.conf.ex points at the
# canonical conf.default that lives under /usr/share/devscripts/).
install -d "${pkgdir}/usr/share/doc/devscripts"
ln -sf /usr/share/devscripts/conf.default \
"${pkgdir}/usr/share/doc/devscripts/devscripts.conf.ex"
# Upstream COPYING is the GPL-2 text; debian/copyright is the canonical
# per-file license map. Install both so license=() entries are backed up
# by actual text on disk.
install -Dm0644 COPYING "${pkgdir}/usr/share/licenses/${pkgname}/COPYING"
install -Dm0644 debian/copyright "${pkgdir}/usr/share/licenses/${pkgname}/copyright"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment