sty-hooks (5994B)
1 #!/bin/sh 2 3 # Copyright (C) 2017-2025 |Méso|Star> (contact@meso-star.com) 4 # 5 # This program is free software: you can redistribute it and/or modify 6 # it under the terms of the GNU General Public License as published by 7 # the Free Software Foundation, either version 3 of the License, or 8 # (at your option) any later version. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public License 16 # along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 . "sty.sh" 19 20 set -e 21 22 if [ ! -e "menu.tsv" ]; then 23 >&2 printf \ 24 '%s: not a star-typesetting directory (the menu.tsv file is missing)\n' \ 25 "${0##*/}" 26 exit 1 27 fi 28 29 # Print on standard output the Makefile targets used to automate hook 30 # management 31 32 shtml="$(sty-list shtml)" 33 hook="$(sty-list hook)" 34 35 sections | while read -r i; do 36 shtml_section="$(printf '%s\n' "${shtml}" \ 37 | sed -n "/^${i}\//{s/\.sh/\.md/g;p;}" | tr '\n' ' ')" 38 hook_section="$(printf '%s\n' "${hook}" \ 39 | sed -n "/^${i}\//p" | tr '\n' ' ' \ 40 | sed -e 's/\.sh[[:space:]]/.hook /g')" 41 42 # Define Makefile target that makes section hooks prerequisites for 43 # the HTML content of the section. 44 # 45 # It is the files generated by each of the hooks that are 46 # prerequisites for the HTML files, not the scripts of the hooks 47 # themselves, because even if the scripts have not changed, their 48 # output may have been updated, which can impact the HTML content 49 # generated at build time. 50 # 51 # Furthermore, it is not the HTML file itself that depends on the 52 # hook's output, but rather the intermediate Markdown dynamically 53 # generated by the script, whose output may depend on the execution of 54 # hooks. 55 if [ -n "${shtml_section}" ] \ 56 && [ -n "${hook_section}" ]; then 57 printf '%s: %s\n' "${shtml_section}" "${hook_section}" 58 fi 59 done 60 61 printf '%s\n' "${hook}" | while read -r i; do 62 # Discard empty line 63 if [ -z "${i}" ]; then continue; fi 64 65 # Divide the path into two parts: 66 # - the top-level directory, i.e. the section 67 # - the shell script to be executed from the section directory 68 section="${i%%/*}" 69 hook="${i##"${section}"/}" 70 71 # The hook is the first one in the current section: it has the highest 72 # priority and therefore has no prerequisites. 73 if [ "${section}" != "${prev_section}" ]; then 74 dep="" 75 tgt_list="" 76 prev_priority="" 77 fi 78 79 # Retrieve the hook priority 80 priority="$(basename "${i}")" 81 priority="${priority%%-*}" 82 83 # Define a name for the hook used as a prefix for Makefile targets in 84 # order to automate its execution and the management of the file it 85 # generates. To ensure that this name is unique, and thus avoid 86 # conflicts between different hooks, it is constructed from the names 87 # of the section and file corresponding to the hook. 88 file="$(basename "${hook}")" 89 prefix="${section}-${file%%.*}" 90 91 # Set the file in which the names of the files generated by the hook 92 # are stored as resources for the website, i.e., the files that must 93 # be deployed with the website. 94 tgt="${i%%.*}.hook" 95 96 if [ "${priority}" = "${prev_priority}" ]; then 97 # The hook's priority is the same as the previous one. Add its 98 # target to the list of prerequisites for hooks with lower priority 99 tgt_list="${tgt_list} ${tgt}" 100 else 101 # The priority of the current hook is lower than those processed 102 # previously. Define as a prerequisite the execution of hooks whose 103 # priority precedes the priority of the current hook. 104 dep="${tgt_list}" 105 106 # The execution of the current hook becomes a prerequisite for hooks 107 # with lower priority. 108 tgt_list="${tgt}" 109 fi 110 111 # Define the Makefile target that automate the hook executation. Its 112 # pre-requisites are the hook script and the output of the # previous 113 # hook in the section, i.e. with an higher priority. So that 114 # execution priority is ensured. 115 # 116 # Finally, make this target a prerequisite for building the website 117 # in order to enforce its execution during the build call. 118 printf '%s: %s %s\n' "${tgt}" "${i}" "${dep}" 119 printf ' @cd -- %s; ' "${section}" 120 printf "\$(SHELL) %s > \$\${OLDPWD}/\$@ " "${hook}" 121 printf "|| { rm -f \$\${OLDPWD}/\$@; exit 1; } \n" 122 123 # Set the target for cleaning files generated by executing the hook. 124 # Run it on "distclean" and not on "clean", as their generation can be 125 # costly while effectively being files generated to "distribute" the 126 # website. 127 printf '%s-distclean:\n' "${prefix}" 128 printf ' if [ -f %s ]; then cat %s | xargs rm -f; fi\n' \ 129 "${tgt}" "${tgt}" 130 printf ' rm -f %s\n' "${tgt}" 131 printf 'distclean__: %s-distclean\n' "${prefix}" 132 133 # Set the target to "lightly" clean up the hook, i.e., force it to 134 # re-execute without deleting the files it would generate. This way, 135 # the hooks could query these files in order to regenerate them 136 # depending on whether they deem it necessary or not. 137 # 138 # This aims to speed up the re-execution of hooks, as there is no way 139 # to track their dependencies, meaning that their (conditional) 140 # re-execution is often the only way to ensure that content is up to 141 # date with the latest updates. 142 printf '%s-clean:\n' "${prefix}" 143 printf ' rm -f %s\n' "${tgt}" 144 printf 'clean__: %s-clean\n' "${prefix}" 145 146 # Set the target that installs website resources generated by the hook 147 printf '%s-install: %s\n' "${prefix}" "${tgt}" 148 printf ' @rsync -avzrR --delete-after --progress \\\n' 149 printf ' --chmod=Dg+s,g+w,Fg+w --chown=:'"\$(GROUP)"' --omit-dir-times \\\n' 150 printf ' --files-from=%s ./ '"\$(PREFIX)"'\n' "${tgt}" 151 printf 'install__: %s-install\n' "${prefix}" 152 153 # Save the current section and priority of the hook that has just been 154 # processed 155 prev_section="${section}" 156 prev_priority="${priority}" 157 done