cookutils view web/cooker.cgi @ rev 751

cooker.cgi: show cook progress
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Sep 20 13:00:39 2015 +0200 (2015-09-20)
parents d15a44a622f6
children 5ebf7a7f1bf4
line source
1 #!/bin/sh
2 #
3 # SliTaz Cooker CGI/web interface.
4 #
6 [ -f "/etc/slitaz/cook.conf" ] && . /etc/slitaz/cook.conf
7 [ -f "cook.conf" ] && . ./cook.conf
9 # The same wok as cook.
10 wok="$WOK"
12 # Cooker DB files.
13 activity="$CACHE/activity"
14 commits="$CACHE/commits"
15 cooklist="$CACHE/cooklist"
16 cookorder="$CACHE/cookorder"
17 command="$CACHE/command"
18 blocked="$CACHE/blocked"
19 broken="$CACHE/broken"
20 cooknotes="$CACHE/cooknotes"
21 wokrev="$CACHE/wokrev"
23 # We're not logged and want time zone to display correct server date.
24 export TZ=$(cat /etc/TZ)
26 if [ "${QUERY_STRING%%=*}" == 'download' ]; then
27 file=$(busybox httpd -d "$PKGS/${QUERY_STRING#*=}")
28 cat <<EOT
29 Content-Type: application/octet-stream
30 Content-Length: $(stat -c %s "$file")
31 Content-Disposition: attachment; filename="$(basename "$file")"
33 EOT
34 cat "$file"
35 exit
36 fi
38 echo -n "Content-Type: "
39 if [ "$QUERY_STRING" == 'rss' ]; then
40 echo 'application/rss+xml'
41 else
42 echo 'text/html; charset=utf-8'
43 fi
44 echo ''
46 # RSS feed generator
47 if [ "$QUERY_STRING" == 'rss' ]; then
48 pubdate=$(date -R)
49 cat <<EOT
50 <?xml version="1.0" encoding="utf-8" ?>
51 <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
52 <channel>
53 <title>SliTaz Cooker</title>
54 <description>The SliTaz packages cooker feed</description>
55 <link>$COOKER_URL</link>
56 <lastBuildDate>$pubdate</lastBuildDate>
57 <pubDate>$pubdate</pubDate>
58 <atom:link href="http://cook.slitaz.org/cooker.cgi?rss" rel="self" type="application/rss+xml" />
59 EOT
60 for rss in $(ls -lt $FEEDS/*.xml | head -n 12); do
61 cat $rss | sed 's|<guid|& isPermaLink="false"|g;s|</pubDate| GMT&|g'
62 done
63 cat <<EOT
64 </channel>
65 </rss>
66 EOT
67 exit 0
68 fi
71 #
72 # Functions
73 #
76 # Put some colors in log and DB files.
78 syntax_highlighter() {
79 case $1 in
80 log)
81 sed -e 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g' \
82 -e 's#OK$#<span class="span-ok">OK</span>#g' \
83 -e 's#Done$#<span class="span-ok">Done</span>#g' \
84 -e 's#yes$#<span class="span-ok">yes</span>#g' \
85 -e 's#no$#<span class="span-no">no</span>#g' \
86 -e 's#error$#<span class="span-red">error</span>#g' \
87 -e 's#ERROR:#<span class="span-red">ERROR:</span>#g' \
88 -e 's#WARNING:#<span class="span-red">WARNING:</span>#g' \
89 -e s"#^Executing:\([^']*\).#<span class='sh-val'>\0</span>#"g \
90 -e s"#^====\([^']*\).#<span class='span-line'>\0</span>#"g \
91 -e s"#^[a-zA-Z0-9]\([^']*\) :: #<span class='span-sky'>\0</span>#"g \
92 -e s"#ftp://[^ '\"]*#<a href='\0'>\0</a>#"g \
93 -e s"#http://[^ '\"]*#<a href='\0'>\0</a>#"g ;;
95 receipt)
96 sed -e s'|&|\&amp;|g' -e 's|<|\&lt;|g' -e 's|>|\&gt;|'g \
97 -e s"#^\#\([^']*\)#<span class='sh-comment'>\0</span>#"g \
98 -e s"#\"\([^']*\)\"#<span class='sh-val'>\0</span>#"g ;;
100 diff)
101 sed -e 's|&|\&amp;|g' -e 's|<|\&lt;|g' -e 's|>|\&gt;|g' \
102 -e s"#^-\([^']*\).#<span class='span-red'>\0</span>#"g \
103 -e s"#^+\([^']*\).#<span class='span-ok'>\0</span>#"g \
104 -e s"#@@\([^']*\)@@#<span class='span-sky'>@@\1@@</span>#"g ;;
106 activity)
107 sed s"#^\([^']* : \)#<span class='log-date'>\0</span>#"g ;;
108 esac
109 }
112 # Latest build pkgs.
114 list_packages() {
115 cd $PKGS
116 ls -1t *.tazpkg | head -20 | \
117 while read file; do
118 echo -n $(stat -c '%y' $PKGS/$file | cut -d . -f 1 | sed s/:[0-9]*$//)
119 echo " : $file"
120 done
121 }
124 # Optional full list button
126 more_button() {
127 [ $(wc -l < ${3:-$CACHE/$1}) -gt ${4:-12} ] &&
128 echo "<a class=\"button\" href=\"cooker.cgi?file=$1\">$2</a>"
129 }
132 # Show the running command and its progression
134 running_command()
135 {
136 local state="Not running"
137 if [ -s "$command" ]; then
138 state="$(cat $command)"
139 if grep -q "^$state" $cooktime ; then
140 set -- $(cat $cooktime)
141 state="$state $((($(date +%s)-$3)*100/$2))%"
142 fi
143 fi
144 echo $state
145 }
148 # xHTML header. Pages can be customized with a separated html.header file.
150 if [ -f "header.html" ]; then
151 cat header.html
152 else
153 cat <<EOT
154 <!DOCTYPE html>
155 <html lang="en">
156 <head>
157 <meta charset="utf-8"/>
158 <title>SliTaz Cooker</title>
159 <link rel="shortcut icon" href="favicon.ico"/>
160 <link rel="stylesheet" type="text/css" href="style.css"/>
161 </head>
162 <body>
164 <div id="header">
165 <div id="logo"></div>
166 <h1><a href="cooker.cgi">SliTaz Cooker</a></h1>
167 </div>
169 <!-- Content -->
170 <div id="content">
171 EOT
172 fi
175 #
176 # Load requested page
177 #
179 case "${QUERY_STRING}" in
180 pkg=*)
181 pkg=${QUERY_STRING#pkg=}
182 log=$LOGS/$pkg.log
183 echo "<h2>Package: $pkg</h2>"
185 # Package info.
186 echo '<div id="info">'
187 if [ -f "$wok/$pkg/receipt" ]; then
188 echo "<a href='cooker.cgi?receipt=$pkg'>receipt</a>"
189 unset WEB_SITE
190 . $wok/$pkg/receipt
192 [ -n "$WEB_SITE" ] && # busybox wget -s $WEB_SITE &&
193 echo "<a href='$WEB_SITE'>home</a>"
195 if [ -f "$wok/$pkg/taz/$PACKAGE-$VERSION/receipt" ]; then
196 echo "<a href='cooker.cgi?files=$pkg'>files</a>"
197 unset EXTRAVERSION
198 . $wok/$pkg/taz/$PACKAGE-$VERSION/receipt
199 if [ -f $wok/$pkg/taz/$PACKAGE-$VERSION/description.txt ]; then
200 echo "<a href='cooker.cgi?description=$pkg'>description</a>"
201 fi
202 if [ -f $PKGS/$PACKAGE-$VERSION$EXTRAVERSION.tazpkg ]; then
203 echo "<a href='cooker.cgi?download=$PACKAGE-$VERSION$EXTRAVERSION.tazpkg'>download</a>"
204 fi
205 if [ -f $PKGS/$PACKAGE-$VERSION$EXTRAVERSION-$ARCH.tazpkg ]; then
206 echo "<a href='cooker.cgi?download=$PACKAGE-$VERSION$EXTRAVERSION-$ARCH.tazpkg'>download</a>"
207 fi
208 echo "<a href='ftp://${HTTP_HOST%:*}/$pkg/'>browse</a>"
209 fi
210 else
211 if [ $(ls $wok/*$pkg*/receipt 2> /dev/null | wc -l) -eq 0 ]; then
212 echo "No package named: $pkg"
213 else
214 ls $wok/$pkg/receipt >/dev/null 2>&1 || pkg="*$pkg*"
215 echo '<table style="width:100%">'
216 for i in $(cd $wok ; ls $pkg/receipt); do
217 pkg=$(dirname $i)
218 unset SHORT_DESC CATEGORY
219 . $wok/$pkg/receipt
220 cat <<EOT
221 <tr>
222 <td><a href="cooker.cgi?pkg=$pkg">$pkg</a></td>
223 <td>$SHORT_DESC</td>
224 <td>$CATEGORY</td>
225 </tr>
226 EOT
227 done
228 echo '</table>'
229 unset pkg
230 fi
231 fi
232 echo '</div>'
234 # Check for a log file and display summary if it exists.
235 if [ -f "$log" ]; then
236 if grep -q "cook:$pkg$" $command; then
237 echo "<pre>The Cooker is currently building: $pkg</pre>"
238 fi
239 if fgrep -q "Summary for:" $LOGS/$pkg.log; then
240 echo '<h3>Cook summary</h3>'
241 echo '<pre>'
242 grep -A 12 "^Summary for:" $LOGS/$pkg.log | sed /^$/d | \
243 syntax_highlighter log
244 echo '</pre>'
245 fi
246 if fgrep -q "Debug information" $LOGS/$pkg.log; then
247 echo '<h3>Cook failed</h3>'
248 echo '<pre>'
249 grep -A 8 "^Debug information" $LOGS/$pkg.log | sed /^$/d | \
250 syntax_highlighter log
251 echo '</pre>'
252 fi
253 echo '<h3>Cook log</h3>'
254 echo '<pre>'
255 cat $log | syntax_highlighter log
256 echo '</pre>'
257 else
258 [ "$pkg" ] && echo "<pre>No log: $pkg</pre>"
259 fi ;;
261 file=*)
262 # Don't allow all files on the system for security reasons.
263 file=${QUERY_STRING#file=}
264 case "$file" in
265 activity|cooknotes|cooklist)
266 [ "$file" == "cooklist" ] && \
267 nb="- Packages: $(cat $cooklist | wc -l)"
268 echo "<h2>DB: $file $nb</h2>"
269 echo '<pre>'
270 tac $CACHE/$file | syntax_highlighter activity
271 echo '</pre>' ;;
273 broken)
274 nb=$(cat $broken | wc -l)
275 echo "<h2>DB: broken - Packages: $nb</h2>"
276 echo '<pre>'
277 cat $CACHE/$file | sort | \
278 sed s"#^[^']*#<a href='cooker.cgi?pkg=\0'>\0</a>#"g
279 echo '</pre>' ;;
281 *.diff)
282 diff=$CACHE/$file
283 echo "<h2>Diff for: ${file%.diff}</h2>"
284 [ "$file" == "installed.diff" ] && echo \
285 "<p>This is the latest diff between installed packages \
286 and installed build dependencies to cook.</p>"
287 echo '<pre>'
288 cat $diff | syntax_highlighter diff
289 echo '</pre>' ;;
291 *.log)
292 log=$LOGS/$file
293 name=$(basename $log)
294 echo "<h2>Log for: ${name%.log}</h2>"
295 if [ -f "$log" ]; then
296 if fgrep -q "Summary" $log; then
297 echo '<pre>'
298 grep -A 20 "^Summary" $log | sed /^$/d | \
299 syntax_highlighter log
300 echo '</pre>'
301 fi
302 echo '<pre>'
303 cat $log | syntax_highlighter log
304 echo '</pre>'
305 else
306 echo "<pre>No log file: $log</pre>"
307 fi ;;
308 esac ;;
310 stuff=*)
311 file=${QUERY_STRING#stuff=}
312 echo "<h2>$file</h2>"
313 echo '<pre>'
314 cat $wok/$file | sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g'
315 echo '</pre>' ;;
317 receipt=*)
318 pkg=${QUERY_STRING#receipt=}
319 echo "<h2>Receipt for: $pkg</h2>"
320 if [ -f "$wok/$pkg/receipt" ]; then
321 ( cd $wok/$pkg ; find stuff -type f 2> /dev/null ) | \
322 while read file ; do
323 echo "<a href=\"?stuff=$pkg/$file\">$file</a>"
324 done
325 echo '<pre>'
326 cat $wok/$pkg/receipt | \
327 syntax_highlighter receipt
328 echo '</pre>'
329 else
330 echo "<pre>No receipt for: $pkg</pre>"
331 fi ;;
333 files=*)
334 pkg=${QUERY_STRING#files=}
335 dir=$(ls -d $WOK/$pkg/taz/$pkg-*)
336 if [ -d "$dir/fs" ]; then
337 echo "<h2>Installed files by: $pkg ($(du -hs $dir/fs | awk '{ print $1 }'))</h2>"
338 echo '<pre>'
339 find $dir/fs -not -type d -print0 | xargs -0 ls -ld | \
340 sed "s|\(.*\) /.*\(${dir#*wok}/fs\)\(.*\)|\1 <a href=\"?download=../wok\2\3\">\3</a>|;s|^\([^-].*\)\(<a.*\)\">\(.*\)</a>|\1\3|"
341 echo '</pre>'
342 else
343 echo "<pre>No files list for: $pkg</pre>"
344 fi ;;
346 description=*)
347 pkg=${QUERY_STRING#description=}
348 echo "<h2>Description of $pkg</h2>"
349 dir=$(ls -d $WOK/$pkg/taz/$pkg-*)
350 if [ -s "$dir/description.txt" ]; then
351 echo '<pre>'
352 cat $dir/description.txt | \
353 sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g'
354 echo '</pre>'
355 else
356 echo "<pre>No description for: $pkg</pre>"
357 fi ;;
359 *)
360 # We may have a toolchain.cgi script for cross cooker's
361 if [ -f "toolchain.cgi" ]; then
362 toolchain='toolchain.cgi'
363 else
364 toolchain='cooker.cgi?pkg=slitaz-toolchain'
365 fi
366 # Main page with summary. Count only package include in ARCH,
367 # use 'cooker arch-db' to manually create arch.$ARCH files.
368 inwok=$(ls $WOK/*/arch.$ARCH | wc -l)
369 cooked=$(ls $PKGS/*.tazpkg | wc -l)
370 unbuilt=$(($inwok - $cooked))
371 pct=0
372 [ $inwok -gt 0 ] && pct=$(( ($cooked * 100) / $inwok ))
373 cat <<EOT
374 <div style="float: right;">
375 <form method="get" action="$SCRIPT_NAME">
376 Package:
377 <input type="text" name="pkg" />
378 </form>
379 </div>
381 <h2>Summary</h2>
383 <pre>
384 Running command : $(running_command)
385 Wok revision : <a href="$WOK_URL">$(cat $wokrev)</a>
386 Commits to cook : $(cat $commits | wc -l)
387 Current cooklist : $(cat $cooklist | wc -l)
388 Broken packages : $(cat $broken | wc -l)
389 Blocked packages : $(cat $blocked | wc -l)
390 </pre>
392 <p class="info">
393 Packages: $inwok in the wok | $cooked cooked | $unbuilt unbuilt |
394 Server date: $(date -u '+%F %R %Z')
395 </p>
396 <div class="pctbar">
397 <div class="pct" style="width: ${pct}%;">${pct}%</div>
398 </div>
400 <p>
401 Latest:
402 <a href="cooker.cgi?file=cookorder.log">cookorder.log</a>
403 <a href="cooker.cgi?file=commits.log">commits.log</a>
404 <a href="cooker.cgi?file=pkgdb.log">pkgdb.log</a>
405 <a href="cooker.cgi?file=installed.diff">installed.diff</a>
406 - Architecture $ARCH:
407 <a href="$toolchain">toolchain</a>
408 </p>
411 <h2 id="activity">Activity</h2>
412 <pre>
413 $(tac $CACHE/activity | head -n 12 | syntax_highlighter activity)
414 </pre>
415 $(more_button activity "More activity" $CACHE/activity 12)
418 <h2 id="cooknotes">Cooknotes</h2>
419 <pre>
420 $(tac $cooknotes | head -n 12 | syntax_highlighter activity)
421 </pre>
422 $(more_button cooknotes "More notes" $cooknotes 12)
425 <h2 id="commits">Commits</h2>
426 <pre>
427 $(cat $commits)
428 </pre>
431 <h2 id="cooklist">Cooklist</h2>
432 <pre>
433 $(cat $cooklist | head -n 20)
434 </pre>
435 $(more_button cooklist "Full cooklist" $cooklist 20)
438 <h2 id="broken">Broken</h2>
439 <pre>
440 $(cat $broken | head -n 20 | sed s"#^[^']*#<a href='cooker.cgi?pkg=\0'>\0</a>#"g)
441 </pre>
442 $(more_button broken "All broken packages" $broken 20)
445 <h2 id="blocked">Blocked</h2>
446 <pre>
447 $(cat $blocked | sed s"#^[^']*#<a href='cooker.cgi?pkg=\0'>\0</a>#"g)
448 </pre>
451 <h2 id="lastcook">Latest cook</h2>
452 <pre>
453 $(list_packages | sed s"#^\([^']*\).* : #<span class='log-date'>\0</span>#"g)
454 </pre>
455 EOT
456 ;;
457 esac
460 # Close xHTML page
462 cat <<EOT
463 </div>
465 <div id="footer">
466 <a href="http://www.slitaz.org/">SliTaz Website</a>
467 <a href="cooker.cgi">Cooker</a>
468 <a href="http://hg.slitaz.org/cookutils/raw-file/tip/doc/cookutils.en.html">
469 Documentation</a>
470 </div>
472 </body>
473 </html>
474 EOT
476 exit 0