# Copyright 1999-2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=8

PYTHON_COMPAT=( python3_{12..15} )

inherit python-single-r1 systemd

DESCRIPTION="Low memory handler that acts on PSI pressure before the kernel OOM killer"
HOMEPAGE="https://github.com/hakavlad/nohang"

if [[ ${PV} == 9999 ]]; then
	inherit git-r3
	EGIT_REPO_URI="https://github.com/hakavlad/nohang.git"
else
	SRC_URI="https://github.com/hakavlad/nohang/archive/v${PV}.tar.gz -> ${P}.tar.gz"
	KEYWORDS="~amd64 ~arm64 ~x86"
fi

LICENSE="MIT"
SLOT="0"
IUSE="desktop systemd"

REQUIRED_USE="${PYTHON_REQUIRED_USE}"

# The daemon itself is pure stdlib Python. The desktop profile shells out to
# notify-send through sudo to reach the logged-in user's session bus.
RDEPEND="
	${PYTHON_DEPS}
	desktop? (
		app-admin/sudo
		x11-libs/libnotify
	)
"

src_prepare() {
	default

	# The Makefile takes the version string from `git describe`, which leaves
	# the file empty when building from a release tarball: the shell truncates
	# it before git fails, and the `-` prefix swallows the error.
	sed -i \
		-e "s|-git describe --tags --long --dirty > version|echo v${PV} > version|" \
		Makefile || die "failed to pin the version string"

	# The Makefile gzips the manpages on its way into ${D}. Portage compresses
	# man/ itself, and warns about anything that arrives already compressed, so
	# hand the pages over as-is and let docompress decide.
	sed -i \
		-e 's|gzip -9cn \(\S*\) > \(\S*\)\.gz|install -p -m0644 \1 \2|' \
		Makefile || die "failed to defer manpage compression to portage"
	if grep -q 'gzip -9cn' Makefile; then
		die "manpage gzip calls left in the Makefile"
	fi

	# /var/run is a compat symlink; OpenRC pidfiles belong in /run, and want
	# the .pid suffix that start-stop-daemon consumers expect.
	sed -i \
		-e 's|pidfile="/var/run/nohang"|pidfile="/run/nohang.pid"|' \
		openrc/nohang.in || die "failed to relocate the nohang pidfile"
	sed -i \
		-e 's|pidfile="/var/run/nohang-desktop"|pidfile="/run/nohang-desktop.pid"|' \
		openrc/nohang-desktop.in || die "failed to relocate the nohang-desktop pidfile"
}

src_compile() {
	# Nothing to build: every executable is a standalone Python script, and the
	# manpages ship pregenerated. The upstream `all` target only prints a hint.
	:
}

src_install() {
	local makeargs=(
		DESTDIR="${D}"
		PREFIX="${EPREFIX}/usr"
		SYSCONFDIR="${EPREFIX}/etc"
		DOCDIR="${EPREFIX}/usr/share/doc/${PF}"
	)

	# The daemon, the two config profiles, the manpages and the logrotate
	# snippet. Everything init-system specific is handled below.
	emake "${makeargs[@]}" base

	# The init scripts are deliberately NOT gated on USE=systemd: they cost a
	# systemd user nothing, and they are the only way to start the daemon on a
	# host that does not run systemd.
	#
	# Expanded here rather than through the upstream install-openrc target,
	# which installs them 0775 - group-writable, for scripts that run as root.
	local svc
	for svc in nohang nohang-desktop; do
		sed \
			-e "s|:TARGET_SBINDIR:|${EPREFIX}/usr/sbin|" \
			-e "s|:TARGET_SYSCONFDIR:|${EPREFIX}/etc|" \
			"openrc/${svc}.in" > "${T}/${svc}.initd" || die "failed to expand the ${svc} init script"
		newinitd "${T}/${svc}.initd" "${svc}"
	done

	# `units` is invoked on its own rather than through the upstream `install`
	# target, which also runs chcon and `systemctl daemon-reload` against the
	# live host instead of against ${D}.
	if use systemd; then
		emake "${makeargs[@]}" \
			SYSTEMDUNITDIR="$(systemd_get_systemunitdir)" units
	fi

	python_fix_shebang "${ED}"

	# Referenced by the shipped logrotate snippet and by separate_log = True.
	keepdir /var/log/nohang
}

pkg_postinst() {
	if [[ -z ${REPLACING_VERSIONS} ]]; then
		elog "Two profiles are installed, and they conflict - enable only one:"
		elog "  nohang          - conservative, headless-safe defaults"
		elog "  nohang-desktop  - tuned for interactive use, sends GUI warnings"
		elog
		elog "OpenRC:  rc-update add nohang default && rc-service nohang start"
		if use systemd; then
			elog "systemd: systemctl enable --now nohang.service"
		fi
		elog
		elog "GUI notifications from the desktop profile need USE=desktop."
		if [[ ! -e /proc/pressure/memory ]]; then
			elog
			elog "This kernel exposes no /proc/pressure/memory: PSI is off."
			elog "Enable CONFIG_PSI, and boot with psi=1 if CONFIG_PSI_DEFAULT_DISABLED"
			elog "is set. Without PSI, nohang falls back to plain memory thresholds."
		fi
	fi
}