cookutils diff lighttpd/index.cgi @ rev 1010
Major release. cook: fix remove_already_packed(), now it works inside the set; package cooking stops if cookit() return non-zero return code while processing compile_rules() from receipt; lighttpd/index.cgi: 'files' page reworked, now it knows about the sets; finally fixed bug when out-of-tree files (such as pulled into $fs NOT from $install) mistakenly displayed as "unpackaged".
author | Aleksej Bobylev <al.bobylev@gmail.com> |
---|---|
date | Wed Nov 22 19:51:01 2017 +0200 (2017-11-22) |
parents | f6dc84fcff2a |
children | 46fe75e9b709 |
line diff
1.1 --- a/lighttpd/index.cgi Mon Nov 13 02:55:58 2017 +0200 1.2 +++ b/lighttpd/index.cgi Wed Nov 22 19:51:01 2017 +0200 1.3 @@ -574,7 +574,7 @@ 1.4 s|^\(-rwxr-xr-x\)|<span class='c21'>\1</span>|; 1.5 s|^\(-rw-r--r--\)|<span class='c31'>\1</span>|; 1.6 s|^\(drwxr-xr-x\)|<span class='c41'>\1</span>|; 1.7 - s|^\([lrwxs-]*\)|<span class='c11'>\1</span>|; 1.8 + s|^\([lrwxs-][lrwxs-]*\)|<span class='c11'>\1</span>|; 1.9 " 1.10 ;; 1.11 esac 1.12 @@ -1312,18 +1312,27 @@ 1.13 page_header 1.14 pkg_info 1.15 1.16 - packaged=$(mktemp) 1.17 - 1.18 # find main package 1.19 wanted=$(. $wok/$pkg/receipt; echo $WANTED) 1.20 main=${wanted:-$pkg} 1.21 + devpkg=''; [ -d "$wok/$main-dev" ] && devpkg="$main-dev" 1.22 1.23 - # identify split packages 1.24 - split="$main $(. $wok/$main/receipt; echo $SPLIT)" 1.25 - [ -d "$wok/$main-dev" ] && split="$split $main-dev" 1.26 - split="$(echo $split | tr ' ' '\n' | sort -u)" 1.27 + splitsets=$(echo $SPLIT" " \ 1.28 + | awk ' 1.29 + BEGIN { RS = " "; FS = ":"; } 1.30 + { print $2; }' \ 1.31 + | sort -u \ 1.32 + | tr '\n' ' ' \ 1.33 + | sed 's|^ *||; s| *$||') 1.34 1.35 - # finally we need the version 1.36 + splitpkgs=$(echo $SPLIT" " \ 1.37 + | awk ' 1.38 + BEGIN { RS = " "; FS = ":"; } 1.39 + { print $1; }' \ 1.40 + | tr '\n' ' ' \ 1.41 + | sed 's|^ *||; s| *$||') 1.42 + 1.43 + # we need the version 1.44 if [ -f "$WOK/linux/receipt" ]; then 1.45 kvers=$(. $WOK/linux/receipt; echo $VERSION) 1.46 kbasevers=$(echo $kvers | cut -d. -f1,2) 1.47 @@ -1333,138 +1342,326 @@ 1.48 fi 1.49 ver=$(. $wok/$main/receipt; echo $VERSION$EXTRAVERSION) 1.50 1.51 + echo "<section><h3>Quick jump:</h3>" 1.52 1.53 - echo "<section><h3>Quick jump:</h3><ul>" 1.54 - echo "$split" | sed 'p' | xargs printf "<li><a href='#%s'>%s</a></li>\n" 1.55 - echo "<li id='li-repeats' style='display:none'><a href='#repeats'>repeatedly packaged files</a></li>" 1.56 - echo "<li id='li-empty' style='display:none'><a href='#empty'>unpackaged empty folders</a></li>" 1.57 - echo "<li id='li-orphans' style='display:none'><a href='#orphans'>unpackaged files</a>" 1.58 - echo "<span id='orphansTypes'></span></li>" 1.59 - echo "</ul></section>" 1.60 1.61 - for p in $split; do 1.62 - namever="$p-$ver" 1.63 - if [ -d "$wok/$p/taz/$p-$ver" ]; then 1.64 - indir=$p 1.65 - elif [ -d "$wok/$main/taz/$p-$ver" ]; then 1.66 - indir=$main 1.67 - fi 1.68 - dir="$wok/$indir/taz/$p-$ver/fs" 1.69 + for part in head body; do 1.70 1.71 - size=$(du -hs $dir | awk '{ sub(/\.0/, ""); print $1 }') 1.72 + for set in '' $splitsets; do 1.73 + pkgsofset=$(echo $SPLIT" " \ 1.74 + | awk -vset="$set" -vmain="$main" -vdev="$devpkg" ' 1.75 + BEGIN { 1.76 + RS = " "; FS = ":"; 1.77 + if (!set) print main; 1.78 + if (!set && dev) print dev; 1.79 + } 1.80 + { 1.81 + if ($2 == set) print $1; 1.82 + }' \ 1.83 + | sort -u) 1.84 1.85 - echo "<section><h3 id='$p'>Contents of package “$namever” (${size:-empty}):</h3>" 1.86 - echo '<pre class="files">' 1.87 - if [ -s "$wok/$indir/taz/$p-$ver/files.list" ]; then 1.88 - echo -n '<span class="underline">permissions·lnk·user ·' 1.89 - echo -en 'group · size·date & time ·name\n</span>' 1.90 - cd $dir 1.91 - find . -print0 | sort -z | xargs -0 ls -ldp --color=always | \ 1.92 - syntax_highlighter files | \ 1.93 - sed "s|\([^>]*\)>\.\([^<]*\)\(<.*\)$|\1 href='$base/$indir/browse/taz/$p-$ver/fs\2'>\2\3|;" | \ 1.94 - awk 'BEGIN { FS="\""; } 1.95 - { gsub("+", "%2B", $2); print; }' 1.96 - else 1.97 - echo 'No files' 1.98 - fi 1.99 - echo '</pre></section>' 1.100 - cat $wok/$indir/taz/$p-$ver/files.list >> $packaged 1.101 - done 1.102 + set_description='' 1.103 + [ -n "$splitsets" ] && 1.104 + case "$set" in 1.105 + '') 1.106 + set_description=' (default set)' 1.107 + set_title='Default set' 1.108 + ;; 1.109 + *) 1.110 + set_description=" (set “$set”)" 1.111 + set_title="Set “$set”" 1.112 + ;; 1.113 + esac 1.114 1.115 - # find repeatedly packaged files 1.116 - repeats="$(sort $packaged | uniq -d)" 1.117 - if [ -n "$repeats" ]; then 1.118 - echo '<script>document.getElementById("li-repeats").style.display = "list-item"</script>' 1.119 - echo -n '<section><h3 id="repeats">Repeatedly packaged files:</h3><pre class="files">' 1.120 - echo "$repeats" | sed 's|^|<span class="c11">!!!</span> |' 1.121 - echo "</pre></section>" 1.122 - fi 1.123 + install="$wok/$main/install" 1.124 + [ -n "$set" ] && install="$install-$set" 1.125 1.126 - # find unpackaged empty folders 1.127 - emptydirs="$( 1.128 - cd $wok/$main/install 1.129 - find -type d | sed 's|\.||' | \ 1.130 - while read d; do 1.131 - [ -z "$(ls "$wok/$main/install$d")" ] || continue 1.132 - echo $d 1.133 - done | \ 1.134 - while read d; do 1.135 - notfound='yes' 1.136 - for p in $(cd $wok/$main/taz; ls); do 1.137 - if [ -d "$wok/$main/taz/$p/fs$d" ]; then 1.138 - notfound='' 1.139 - break 1.140 - fi 1.141 - done 1.142 - [ -n "$notfound" ] && 1.143 - ls -ldp --color=always .$d | syntax_highlighter files | sed 's|>\./|>/|' 1.144 - done 1.145 - )" 1.146 - if [ -n "$emptydirs" ]; then 1.147 - echo '<script>document.getElementById("li-empty").style.display = "list-item"</script>' 1.148 - echo -n '<section><h3 id="empty">Unpackaged empty folders:</h3><pre class="files">' 1.149 - echo "$emptydirs" 1.150 - echo "</pre></section>" 1.151 - fi 1.152 + case $part in 1.153 + head) 1.154 + [ -n "$splitsets" ] && 1.155 + case "$set" in 1.156 + '') echo "<ul><li>Default set:";; 1.157 + *) echo "<li>Set “$set”:";; 1.158 + esac 1.159 + echo -e '\t<ul>' 1.160 + echo "$pkgsofset" | sed 'p' | xargs printf "\t\t<li><a href='#%s'>%s</a></li>\n" 1.161 + cat <<EOT 1.162 + <li id='li-repeats$set' style='display:none'> 1.163 + <a href='#repeats$set'>repeatedly packaged files</a></li> 1.164 + <li id='li-empty$set' style='display:none'> 1.165 + <a href='#empty$set'>unpackaged empty folders</a></li> 1.166 + <li id='li-outoftree$set' style='display:none'> 1.167 + <a href='#outoftree$set'>out-of-tree files</a></li> 1.168 + <li id='li-orphans$set' style='display:none'> 1.169 + <a href='#orphans$set'>unpackaged files</a> 1.170 + <span id='orphansTypes$set'></span></li> 1.171 +EOT 1.172 + echo -e '\t</ul>' 1.173 + [ -n "$splitsets" ] && echo "</li>" 1.174 + ;; 1.175 + body) 1.176 + all_files=$(mktemp) 1.177 + cd $install; find ! -type d | sed 's|\.||' > $all_files 1.178 1.179 - # find unpackaged files 1.180 - all_files=$(mktemp) 1.181 - cd $wok/$main/install; find ! -type d | sed 's|\.||' > $all_files 1.182 - orphans="$(sort $all_files $packaged | uniq -u)" 1.183 - if [ -d "$wok/$main/install" -a -n "$orphans" ]; then 1.184 - echo '<script>document.getElementById("li-orphans").style.display = "list-item"</script>' 1.185 - echo '<section><h3 id="orphans">Unpackaged files:</h3>' 1.186 - table=$(mktemp) 1.187 - echo "$orphans" | awk -vi="$base/$indir/browse/install" ' 1.188 - function tag(text, color) { 1.189 - printf("<span class=\"c%s1\">%s</span> ", color, text); 1.190 - printf("<a class=\"c00\" href=\"%s\">%s</a>\n", i $0, $0); 1.191 - } 1.192 - /\/perllocal.pod$/ || /\/\.packlist$/ || /\/share\/bash-completion\// || 1.193 - /\/lib\/systemd\// || /\.pyc$/ || /\.pyo$/ || /\/fonts\.scale$/ || /\/fonts\.dir$/ { 1.194 - tag("---", 0); next } 1.195 - /\.pod$/ { tag("pod", 5); next } 1.196 - /\/share\/man\// { tag("man", 5); next } 1.197 - /\/share\/doc\// || /\/share\/gtk-doc\// || /\/share\/info\// || 1.198 - /\/share\/devhelp\// { tag("doc", 5); next } 1.199 - /\/share\/icons\// { tag("ico", 2); next } 1.200 - /\/share\/locale\// { tag("loc", 4); next } 1.201 - /\.h$/ || /\.a$/ || /\.la$/ || /\.pc$/ || /\/bin\/.*-config$/ || 1.202 - /\/Makefile.*$/ { tag("dev", 3); next } 1.203 - /\/share\/help\// || /\/share\/appdata\// { tag("gnm", 6); next } 1.204 - { tag("???", 1) } 1.205 - ' > $table 1.206 + # ------------------------------------------------------ 1.207 + # Packages content 1.208 + # ------------------------------------------------------ 1.209 + packaged=$(mktemp) 1.210 + for p in $pkgsofset; do 1.211 + namever="$p-$ver" 1.212 + if [ -d "$wok/$p/taz/$p-$ver" ]; then 1.213 + indir=$p 1.214 + elif [ -d "$wok/$main/taz/$p-$ver" ]; then 1.215 + indir=$main 1.216 + fi 1.217 + dir="$wok/$indir/taz/$p-$ver/fs" 1.218 1.219 - # Summary table 1.220 - orphans_types='()' 1.221 - for i in head body; do 1.222 - case $i in 1.223 - head) echo -n '<table class="summary"><tr>';; 1.224 - body) echo -n '<th> </th></tr><tr>';; 1.225 + size=$(du -hs $dir | awk '{ sub(/\.0/, ""); print $1 }') 1.226 + 1.227 + echo 1.228 + echo "<section id='$p'>" 1.229 + echo " <h3>Contents of package “$namever” (${size:-empty}):</h3>" 1.230 + echo ' <pre class="files">' 1.231 + if [ -s "$wok/$indir/taz/$p-$ver/files.list" ]; then 1.232 + echo -en '<span class="underline">permissions·lnk·user ·group · size·date & time ·name\n</span>' 1.233 + cd $dir 1.234 + find . -print0 \ 1.235 + | sort -z \ 1.236 + | xargs -0 ls -ldp --color=always \ 1.237 + | syntax_highlighter files \ 1.238 + | sed "s|\([^>]*\)>\.\([^<]*\)\(<.*\)$|\1 href='$base/$indir/browse/taz/$p-$ver/fs\2'>\2\3|;" \ 1.239 + | awk 'BEGIN { FS="\""; } 1.240 + { gsub("+", "%2B", $2); print; }' 1.241 + else 1.242 + echo 'No files' 1.243 + fi 1.244 + echo '</pre>' 1.245 + echo '</section>' 1.246 + 1.247 + cat $wok/$indir/taz/$p-$ver/files.list >> $packaged 1.248 + done 1.249 + # ------------------------------------------------------ 1.250 + # /Packages content 1.251 + # ------------------------------------------------------ 1.252 + 1.253 + # ------------------------------------------------------ 1.254 + # Repeatedly packaged files 1.255 + # ------------------------------------------------------ 1.256 + repeats=$(mktemp) 1.257 + sort $packaged | uniq -d > $repeats 1.258 + if [ -s "$repeats" ]; then 1.259 + echo 1.260 + echo "<script>document.getElementById('li-repeats$set').style.display = 'list-item'</script>" 1.261 + echo "<section id='repeats$set'>" 1.262 + echo " <h3>Repeatedly packaged files$set_description:</h3>" 1.263 + cd $install 1.264 + 1.265 + IFS=$'\n' 1.266 + echo -n ' <pre class="files">' 1.267 + echo -en '<span class="underline">permissions·lnk·user ·group · size·date & time ·name\n</span>' 1.268 + while read i; do 1.269 + find .$i -exec ls -ldp --color=always '{}' \; \ 1.270 + | syntax_highlighter files \ 1.271 + | sed 's|>\./|>/|' 1.272 + done < $repeats 1.273 + echo '</pre>' 1.274 + echo '</section>' 1.275 + unset IFS 1.276 + fi 1.277 + rm $repeats 1.278 + # ------------------------------------------------------ 1.279 + # /Repeatedly packaged files 1.280 + # ------------------------------------------------------ 1.281 + 1.282 + # ------------------------------------------------------ 1.283 + # Unpackaged empty folders 1.284 + # ------------------------------------------------------ 1.285 + emptydirs=$(mktemp) 1.286 + cd $install 1.287 + IFS=$'\n' 1.288 + find -type d \ 1.289 + | sed 's|\.||' \ 1.290 + | while read d; do 1.291 + [ -z "$(ls "$wok/$main/install$d")" ] || continue 1.292 + echo $d 1.293 + done \ 1.294 + | while read d; do 1.295 + notfound='yes' 1.296 + for p in $(cd $wok/$main/taz; ls); do 1.297 + if [ -d "$wok/$main/taz/$p/fs$d" ]; then 1.298 + notfound='' 1.299 + break 1.300 + fi 1.301 + done 1.302 + [ -n "$notfound" ] && 1.303 + ls -ldp --color=always .$d \ 1.304 + | syntax_highlighter files \ 1.305 + | sed 's|>\./|>/|' 1.306 + done > $emptydirs 1.307 + unset IFS 1.308 + if [ -s "$emptydirs" ]; then 1.309 + echo 1.310 + echo "<script>document.getElementById('li-empty$set').style.display = 'list-item'</script>" 1.311 + echo "<section id='empty$set'>" 1.312 + echo " <h3>Unpackaged empty folders$set_description:</h3>" 1.313 + echo -n ' <pre class="files">' 1.314 + echo -en '<span class="underline">permissions·lnk·user ·group · size·date & time ·name\n</span>' 1.315 + cat $emptydirs 1.316 + echo '</pre>' 1.317 + echo '</section>' 1.318 + fi 1.319 + rm $emptydirs 1.320 + # ------------------------------------------------------ 1.321 + # /Unpackaged empty folders 1.322 + # ------------------------------------------------------ 1.323 + 1.324 + # ------------------------------------------------------ 1.325 + # Out-of-tree files 1.326 + # ------------------------------------------------------ 1.327 + outoftree=$(mktemp) 1.328 + awk -F$'\n' -vall="$all_files" ' 1.329 + { 1.330 + if (FILENAME == all) files_all[$1] = "1"; 1.331 + else files_pkg[$1] = "1"; 1.332 + } 1.333 + END { 1.334 + for (i in files_pkg) { 1.335 + if (! files_all[i]) print i; 1.336 + } 1.337 + } 1.338 + ' "$all_files" "$packaged" > $outoftree 1.339 + 1.340 + if [ -d "$install" -a -s "$outoftree" ]; then 1.341 + echo 1.342 + echo "<script>document.getElementById('li-outoftree$set').style.display = 'list-item'</script>" 1.343 + echo "<section id='outoftree$set'>" 1.344 + echo " <h3>Out-of-tree files$set_description:</h3>" 1.345 + echo -n ' <pre class="files">' 1.346 + echo -en '<span class="underline">permissions·lnk·user ·group · size·date & time ·name\n</span>' 1.347 + IFS=$'\n' 1.348 + while read outoftree_line; do 1.349 + # Find the package out-of-tree file belongs to 1.350 + for i in $pkgsofset; do 1.351 + if grep -q "^$outoftree_line$" $wok/$main/taz/$i-$ver/files.list; then 1.352 + cd $wok/$main/taz/$i-$ver/fs 1.353 + ls -ldp --color=always ".$outoftree_line" \ 1.354 + | syntax_highlighter files \ 1.355 + | sed "s|\([^>]*\)>\.\([^<]*\)\(<.*\)$|\1 href='$base/$main/browse/taz/$i-$ver/fs\2'>\2\3|;" \ 1.356 + | awk 'BEGIN { FS="\""; } 1.357 + { gsub("+", "%2B", $2); print; }' 1.358 + fi 1.359 + done 1.360 + done < $outoftree 1.361 + unset IFS 1.362 + echo '</pre>' 1.363 + echo '</section>' 1.364 + fi 1.365 + rm $outoftree 1.366 + # ------------------------------------------------------ 1.367 + # /Out-of-tree files 1.368 + # ------------------------------------------------------ 1.369 + 1.370 + # ------------------------------------------------------ 1.371 + # Unpackaged files 1.372 + # ------------------------------------------------------ 1.373 + orphans=$(mktemp) 1.374 + awk -vall="$all_files" ' 1.375 + { 1.376 + if (FILENAME == all) files_all[$1] = "1"; 1.377 + else files_pkg[$1] = "1"; 1.378 + } 1.379 + END { 1.380 + for (i in files_all) { 1.381 + if (! files_pkg[i]) print i; 1.382 + } 1.383 + } 1.384 + ' "$all_files" "$packaged" > $orphans 1.385 + if [ -d "$install" -a -s "$orphans" ]; then 1.386 + echo 1.387 + echo "<script>document.getElementById('li-orphans$set').style.display = 'list-item'</script>" 1.388 + echo "<section id='orphans$set'>" 1.389 + echo " <h3>Unpackaged files$set_description:</h3>" 1.390 + table=$(mktemp) 1.391 + awk ' 1.392 + function tag(text, color) { 1.393 + printf("<span class=\"c%s1\">%s</span> ", color, text); 1.394 + printf("%s\n", $0); 1.395 + } 1.396 + /\/perllocal.pod$/ || /\/\.packlist$/ || /\/share\/bash-completion\// || 1.397 + /\/lib\/systemd\// || /\.pyc$/ || /\.pyo$/ || /\/fonts\.scale$/ || /\/fonts\.dir$/ { 1.398 + tag("---", 0); next } 1.399 + /\.pod$/ { tag("pod", 5); next } 1.400 + /\/share\/man\// { tag("man", 5); next } 1.401 + /\/share\/doc\// || /\/share\/gtk-doc\// || /\/share\/info\// || 1.402 + /\/share\/devhelp\// { tag("doc", 5); next } 1.403 + /\/share\/icons\// { tag("ico", 2); next } 1.404 + /\/share\/locale\// { tag("loc", 4); next } 1.405 + /\.h$/ || /\.a$/ || /\.la$/ || /\.pc$/ || /\/bin\/.*-config$/ || 1.406 + /\/Makefile.*$/ { tag("dev", 3); next } 1.407 + /\/share\/help\// || /\/share\/appdata\// { tag("gnm", 6); next } 1.408 + { tag("???", 1) } 1.409 + ' "$orphans" > $table 1.410 + 1.411 + # Summary table 1.412 + orphans_types='()' 1.413 + for i in head body; do 1.414 + case $i in 1.415 + head) echo -n '<table class="summary"><tr>';; 1.416 + body) echo -n '<th> </th></tr><tr>';; 1.417 + esac 1.418 + for j in '???1' dev3 loc4 ico2 doc5 man5 pod5 gnm6 '---0'; do 1.419 + tag=${j:0:3}; class="c${j:3:1}0"; [ "$class" == 'c00' ] && class='c01' 1.420 + case $i in 1.421 + head) echo -n "<th class='$class'>$tag</th>";; 1.422 + body) 1.423 + tagscount="$(grep ">$tag<" $table | wc -l)" 1.424 + printf '<td>%s</td>' "$tagscount" 1.425 + [ "$tagscount" -gt 0 ] && orphans_types="${orphans_types/)/ $tag)}" 1.426 + ;; 1.427 + esac 1.428 + done 1.429 + done 1.430 + echo '<td> </td></tr></table>' 1.431 + orphans_types="${orphans_types/( /(}" 1.432 + [ "$orphans_types" != '()' ] && 1.433 + echo "<script>document.getElementById('orphansTypes$set').innerText = '${orphans_types// /, }';</script>" 1.434 + 1.435 + i="$wok/$main/install$suffix" 1.436 + echo -n ' <pre class="files">' 1.437 + echo -en '<span class="underline">tag·permissions·lnk·user ·group · size·date & time ·name\n</span>' 1.438 + IFS=$'\n' 1.439 + while read orphan_line; do 1.440 + echo -n "${orphan_line/span> */span>} " 1.441 + cd $i 1.442 + ls -ldp --color=always ".${orphan_line#*</span> }" \ 1.443 + | syntax_highlighter files \ 1.444 + | sed "s|\([^>]*\)>\.\([^<]*\)\(<.*\)$|\1 href='$base/$main/browse/install$suffix\2'>\2\3|;" \ 1.445 + | awk 'BEGIN { FS="\""; } 1.446 + { gsub("+", "%2B", $2); print; }' 1.447 + done < $table 1.448 + unset IFS 1.449 + echo '</pre>' 1.450 + echo '</section>' 1.451 + rm $table 1.452 + fi 1.453 + rm $orphans 1.454 + # ------------------------------------------------------ 1.455 + # /Unpackaged files 1.456 + # ------------------------------------------------------ 1.457 + 1.458 + rm $all_files $packaged 1.459 + ;; 1.460 esac 1.461 - for j in '???1' dev3 loc4 ico2 doc5 man5 pod5 gnm6 '---0'; do 1.462 - tag=${j:0:3}; class="c${j:3:1}0"; [ "$class" == 'c00' ] && class='c01' 1.463 - case $i in 1.464 - head) echo -n "<th class='$class'>$tag</th>";; 1.465 - body) 1.466 - tagscount="$(grep ">$tag<" $table | wc -l)" 1.467 - printf '<td>%s</td>' "$tagscount" 1.468 - [ "$tagscount" -gt 0 ] && orphans_types="${orphans_types/)/ $tag)}" 1.469 - ;; 1.470 - esac 1.471 - done 1.472 - done 1.473 - echo '<td> </td></tr></table>' 1.474 - orphans_types="${orphans_types/( /(}" 1.475 - [ "$orphans_types" != '()' ] && 1.476 - echo "<script>document.getElementById('orphansTypes').innerText = '${orphans_types// /, }';</script>" 1.477 + done # /set 1.478 1.479 - echo -n '<pre class="files">' 1.480 - cat $table 1.481 - echo '</pre></section>' 1.482 - rm $table 1.483 - fi 1.484 - rm $packaged $all_files 1.485 + case "$part" in 1.486 + head) 1.487 + [ -n "$splitsets" ] && echo "</ul>" 1.488 + echo "</section>" 1.489 + ;; 1.490 + esac 1.491 + done # /part 1.492 + 1.493 ;; 1.494 1.495 description)