# Copyright 2026 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: hyprpm.eclass # @MAINTAINER: # Marc Meier # @AUTHOR: # Marc Meier # @SUPPORTED_EAPIS: 8 9 # @BLURB: Eclass for fetching and installing hyprland plugins defined via a hyprpm.toml # @DESCRIPTION: # Will automatically resolve the correct git commit of # a given plugin to use for the installed Hyprland version # and automatically installs built plugin files. # # Building of the plugin files is not automatically done, # but often a simple call to make. # # As the effective commit built (and thus the source tree) # is dependant on the Hyprland version in use, using patch # files is often a fool's errand. It is advisable to use # sed where possible instead. case ${EAPI} in 8|9) ;; *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; esac if [[ ! ${_HYPRPM_ECLASS} ]]; then _HYPRPM_ECLASS=1 DEPEND=" gui-wm/hyprland:= " BDEPEND=" app-misc/yq-go ${DEPEND} " RDEPEND="${DEPEND}" inherit git-r3 if [[ ${EAPI} = 8 ]]; then inherit eapi9-pipestatus fi # @ECLASS_VARIABLE: HYPRPM_REPO_URI # @REQUIRED # @DESCRIPTION: # URI for the source of the plugin # @ECLASS_VARIABLE: HYPRPM_OVERRIDE_HYPRLAND_COMMIT # @USER_VARIABLE # @DEFAULT_UNSET # @DESCRIPTION: # Do not check Hyprland commit and use this instead # # Intended in case the specific Hyprland version in use # is not a 1:1 match for one of the tagged versions, and # thus commit resolution would fail. # # This is necessary, for example, when running live ebuilds. # @ECLASS_VARIABLE: HYPRPM_RESOLVE_COMMIT # @DEFAULT_UNSET # @DESCRIPTION: # The commit used to resolve versioned commits # # As the effective commit built is dependant on # the Hyprland version built against, it is not really # possible to practically version hyprpm plugins. This # variable is intended to bring some consitency to plugins, # as defining this will force a specific commit from which # to extract the effectivly built commit. # # If unset will fall back to the head of the git repo # @ECLASS_VARIABLE: HYPRPM_PLUGIN_DIR # @DEFAULT_UNSET # @DESCRIPTION: # Will override the directory to which the plugins are installed # # If unset will use /usr/lib/hyprland-plugins/ HYPRPM_PLUGIN_DIR=${HYPRPM_PLUGIN_DIR:-/usr/lib/hyprland-plugins/} # @ECLASS_VARIABLE: HYPRPM_INSTALLED_OBJECTS # @INTERNAL # @DESCRIPTION: # Keeps track of the plugin objects that were installed to # be able to make an informative postinstall HYPRPM_INSTALLED_OBJECTS=() hyprpm_src_unpack() { debug-print-function ${FUNCNAME} "$@" EGIT_REPO_URI=${HYPRPM_REPO_URI} local esc_pn=${PN//[-+]/_} local flagname=HYPRPM_OVERRIDE_PLUGIN_${esc_pn^^}_COMMIT if [[ -n ${!flagname} ]]; then einfo "Override ${flagname} found" einfo "Will use commit '${!flagname}' and not consult \`hyprpm.toml\`" EGIT_COMMIT="${!flagname}" else einfo "Resolving matching commit" einfo "To override this use the following flag:" einfo " ${flagname}" einfo if [[ ! -z "${HYPRPM_RESOLVE_COMMIT}" ]]; then EGIT_COMMIT="${HYPRPM_RESOLVE_COMMIT}" fi einfo "Fetching repo to get access to the hyprpm.toml" git-r3_src_fetch git-r3_checkout local hyprland_commit if [[ ! -z "${HYPRPM_OVERRIDE_HYPRLAND_COMMIT}" ]]; then ewarn "Hyprland's commit hash was manually overwritten." ewarn "This can lead to serious compatibility issues and" ewarn "Hyprland crashes." hyprland_commit="${HYPRPM_OVERRIDE_HYPRLAND_COMMIT}" else hyprland_commit=$( XDG_RUNTIME_DIR="" Hyprland --version | head -n 1 | grep -Eo "[0-9a-f]{40}"; pipestatus || die "Failed to get installed Hyprland's commit hash" ) einfo "Got Hyprland commit ${hyprland_commit} from the installed Hyprland instance" fi local toml_query=".repository.commit_pins.[] | select(.[0] == \"${hyprland_commit}\") | .[1]" local plugin_commit=$(yq "${toml_query}" "${WORKDIR}/${P}/hyprpm.toml" || die "Failed to query hyprpm.toml") if [[ -n ${plugin_commit} ]]; then einfo "Extracted plugin commit ${plugin_commit} from hyprpm.toml" EGIT_COMMIT="${plugin_commit}" einfo "Refetching repo with the correct commit" else ewarn "No matching commit pin was found in the hyprpm.toml of this" ewarn "plugin repository for the installed Hyprland commit:" ewarn " ${hyprland_commit}" ewarn "Falling back to repository HEAD to match upstream hyprpm behavior." ewarn "Compatibility with the installed Hyprland version is not guaranteed." ewarn "This can lead to serious compatibility issues and Hyprland crashes." unset EGIT_COMMIT fi fi git-r3_src_fetch git-r3_checkout } # @FUNCTION: hyprpm_doplugin # @USAGE: # @DESCRIPTION: # Install a passed plugin file to the plugin dir. # # Will use ${HYPRPM_PLUGIN_DIR} or its fallback # as a target # # Use hyprpm_autoinstall instead when possible hyprpm_doplugin() { [[ -z "${1}" ]] && die "\`hyprpm_doplugin\` needs a parameter" insinto "${HYPRPM_PLUGIN_DIR}" doins "${1}" HYPRPM_INSTALLED_OBJECTS+="${HYPRPM_PLUGIN_DIR}$(basename "${1}")" } # @FUNCTION: hyprpm_autoinstall # @USAGE: # @DESCRIPTION: # Parse the hyprpm.toml file and automatically find # where all the plugin files are to install # # This is generally prefered over using hyprpm_doplugin # directly hyprpm_autoinstall() { local toml_query="to_entries | filter(.key != \"repository\") | .[].value.output" for file in $(yq "${toml_query}" "${WORKDIR}/${P}/hyprpm.toml" || die "Failed to query hyprpm.toml"); do if [[ -f "${file}" ]]; then hyprpm_doplugin "${file}" else einfo "Library ${file} does not exist. Skipping..." fi done } hyprpm_src_install() { hyprpm_autoinstall } hyprpm_pkg_postinst() { elog elog "The following plugins have been installed:" for plugin in "${HYPRPM_INSTALLED_OBJECTS[@]}"; do elog " - $plugin" done elog "Remember to load them in your hyprland config as follows:" for plugin in "${HYPRPM_INSTALLED_OBJECTS[@]}"; do elog "> plugin = $plugin" done elog } fi # _HYPRPM_ECLASS EXPORT_FUNCTIONS src_unpack src_install pkg_postinst