]> git.plutz.net Git - shellwiki/blob - searchindex.sh
add license headers
[shellwiki] / searchindex.sh
1 #!/bin/sh
2
3 # Copyright 2023 Paul Hänsch
4
5 # Permission to use, copy, modify, and/or distribute this software for any
6 # purpose with or without fee is hereby granted, provided that the above
7 # copyright notice and this permission notice appear in all copies.
8
9 # THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17 export _EXEC="${0%/*}/" _DATA="."
18 verb="" v=0 cmd="" force="" location=""
19
20 help() {
21   ex="$1"
22
23   cat >&2 <<-EOF
24         USAGE:
25
26         ${0##*/} prune [--exec "INSTALL_DIR"] [--data "SITE_DIR"] [-v]
27
28         ${0##*/} index [--exec "INSTALL_DIR"] [--data "SITE_DIR"] \\
29                        [--location "/PAGE"] [--force] [-v]
30
31         Commands:
32
33         prune
34             Remove outdated records from the database. This is usually
35             more time consuming than index creation. It is generally
36             save to run pruning while the wiki is online, even when
37             pages are being updated. Although in rare cases a search
38             operation may return incomplete results while running on
39             a database being pruned.
40
41             Pruning mode should be called regularly via cron.
42
43         index
44             Add pages to the search index. Pages with a current index
45             will be skipped unless the --force option is provided.
46             Optionally a --location can be provided to add only a
47             part of the document tree.
48
49         When running indexing and pruning together, indexing should be run
50         first and pruning afterwards.
51
52         Pruning becomes necessary with page updates, not during mere read
53         operation. On a medium traffic installation pruning should be run
54         about once a week. 
55         Pruning the index more often than daily will rarely be necessary
56         and with low traffic sites monthly maintenance may be completely
57         fine.
58
59         Options:
60
61         --exec INSTALL_DIR
62             Point to the location of your shellwiki installation. This will
63             default to the path at which the script is called, if it can be
64             determined.
65
66         --data SITE_DIR
67             Point to the location of your site installation. I.e. the directory
68             containing your "pages/" and "index/" dir. Defaults to working
69             directory.
70
71         --force
72             Add pages to index even if they seem to be indexed already.
73
74         --loction /PAGE
75             Index only the given page and its children. The path is given
76             relative to the web root, i.e. without the DATA and "page/"
77             directory.
78
79         -v
80             Be more verbose.
81         EOF
82
83   exit "${ex:-0}"
84 }
85
86 while [ $# -gt 0 ]; do case $1 in
87   --exec|-e) _EXEC="${2%/}"; shift 2;;
88   --data|-d) _DATA="${2%/}"; shift 2;;
89   --verbose|-v) verb=true; shift 1;;
90   --force) force=true; shift 1;;
91   --help) help 0 2>&1;;
92   prune|index)
93     [ ! "$cmd" ] && cmd="$1" || help 1
94     shift 1;;
95   *) help 1;;
96 esac; done
97
98 if ! [ -d "$_DATA/pages/" -a -d "$_DATA/index/" ]; then
99   printf 'ERROR: %s\nTry --help\n' "\"${_DATA}\" does not seem to be a valid site directory" >&2
100   exit 1
101 fi
102 if ! [ -x "$_EXEC/parsers/40_indexer.sh" -a -x "$_EXEC/cgilite/storage.sh" ]; then
103   printf 'ERROR: %s\nTry --help\n' "could not determine shellwiki installation path (tried \"$_EXEC\")" >&2
104   exit 1
105 fi
106 if [ ! "$cmd" ]; then
107   help 1
108 fi
109
110 . "$_EXEC/cgilite/storage.sh"
111
112 prune() {
113   for word in "$_DATA/index"/*; do
114     [ "$word" = "$_DATA/index/*" ] && continue
115   
116     [ "$verb" ] && printf "%${v}s\r%s\r" "" "${word##*/}" >&2
117     v="${#word}"
118     mv -- "$word" "${word}.$$"
119   
120     while read -r date location freq num total; do
121       l="$_DATA/pages$(UNSTRING "$location")#index.flag"
122       d="$(stat -c %Y "$l")" 2>&-
123   
124       if [ "$date" -ge "$d" ] 2>&-; then
125         printf '%i      %s      %f      %i      %i\n' \
126                "$date" "$location" "$freq" "$num" "$total"
127       elif [ "$verb" ]; then
128         printf "\rRemoving \"%s\" from \"%s\"\n" "$location" "${word##*/}" >&2
129       fi
130     done <"${word}.$$" >>"${word}"
131     rm -- "${word}.$$"
132   done
133 }
134
135 index() {
136   export PATH_INFO="" _DATE="$(date +%s)"
137
138   if [ "$location" ]; then
139     location="${location#/}" location="${location%/}"
140     printf %s\\n "/${location}/"
141     find "$_DATA/pages/" -type d -path "$_DATA/pages/${location}/*" -not -name "#*" -printf "/%P/\n"
142   else
143     find "$_DATA/pages/" -type d -not -name "#*" -printf "/%P/\n"
144   fi \
145   | while read PATH_INFO; do
146     [ "$force" ] && rm -f -- "$_DATA/pages/$PATH_INFO/#index.flag"
147     if [ "$_DATA/pages/$PATH_INFO/#page.md" -nt "$_DATA/pages/$PATH_INFO/#index.flag" \
148          -o -f "$_DATA/pages/$PATH_INFO/#page.md" \
149        -a ! -f "$_DATA/pages/$PATH_INFO/#index.flag" ] 2>&-
150   then
151       [ "$verb" ] && printf "%${v}s\r%s\r" "" "$PATH_INFO" >&2
152       v="${#PATH_INFO}"
153       "$_EXEC/parsers/40_indexer.sh" <"$_DATA/pages/$PATH_INFO/#page.md" >/dev/null
154     fi
155   done
156 }
157
158 case $cmd in
159   index) index;;
160   prune) prune;;
161 esac