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