cookutils view cooker @ rev 142
QA: exit if broken link
author | Christophe Lincoln <pankso@slitaz.org> |
---|---|
date | Wed May 11 14:53:20 2011 +0200 (2011-05-11) |
parents | fb53f8b0a0ca |
children | cd039ff446c4 |
line source
1 #!/bin/sh
2 #
3 # SliTaz Build Bot. The Cooker is a tool to automate and test SliTaz package
4 # building. Please read the Cookbook documentation for more information
5 # and discuss with the AUTHORS before adding anything here. PS: no translations
6 # here since it's not an end user tool and it's not useful, all devs should
7 # at least understand basic English.
8 #
10 [ -f "/etc/slitaz/cook.conf" ] && . /etc/slitaz/cook.conf
11 [ -f "cook.conf" ] && . ./cook.conf
13 # Set pkg name and use same wok as cook.
14 pkg="$2"
15 wok="$WOK"
16 flavors="$SLITAZ/flavors"
18 # Cooker DB files.
19 activity="$CACHE/activity"
20 commits="$CACHE/commits"
21 cooklist="$CACHE/cooklist"
22 cookorder="$CACHE/cookorder"
23 command="$CACHE/command"
24 blocked="$CACHE/blocked"
25 broken="$CACHE/broken"
26 cooknotes="$CACHE/cooknotes"
28 # PID file.
29 pidfile='/var/run/cooker.pid'
31 #
32 # Functions
33 #
35 usage() {
36 cat << EOT
38 Usage: cooker [command] [pkg|list|note]
40 Options:
41 usage|-u Display this short usage.
42 setup|-s Setup the Cooker environment.
43 note|-n Add a note to the cooknotes.
44 notes|-ns Display all the cooknotes.
45 block|-b Block a package so cook will skip it.
46 unblock|-ub Unblock a blocked package.
47 pkg|-p Same as 'cook pkg' but with cooker log.
48 flavor|-f Cook all packages of a flavor.
49 list|-l Cook all packages in the given list.
50 cat|-c Cook all packages of a category.
51 rev|-r Cook packages of a specific revision.
52 all|-a Find and cook all unbuilt packages.
54 EOT
55 exit 0
56 }
58 separator() {
59 echo "================================================================================"
60 }
62 # Lograte activity.
63 [ -s "$activity" ] && tail -n 60 $activity > /tmp/tail && \
64 mv -f /tmp/tail $activity
66 # Log activities, we want first letter capitalized.
67 log() {
68 grep ^[A-Z] | \
69 sed s"#^[A-Z]\([^']*\)#$(date '+%Y-%m-%d %H:%M') : \0#" >> $activity
70 }
72 # Some messages occur in activity but log verbose output when checking for commits
73 # into a log file.
74 log_commits() {
75 sed '/^.\//'d | sed '/^.hg/'d | tee -a $LOGS/commits.log
76 }
78 # Log broken packages.
79 broken() {
80 if ! grep -q "^$pkg$" $broken; then
81 echo "$pkg" >> $broken
82 fi
83 }
85 # Clean up before exit when check and cook commits finish.
86 clean_exit() {
87 rm -f $command && touch $command
88 rm -f $pidfile
89 }
91 # Summary for commits.
92 commits_summary() {
93 msg="from revision $cur to $new"
94 [ "$new" == "$cur" ] && msg="revision $new"
95 echo "Will cook $msg"
96 separator
97 echo -e "\nSummary for commits"
98 separator
99 echo "Hg wok revision : $cur"
100 echo "Pulled revision : $new"
101 echo "Check date : $(date '+%Y-%m-%d %H:%M:%S')"
102 }
104 # Scan packages build deps and fill up cookorder list.
105 cook_order_scan() {
106 rm -f $cookorder
107 for pkg in $(cat $cooklist)
108 do
109 unset BUILD_DEPENDS
110 . $wok/$pkg/receipt
111 # The :: is for web interface color.
112 [ "$BUILD_DEPENDS" ] && echo "$pkg :: $BUILD_DEPENDS"
113 for dep in $BUILD_DEPENDS
114 do
115 if grep -q "^$dep$" $cooklist; then
116 if ! grep -q "^$dep$" $cookorder; then
117 echo "$dep" >> $cookorder
118 fi
119 fi
120 done
121 done
123 # Append unordered packages to cookorder.
124 for pkg in $(cat $cooklist)
125 do
126 if ! grep -q "^$pkg$" $cookorder; then
127 echo "$pkg" >> $cookorder
128 fi
129 done
130 }
132 # Scan and rescan until the cooklist is ordered then handle WANTED.
133 cook_order() {
134 time=$(date +%s)
135 scan=0
137 # Keep an original cooklist so we do a diff when ordering is finished.
138 cp -f $cooklist $cooklist.0
139 echo "cookorder" > $command
140 echo -e "\nInitial Cooker order scan"
141 separator
142 cook_order_scan
144 # Diff between the cooklist and new ordered list ? So copy the last
145 # cookorder to cooklist and rescan it.
146 while /bin/true
147 do
148 diff $cooklist $cookorder > $cookorder.diff
149 if [ -s "$cookorder.diff" ]; then
150 scan=$(($scan + 1))
151 echo -e "\nDiff scan: $scan"
152 separator
153 mv -f $cookorder $cooklist
154 cook_order_scan
155 else
156 break
157 fi
158 done
160 # Keep a diff between submited cooklist and the ordered.
161 diff $cooklist.0 $cooklist > $cooklist.diff
162 rm -f $cookorder $cookorder.diff $cooklist.0
164 # Scan finished: append pkg to WANTED or leave it in the ordered cooklist.
165 echo -e "\nHandle WANTED package"
166 separator
167 for pkg in $(cat $cooklist)
168 do
169 unset WANTED
170 . $wok/$pkg/receipt
171 if [ "$WANTED" ]; then
172 echo "$pkg :: $WANTED"
173 if grep ^${WANTED}$ $cooklist; then
174 sed -i -e "/^$pkg$/"d \
175 -e "/^$WANTED$/ a $pkg" $cooklist
176 fi
177 fi
178 done
180 # Show ordered cooklist
181 echo -e "\nCooklist order"
182 separator
183 cat $cooklist
184 separator
185 time=$(($(date +%s) - $time))
186 pkgs=$(cat $cooklist | wc -l)
187 echo -e "\nSummary for cookorder"
188 separator
189 cat << EOT
190 Ordered packages : $pkgs
191 Scans executed : $scan
192 Scan duration : ${time}s
193 EOT
194 separator && rm -f $command
195 }
197 # Remove blocked (faster this way than grepping before).
198 strip_blocked() {
199 for pkg in $(cat $blocked)
200 do
201 sed -i /^${pkg}$/d $cooklist
202 done && sed -i /^$/d $cooklist
203 }
205 # Use in default mode and with all cmd.
206 cook_commits() {
207 if [ -s "$commits" ]; then
208 for pkg in $(cat $commits)
209 do
210 echo "cook:$pkg" > $command
211 cook $pkg || broken
212 sed -i /^${pkg}$/d $commits
213 done
214 fi
215 }
217 # Cook all packages in a cooklist.
218 cook_list() {
219 for pkg in $(cat $cooklist)
220 do
221 cook $pkg || broken
222 sed -i /^${pkg}$/d $cooklist
223 done
224 }
226 #
227 # Commands
228 #
229 case "$1" in
230 usage|help|-u|-h)
231 usage ;;
232 setup|-s)
233 # Setup the Cooker environment.
234 echo -e "\nSetting up the Cooker"
235 echo "Cooker setup using: $SLITAZ" | log
236 separator
237 for pkg in $SETUP_PKGS mercurial rsync
238 do
239 [ ! -d "$INSTALLED/$pkg" ] && tazpkg get-install $pkg
240 done
241 mkdir -p $SLITAZ && cd $SLITAZ
242 [ -d "${wok}-hg" ] && echo -e "Hg wok already exists.\n" && exit 1
243 [ -d "$wok" ] && echo -e "Build wok already exists.\n" && exit 1
245 # Directories and files
246 echo "mkdir's and touch files in: $SLITAZ"
247 mkdir -p $PKGS $LOGS $CACHE $SRC
248 for f in $activity $blocked $broken $commits $cooklist $command
249 do
250 touch $f
251 done
252 hg clone $WOK_URL ${wok}-hg || exit 1
253 [ -d "$flavors" ] || hg clone $FLAVORS_URL flavors
254 cp -a ${wok}-hg $wok
255 separator && echo "" ;;
256 note|-n)
257 # Blocked a pkg and want others to know why ? Post a note!
258 note="$2"
259 date=$(date "+%Y-%m-%d %H:%M")
260 [ "$note" ] && echo "$date : $note" >> $cooknotes ;;
261 notes|-ns)
262 # View cooknotes.
263 echo -e "\nCooknotes"
264 separator
265 cat $cooknotes
266 separator && echo "" ;;
267 block|-b)
268 # Block a package.
269 [ "$pkg" ] && cook $pkg --block ;;
270 unblock|-ub)
271 # Unblock a package.
272 [ "$pkg" ] && cook $pkg --unblock ;;
273 reverse|-r)
274 # Cook all reverse dependencies for a package. This command lets us
275 # control the Cooker manually for commits that will cook a lot of packages.
276 #
277 # Use hg commit ? Ex: hg commit -m "Message bla bla | cooker:reverse"
278 #
279 [ ! -d "$wok/$pkg" ] && echo -e "\nNo package $2 found.\n" && exit 0
280 rm -f $cooklist && touch $cooklist && cd $wok
281 echo -e "\nReverse cooklist for: $pkg"
282 separator && cd $wok
283 for rev in *
284 do
285 unset DEPENDS BUILD_DEPENDS && . $wok/$rev/receipt
286 if echo "$DEPENDS $BUILD_DEPENDS" | fgrep -q $pkg; then
287 echo "$rev" | tee -a $cooklist
288 fi
289 done && separator
290 echo -e "Reverse dependencies found: $(cat $cooklist | wc -l)\n"
291 strip_blocked
292 cook_order | tee $LOGS/cookorder.log
293 cook_list ;;
294 pkg|-p)
295 # Same as 'cook pkg' but with log for web interface.
296 cook $pkg || broken
297 clean_exit ;;
298 cat|-c)
299 # Cook all packages of a category.
300 cat="$2"
301 rm -f $cooklist && touch $cooklist && cd $wok
302 for pkg in *
303 do
304 unset CATEGORY && . $pkg/receipt
305 [ "$CATEGORY" == "$cat" ] && echo $pkg >> $cooklist
306 done
307 strip_blocked
308 cook_order | tee $LOGS/cookorder.log
309 cook_list ;;
310 flavor|-f)
311 # Cook all packages of a flavor.
312 name="$2"
313 [ ! -d "$flavors/$name" ] && \
314 echo -e "\nSpecified flavor does not exist: $name\n" && exit 1
315 [ -d "$flavors/.hg" ] && cd $flavors && hg pull -u
316 list=$flavors/$name/packages.list
317 cp -a $list $cooklist
318 strip_blocked
319 cook_order | tee $LOGS/cookorder.log
320 cook_list ;;
321 list|-l)
322 # Cook a list of packages given in argument.
323 list="$2"
324 [ ! -f "$list" ] && \
325 echo -e "\nSpecified list does not exist: $list\n" && exit 1
326 cp -a $list $cooklist
327 strip_blocked
328 cook_order | tee $LOGS/cookorder.log
329 cook_list ;;
330 rev|-r)
331 # Cook or recook a specific Hg revision.
332 rev="$2"
333 [ "$rev" ] || exit 0
334 cd $wok
335 rm -f $cooklist && touch $cooklist
336 for pkg in $(hg log --rev=$rev --template "{files}")
337 do
338 echo "$pkg" | cut -d "/" -f 1 >> $cooklist
339 done
340 strip_blocked
341 cook_order | tee $LOGS/cookorder.log
342 cook_list ;;
343 all|-a)
344 # Try to build all unbuilt packages except blocked's.
345 echo "cooker:all" > $command
346 rm -f $cooklist && touch $cooklist
347 echo "" && cd $wok
348 echo "Cooker cooklist"
349 separator
351 # Find all unbuilt packages. Get EXTRAVERSION from packed receipt
352 # if it exists since extra version is added when packing the package.
353 echo "Searching for all unbuilt packages" | log
354 for pkg in *
355 do
356 unset EXTRAVERSION
357 . $pkg/receipt
358 [ -f "$pkg/taz/$PACKAGE-$VERSION/receipt" ] && \
359 . $pkg/taz/$PACKAGE-$VERSION/receipt
360 if [ ! -f "$PKGS/$PACKAGE-${VERSION}${EXTRAVERSION}.tazpkg" ]
361 then
362 echo $pkg && echo $pkg >> $cooklist
363 fi
364 done
365 strip_blocked
366 cook_order | tee $LOGS/cookorder.log
367 echo "Packages to cook: $(cat $cooklist | wc -l)" | log
368 cook_list ;;
369 *)
370 # Default is to cook all commits if not yet running.
371 [ "$1" ] && usage
372 cooklist=$CACHE/commits
373 if [ -f "$pidfile" ]; then
374 pid=$(cat /var/run/cooker.pid)
375 gettext -e "\nStill cooking latest commits with pid:"
376 echo -e " $pid\n" && exit 0
377 fi
379 # Start and get a PID file.
380 rm -f $LOGS/commits.log
381 echo ""
382 echo "Checking for commits" | log_commits
383 separator | tee -a $LOGS/commits.log
384 echo $$ > $pidfile
385 echo "Cooker PID : $$" | log_commits
386 echo "Cooker date : $(date '+%Y-%m-%d %H:%M:%S')" | log_commits
388 # Get revisions. Here we have 2 echoes since we want a msg on screen,
389 # in commits log and activity DB without a space before.
390 cd $wok || exit 1
391 cur=$(hg head --template '{rev}\n')
392 echo "Updating wok : ${wok}-hg (rev $cur)" | log_commits
393 echo "Updating wok: ${wok}-hg" | log
394 echo "hg:pull" > $command
395 cd ${wok}-hg && hg pull -u | log_commits
396 new=$(hg head --template '{rev}\n')
398 # Sync build wok with rsync so we don't take care about removing old
399 # files as before.
400 if [ "$new" -gt "$cur" ]; then
401 echo "Changes found from: $cur to $new" | log
402 echo "Syncing build wok with Hg wok..." | log_commits
403 rsync -r -t -c -l -u -v -D -E ${wok}-hg/ $wok/ | \
404 sed '/^$/'d | log_commits
405 else
406 echo "No revision changes: $cur vs $new" | log
407 separator | log_commits
408 clean_exit && echo "" && exit 0
409 fi
411 # Get and display modifications.
412 cd ${wok}-hg
413 commits_summary | log_commits
414 cur=$(($cur + 1))
415 rm -f $commits.tmp && touch $commits.tmp
416 for rev in $(seq $cur $new)
417 do
418 for file in $(hg log --rev=$rev --template "{files}")
419 do
420 pkg=$(echo $file | cut -d "/" -f 1)
421 desc=$(hg log --rev=$rev --template "{desc}" $file)
422 echo "Commited : $pkg - $desc" | log_commits
423 echo $pkg >> $commits.tmp
424 done
425 done
427 # Keep previous commit and discard duplicate lines
428 cat $commits $commits.tmp | sed /"^$"/d > $commits.new
429 uniq $commits.new > $commits && rm $commits.*
430 pkgs=$(cat $commits | wc -l)
431 echo "Packages to cook: $pkgs" | log
432 echo "Packages to cook : $pkgs" | log_commits
433 separator | log_commits
434 echo ""
435 strip_blocked
436 cook_order | tee $LOGS/cookorder.log
437 cook_commits
438 clean_exit ;;
439 esac
441 exit 0