From f0265b9bea4e1f10df188e444c3239c376ffa578 Mon Sep 17 00:00:00 2001 From: Yingjie Wang Date: Fri, 28 Mar 2025 23:13:12 -0400 Subject: [PATCH] feat: add triggers array in HOOK and update hook behavier --- README.md | 5 ++--- leaf | 52 +++++++++++++++++++++++++++++++++++++++++---------- leaf.conf | 3 +-- template.HOOK | 1 + 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 8843e8f..ee3d89c 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,7 @@ BUILD_DIR - 编译目录 PKGBUILD_DIR - PKGBUILD目录 TRACE_DIR - 安装文件跟踪目录 - INSTALL_HOOK_DIR - 安装软件包时触发的钩子目录 - REMOVE_HOOK_DIR - 移除软件包时触发的钩子目录 + HOOK_DIR - 钩子目录 BINARY_DIR - 二进制包存放目录 TEMP_DIR - 二进制包解包临时目录 INSTALLED_PACKAGES - 已安装软件包数据库 @@ -87,7 +86,7 @@ 编写PKGBUILD的一般原则: 模块见`template.PKGBUILD`, 语法必须符合`BASH`, 可以定义额外的函数(尽量不要在头部定义全局变量, 这会导致构建环境的污染, 需要手动`unset`, 推荐在函数中用`local`定义局部变量); `src_build`函数只负责编译软件, 并将其安装到`$pkgdir`, 而`src_[pre|post][install|remove]`函数只负责操作根文件系统; `Systemd`单元一般由用户手动开启或关闭。 - 另外, 某些软件包需要生成缓存或更改文件属性才能正常使用(见`HOOKS.md`), 需要定义特定操作的钩子文件, 模板见`template.HOOK`, 语法必须符合`BASH`。 + 另外, 某些软件包需要生成缓存或更改文件属性才能正常使用(见`HOOKS.md`), 需要定义特定操作的钩子文件, 模板见`template.HOOK`, 语法必须符合`BASH`。在 `PKGBUILD` 文件内请使用 `leaf_install_hook .HOOK` 来安全地安装 `.HOOK` 文件,该函数将检查 `.HOOK` 文件的有效性,并正确安装到 `${pkgdir}${HOOK_DIR}`。 4. 构建选项 diff --git a/leaf b/leaf index 23276a5..344d0d3 100755 --- a/leaf +++ b/leaf @@ -84,12 +84,44 @@ main() { fi } +########################################################### +# Help functions that give PKGBUILD to use +########################################################### + leaf_clear_flags() { for flag in $leaf_flags; do unset $flag done } +leaf_install_hook() { + local _hook_file="$1" + local _hook_dest="${pkgdir}${HOOK_DIR}" + + # check file name + [[ -f "$_hook_file" ]] || leaf_error "Hook file '$_hook_file' does not exist" + [[ -r "$_hook_file" ]] || leaf_error "Hook file '$_hook_file' is not readable" + [[ "$(basename "$_hook_file")" == *.HOOK ]] || leaf_error "Hook file must end with .HOOK extension" + + # check hook file by load it in a sub shell + ( + unset triggers target operation 2>/dev/null + declare -a triggers + declare -a target + source "$_hook_file" || leaf_error "Source ${_hook_file} failed." + [[ ${#triggers[@]} -gt 0 ]] || leaf_error "${_hook_file} missing 'triggers' array" + [[ ${#target[@]} -gt 0 ]] || leaf_error "${_hook_file} missing 'target' array" + declare -f operation &>/dev/null || leaf_error "${_hook_file} missing 'operation' function" + ) || leaf_error "Hook file ${_hook_file} is not valid. Please check your package ${PKG_NAME}." + + # install hook file + install -Dm644 -- "$_hook_file" "${_hook_dest}/$(basename "$_hook_file")" || { + leaf_error "Failed to install hook file to ${_hook_dest}" + } + + echo -e "Installed hook: $(basename "$_hook_file")" +} + leaf_check_directories() { if [ -z "${BUILD_DIR}" ]; then leaf_error "Directory \${BUILD_DIR} must be existed" @@ -147,21 +179,21 @@ leaf_invoke_hooks() { local _hook _target _hook_dir local _trace_dir="${TRACE_DIR}/${PKG_PREFIX}/${PKG_NAME}" case "$1" in - install) - _hook_dir="${INSTALL_HOOK_DIR}" - ;; - remove) - _hook_dir="${REMOVE_HOOK_DIR}" + install|remove) ;; *) - leaf_error "leaf_invoke_hooks get $1, which is invalid." + leaf_error "leaf_invoke_hooks: $1 is invalid!" ;; esac - if [ ! -d "${_hook_dir}" ]; then - leaf_error "Hook dir ${_hook_dir} does not exist." + if [ ! -d "${HOOK_DIR}" ]; then + leaf_error "Hook dir ${HOOK_DIR} does not exist. Check your leaf installation." fi - find "${_hook_dir}" -type f -name "*.HOOK" | while read -r _hook; do - source "${_hook}" + find "${HOOK_DIR}" -type f -name "*.HOOK" | while read -r _hook; do + unset triggers target operation + declare -a triggers + declare -a target + source "${_hook}" || leaf_error "Failed to source hook file: ${_hook}" + [[ " ${triggers[*]} " =~ " $1 " ]] || continue for _target in "${target[@]}"; do if grep -qe "${_target}" "${_trace_dir}"/FILES 2>/dev/null; then operation diff --git a/leaf.conf b/leaf.conf index 367a1a8..825721a 100644 --- a/leaf.conf +++ b/leaf.conf @@ -3,8 +3,7 @@ DIST_DIR="${LEAF_DIR}/distfiles" BUILD_DIR="${LEAF_DIR}/build" PKGBUILD_DIR="${LEAF_DIR}/pkgbuild" TRACE_DIR="${LEAF_DIR}/trace" -INSTALL_HOOK_DIR="${LEAF_DIR}/hooks/install" -REMOVE_HOOK_DIR="${LEAF_DIR}/hooks/remove" +HOOK_DIR="${LEAF_DIR}/hooks" BINARY_DIR="${LEAF_DIR}/binaries" TEMP_DIR="${LEAF_DIR}/temp" INSTALLED_PACKAGES="${LEAF_DIR}/installed" diff --git a/template.HOOK b/template.HOOK index 526fd89..d9ab9f7 100644 --- a/template.HOOK +++ b/template.HOOK @@ -1,4 +1,5 @@ target=() +triggers=(install remove) #can be install or remove or both in an array operation() { : }