star-ty

Generate content for online publication
git clone git://git.meso-star.fr/star-ty.git
Log | Files | Refs | README | LICENSE

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