b7649bde3db5bbfd80774fe7ebc21ccba4831a39
[amitay/build-farm.git] / build_test.fns
1 #!/bin/sh -*- mode: shell-script; -*-
2
3 # build_farm -- distributed build/test architecture for samba, rsync, etc
4
5 # Copyright (C) 2001 by Andrew Tridgell <tridge@samba.org>
6 # Copyright (C) 2001 by Andrew Bartlett <abartlet@samba.org>
7 # Copyright (C) 2001, 2003 by Martin Pool <mbp@samba.org>
8
9 # default maximum runtime for any command
10 MAXTIME=25200 # 7 hours
11 SMBD_MAXTIME=18000 # 5 hours for a samba process ..
12 # default maximum memory size (100M) for any command
13 MAXMEM=100000
14 RUN_FROM_BUILD_FARM=yes
15 export RUN_FROM_BUILD_FARM
16 export MAXTIME SMBD_MAXTIME
17
18 deptrees="";
19
20 build_test_fns_id='$Id$'
21
22 copy_dir() {
23         Tsrc=$1
24         Tdst=$2
25         pwd
26         echo rsync -a --delete $Tsrc/ $Tdst
27         rsync -a --delete $Tsrc/ $Tdst || return 1
28         return 0
29 }
30
31 #############################
32 # build a signature of a tree, used to see if we
33 # need to rebuild 
34 #############################
35
36 sum_tree() {
37         sum_tree_test_root=$1
38         sum_tree_tree=$2
39         sum_tree_sum=$3
40         sum_tree_scm=$4
41         find $sum_tree_test_root/$sum_tree_tree -type f -print | grep -v version.h | sort | xargs sum > $sum_tree_sum
42         sum build_test build_test.fns >> $sum_tree_sum
43
44         if [ -f "$host.fns" ]; then
45                 sum $host.fns >> $sum_tree_sum
46         else
47                 sum generic.fns >> $sum_tree_sum
48         fi
49
50         if [ -f "$test_root/$tree.$scm" ]; then
51                 sum "$test_root/$tree.$scm" >> $sum_tree_sum
52         fi
53
54         for d in $deptrees; do
55                 dscm=`choose_scm "$d"`
56                 if [ -f "$test_root/$d.$dscm" ]; then
57                 sum "$test_root/$d.$dscm" >> $sum_tree_sum
58                 fi
59         done
60 }
61
62 #############################
63 # send the logs to the master site
64 #############################
65
66 send_logs() {
67         if [ "$nologreturn" = "yes" ]; then
68                 echo "skipping log transfer"
69         else
70                 log="$1"
71                 err="$2"
72                 shift
73                 shift
74                 chmod 0644 "$log" "$err"
75
76                 # xargs -i is implemented differently or not at all.
77                 # GNU xargs did not implement "-I" until 4.2.9:
78                 xargs --version 2>&1 | grep "^GNU xargs" > /dev/null
79                 status=$?
80                 if [ x"$status" = x"0" ]; then
81                         XARGS_IS_GNU=yes
82                 fi
83
84                 if [ x"$XARGS_IS_GNU" = x"yes" ]; then
85                         XARGS_I="xargs -i"
86                 else
87                         XARGS_I="xargs -I '{}'"
88                 fi
89
90                 find $log -size +40000 | $XARGS_I sh -c 'dd if={} bs=1024 count=20000 of={}.tmp && mv {}.tmp {} &&  echo "\n***LOG TRUNCATED***" >> {}'
91                 find $err -size +40000 | $XARGS_I sh -c 'dd if={} bs=1024 count=20000 of={}.tmp && mv {}.tmp {} &&  echo "\n***LOG TRUNCATED***" >> {}'
92
93                 rsync $* -c -q --password-file=.password -z --timeout=200 \
94                         "$log" "$err" $host@build.samba.org::build_farm_data/
95         fi
96 }
97
98 #############################
99 # send the logs when they haven't changed
100 # the aim is to just update the servers timestamp.
101 # sending with a very large rsync block size does this
102 # with minimal network traffic
103 #############################
104
105 send_logs_skip() {
106         touch "$1" "$2"
107         send_logs "$1" "$2" -B 10000000
108 }
109
110 ############################
111 # fetch the latest copy of the tree
112 ############################
113
114 fetch_tree() {
115         if [ "$norsync" = "yes" ]; then
116                 echo "skipping tree transfer"
117         else
118                 fetchtree=$1
119                 if rsync --exclude=autom4te.cache/ --exclude=.svn/ --exclude=.git/ \
120                         --delete-excluded -q --partial --timeout=200 -ctrlpz --delete --ignore-errors \
121                         samba.org::ftp/unpacked/$fetchtree/ $test_root/$fetchtree; then
122                         echo "transferred $fetchtree OK"
123                 else
124                         echo "transfer of $fetchtree failed code $?"
125                         return 1
126                 fi
127         fi
128         return 0
129 }
130
131 ############################
132 # fetch the latest copy of the rev meta info
133 ############################
134
135 fetch_revinfo() {
136         tree=$1
137         scm=$2
138
139         test -z "$scm" && return 1
140         test x"$scm" = x"unknown" && return 1
141         test x"$scm" = x"cvs" && return 1
142
143         if [ "$norsync" = "yes" ]; then
144                 echo "skipping .revinfo.$scm transfer"
145         else
146                 if [ -r $test_root/$tree.$scm ]; then
147                         [ -f $test_root/$tree.$scm.old ] && rm -f $test_root/$tree.$scm.old
148                         [ -f $test_root/$tree.$scm ] && mv $test_root/$tree.$scm $test_root/$tree.$scm.old
149                 fi
150                 rsync -q --timeout=200 -clz --ignore-errors \
151                         samba.org::ftp/unpacked/$tree/.revinfo.$scm $test_root/$tree.$scm
152         fi
153         if [ -r $test_root/$tree.$scm ]; then
154                 return 0;
155         fi
156         return 1
157 }
158
159 ############################
160 # choose the scm that is used for the given project
161 ############################
162
163 choose_scm() {
164         tree=$1
165
166         case "$tree" in
167                         samba* | rsync | libreplace | talloc | tdb | ldb | pidl | ccache*)
168                         echo "git"
169                                 return 0
170                         ;;
171         esac
172
173         echo "svn"
174         return 0
175 }
176
177 locknesting=0
178
179 ############################
180 # grab a lock file. Not atomic, but close :)
181 # tries to cope with NFS
182 ############################
183
184 lock_file() {
185                 if [ -z "$lock_root" ]; then
186                         lock_root=`pwd`;
187                 fi
188
189                 lckf="$lock_root/$1"
190                 machine=`cat "$lckf" 2> /dev/null | cut -d: -f1`
191                 pid=`cat "$lckf" 2> /dev/null | cut -d: -f2`
192
193                 if [ "$pid" = "$$" ]; then
194                         locknesting=`expr $locknesting + 1`
195                         echo "lock nesting now $locknesting"
196                         return 0
197                 fi
198
199                 if test -f "$lckf"; then
200                         test x$machine = x$host || {
201                                 echo "lock file $lckf is valid for other machine $machine"
202                                 return 1
203                         }
204
205                         kill -0 $pid && {
206                                 echo "lock file $lckf is valid for process $pid"
207                                 return 1
208                         }
209
210                         echo "stale lock file $lckf for $machine:$pid"
211                         cat "$lckf"
212                         /bin/rm -f "$lckf"
213                 fi
214                 echo "$host:$$" > "$lckf"
215                 return 0
216 }
217
218 ############################
219 # unlock a lock file
220 ############################
221
222 unlock_file() {
223         if [ -z "$lock_root" ]; then
224                 lock_root=`pwd`;
225         fi
226         if [ "$locknesting" != "0" ]; then
227                 locknesting=`expr $locknesting - 1`
228                 echo "lock nesting now $locknesting"
229         else 
230                 lckf="$lock_root/$1"
231                 /bin/rm -f "$lckf"
232         fi
233 }
234
235 ############################
236 # run make, and print trace
237 ############################
238
239 do_make() {
240         if [ x"$MAKE" = x ]; then
241                 MAKE=make
242         fi
243
244         MMTIME=$MAXTIME
245         # some trees don't need as much time
246         case "$tree" in
247                 rsync | tdb | talloc | libreplace | ccache*)
248                         if [ "$compiler" != "checker" ]; then
249                                 MMTIME=`expr $MMTIME / 5`
250                         fi
251                 ;;
252         esac
253
254
255         for t in $*; do
256                 if [ x"$BUILD_FARM_NUM_JOBS" = x ]; then
257                         echo "$MAKE $t"
258                         $builddir/timelimit $MMTIME "$MAKE" "$t"
259                         status=$?
260                 else
261                         # we can parallelize everything and all targets
262                         if [ x"$t" = xeverything ] || [ x"$t" = xall]; then
263                                 echo "$MAKE" "-j$BUILD_FARM_NUM_JOBS"  "$t"
264                                 $builddir/timelimit $MMTIME "$MAKE" "-j$BUILD_FARM_NUM_JOBS"  "$t"
265                                 status=$?
266                         else
267                                 echo "$MAKE $t"
268                                 $builddir/timelimit $MMTIME "$MAKE" "$t"
269                                 status=$?
270                         fi
271                 fi
272
273                 if [ $status != 0 ]; then
274                         case "$t" in
275                                 test|check|installcheck)
276                                         ;;
277                                 *)
278                                         #run again with V=1, so we see failed commands
279                                         $builddir/timelimit $MMTIME "$MAKE" "$t" V=1
280                                         status=$?
281                                         ;;
282                         esac
283                 fi
284
285                 if [ $status != 0 ]; then
286                         return $status;
287                 fi
288
289         done
290
291         return 0
292 }
293
294
295 ############################
296 # do the coverage report
297 ############################
298
299 action_lcovreport() {
300         if [ "$LCOV_REPORT" = "yes" ]; then
301                 case "$tree" in
302                 lorikeet-heimdal*)
303                         lcov --directory $builddir --capture --output-file $builddir/$tree.lcov.info
304                         ;;
305                 samba_3_master*)
306                         lcov --base-directory $builddir --directory $builddir/.. --capture --output-file $builddir/$tree.lcov.info
307                         ;;
308                 samba_4*)
309                         # rm -f heimdal/lib/*/{lex,parse,sel-lex}.{gcda,gcno}
310                         lcov --base-directory $builddir --directory $builddir/.. --capture --output-file $builddir/$tree.lcov.info
311                         ;;
312                 *)
313                         lcov --base-directory $builddir --directory $builddir --capture --output-file $builddir/$tree.lcov.info
314                         ;;
315                 esac
316                 genhtml -o $builddir/coverage $builddir/$tree.lcov.info
317                 rc=$?
318                 echo "return code: $rc"
319         else
320                 echo "LCOV_REPORT not set and lcovreport asked"
321                 echo "Most probably an error please fix !"
322                 return 1
323         fi
324 }
325
326
327 ############################
328 # configure the tree
329 ############################
330
331 action_configure() {
332
333         if [ ! -x $srcdir/configure -a -r $srcdir/Makefile.PL ]; then
334                 perl $srcdir/Makefile.PL PREFIX="$prefix"
335                 cstatus=$?
336                 echo "CONFIGURE STATUS: $cstatus"
337                 return $cstatus;
338         fi
339
340         if [ ! -x $srcdir/configure ]; then
341                 ls -l $srcdir/configure
342                 echo "$srcdir/configure is missing"
343                 cstatus=255
344                 echo "CONFIGURE STATUS: $cstatus"
345                 return $cstatus;
346         fi
347
348         echo "CFLAGS=$CFLAGS"
349         echo configure options: $config_and_prefix
350         echo CC="$CCACHE $compiler" $srcdir/configure $config_and_prefix
351
352         CC="$CCACHE $compiler"
353         export CC
354         $builddir/timelimit $MAXTIME $srcdir/configure $config_and_prefix
355         cstatus=$?
356
357         if [ x"$cstatus" != x"0" ]; then
358                 if [ -f config.log ]; then
359                         echo "contents of config.log:"
360                         cat config.log
361                 fi
362
363                 # Waf style
364                 if [ -f bin/config.log ]; then
365                         echo "contents of config.log:"
366                         cat bin/config.log
367                 fi
368         fi
369         echo "CONFIGURE STATUS: $cstatus"
370         return $cstatus
371 }
372
373 ############################
374 # show the configure log
375 ############################
376
377 action_config_log() {
378
379         log_files="config.log bin/config.log"
380         for f in $log_files; do
381                 if [ -f $f ]; then
382                         echo "contents of config.log:"
383                         cat $f
384                         return 0
385                 fi
386         done
387         return 0
388 }
389
390 ############################
391 # show the config.h
392 ############################
393
394 action_config_header() {
395         hdr_files="config.h include/config.h bin/default/config.h bin/default/source4/include/config.h bin/default/source3/include/config.h"
396         for h in $hdr_files; do
397                 if [ -f $h ]; then
398                         echo "contents of $h:"
399                         cat $h
400                         return 0
401                 fi
402         done
403
404         return 0
405 }
406
407
408
409 ############################
410 # build the tree
411 ############################
412 action_build() {
413         case "$tree" in
414         samba_4*)
415                 do_make everything
416                 bstatus=$?
417                 ;;
418         samba_3*)
419                 do_make everything torture
420                 bstatus=$?
421                 ;;
422         *)
423                 do_make all
424                 bstatus=$?
425                 ;;
426         esac
427
428         echo "BUILD STATUS: $bstatus"
429
430         return $bstatus
431 }
432
433 ############################
434 # show static analysis results
435 ############################
436
437 action_cc_checker() {
438
439         # default to passing the cc_checker
440         cccstatus=0
441
442         if [ -f ibm_checker.out ]; then
443                 cat ibm_checker.out
444                 cccstatus=`cat ibm_checker.out | grep '^\-\- ' | wc -l`
445         fi
446
447         echo "CC_CHECKER STATUS: $cccstatus"
448         return $cccstatus;      
449 }
450
451 ############################
452 # install the tree
453 ############################
454
455 action_install() {
456         if [ -d $prefix ]; then
457                 if [ "$noclean" != "yes" ]; then
458                         rm -rf $prefix
459                 fi
460         fi
461
462         do_make install
463         istatus=$?
464         echo "INSTALL STATUS: $istatus"
465         return $istatus;
466 }
467
468 ############################
469 # test the tree
470 action_test_samba() {
471         do_make test
472         totalstatus=$?
473
474         # if we produced a test summary then show it
475         [ -f st/summary ] && {
476                 echo "TEST SUMMARY"
477                 cat st/summary
478         }
479
480         return "$totalstatus"
481 }
482
483 action_test_generic() {
484         CC="$compiler"
485         export CC
486         do_make installcheck
487         totalstatus=$?
488         echo "TEST STATUS: $totalstatus"
489         return "$totalstatus"
490 }
491
492 action_test_lorikeet_heimdal() {
493         CC="$compiler"
494         export CC
495         SOCKET_WRAPPER_DIR=`pwd`/sw
496         mkdir $SOCKET_WRAPPER_DIR
497         export SOCKET_WRAPPER_DIR
498         do_make check
499         totalstatus=$?
500         SOCKET_WRAPPER_DIR=
501         export SOCKET_WRAPPER_DIR
502         echo "TEST STATUS: $totalstatus"
503         return "$totalstatus"
504 }
505
506
507 #############################
508 # attempt some basic tests of functionaility
509 # starting as basic as possible, and getting incresingly complex
510 #############################
511
512 action_test() {
513         # Samba needs crufty code of its own for backward
514         # compatiblity.  I think a better way to do this in the future
515         # is to just call 'make installcheck'.
516         case "$tree" in
517         samba*|smb-build|pidl)
518                 action_test_samba
519                 ;;
520         lorikeet-heimdal*)
521                 action_test_lorikeet_heimdal
522                 ;;
523         *)
524                 action_test_generic
525                 ;;
526         esac
527 }
528
529 ###########################
530 # do a test build of a particular tree
531 # This is the master function called by generic.fns or
532 # host.fns
533 ###########################
534
535 test_tree() {
536         tree=$1
537         source=$2
538         compiler="$3"
539         shift
540         shift
541         shift
542         echo "Starting to deal with tree $tree with compiler $compiler"
543         if [ "$compiler" = "gcc" ] && [ "$tree" != "ccache" ] && [ "$tree" != "ccache-maint" ] && ccache -V > /dev/null 2>/dev/null; then
544                 CCACHE="ccache"
545                 export CCACHE
546         else
547                 CCACHE=""
548         fi
549
550         # limit our resource usage
551         ulimit -t $MAXTIME 2> /dev/null
552
553         # max mem size 100M
554         ulimit -m $MAXMEM 2> /dev/null
555
556         # max file size 100M
557         # darn, this affects sparse files too! disable it
558         # ulimit -f 100000 2> /dev/null
559
560         # try and limit the number of open files to 250. That means we'll discover
561         # fd leaks faster
562         ulimit -n 250 2> /dev/null
563
564         # Keep stuff private
565         umask 077
566
567         if [ -z "$test_root" ]; then
568                 test_root=`pwd`
569         fi
570
571         log="build.$tree.$host.$compiler.log"
572         err="build.$tree.$host.$compiler.err"
573         sum="build.$tree.$host.$compiler.sum"
574         lck="build.$tree.lck"
575                 srcdir="$test_root/$tree/$source"
576
577         lock_file "$lck" || {
578                 return
579         }
580
581         # work out what other trees this package depends on
582         deptrees=""
583         case "$tree" in
584                 samba-gtk)
585                 deptrees="samba_4_0_test"
586                 ;;
587         esac
588
589         scm=`choose_scm "$tree"`
590
591         # pull the entries, if any
592         # Remove old .svn or .git files
593         # Move the current .svn org .git to .svn.old or
594         # .git.old then fetch the new from rsync
595         if fetch_revinfo "$tree" "$scm"; then
596                 for d in $deptrees; do
597                         # If there is dependency substree(s) we add info
598                         # from the dependency tree so that we
599                         # can rebuild in case one of them has changed
600                         dscm=`choose_scm "$d"`
601                         if [ -f "$test_root/$d.$dscm" ]; then
602                                 if [ "$d" != "$tree" ]; then
603                                         cat "$test_root/$d.$dscm" >> $test_root/$tree.$scm
604                                 fi
605                         fi
606                 done
607                 [ -f $test_root/$tree.$compiler.$scm.old ] && rm -f $test_root/$tree.$compiler.$scm.old
608                 [ -f $test_root/$tree.$compiler.$scm ] && mv $test_root/$tree.$compiler.$scm $test_root/$tree.$compiler.$scm.old
609                 [ -f $test_root/$tree.$scm ] && cp $test_root/$tree.$scm $test_root/$tree.$compiler.$scm
610
611                 if [ -f $test_root/$tree.$compiler.$scm.old ] && \
612                                 cmp $test_root/$tree.$compiler.$scm $test_root/$tree.$compiler.$scm.old > /dev/null; then
613
614                         echo "skip: $tree.$compiler nothing changed in $scm"
615                         cd $test_root
616                         send_logs_skip "$log" "$err"
617                         unlock_file "$lck"
618                         return
619                 fi
620         fi
621
622         # pull the tree
623         fetch_tree "$tree" || {
624                 cd $test_root
625                 unlock_file "$lck"
626                 return
627         }
628
629         if [ ! -x $srcdir/configure ] && [ "$tree" != "pidl" ]; then
630                 echo "skip: $tree.$compiler configure not present, try again next time!"
631                 cd $test_root
632                 unlock_file "$lck"
633                 return
634         fi
635
636         echo "Starting build of $tree.$compiler in process $$ at `date`"
637
638
639         # Parameters for the build depending on the tree
640         case "$tree" in
641                 libreplace)
642                         builddir="$test_root/tmp.$tree.$compiler"
643                         usingtmpbuild=1
644                         if [ -d $builddir ]; then
645                                 rm -rf $builddir
646                         fi
647                         mkdir -p $builddir
648                         export builddir
649                         ;;
650                 *)
651                         builddir=$srcdir
652                         usingtmpbuild=0
653                         export builddir
654                         ;;
655         esac
656
657         #Fix the user
658         if [ ! x$USER = x"" ]; then
659                 whoami=$USER
660         else 
661                 if [ ! x$LOGNAME = x"" ]; then
662                         whoami=$LOGNAME
663                 else
664                         whoami=build
665                 fi
666         fi
667
668         # build the timelimit utility
669         echo "Building timelimit"
670         mkdir -p $builddir
671         echo $compiler $TIMELIMIT_FLAGS -o $builddir/timelimit $test_root/timelimit.c
672         $compiler $TIMELIMIT_FLAGS -o $builddir/timelimit $test_root/timelimit.c || exit 1
673
674         # build the killbysubdir utility
675         echo "Building killbysubdir"
676         echo $compiler -o $builddir/killbysubdir $test_root/killbysubdir.c
677         $compiler -o $builddir/killbysubdir $test_root/killbysubdir.c
678
679         prefix="$test_root/prefix/$tree.$compiler"
680         mkdir -p "$prefix"
681
682         # This can be defined in <host>.fns files
683         sw_config=$config
684
685         case "$tree" in
686         lorikeet-heimdal)
687                 sw_config="$config --enable-socket-wrapper"
688                 ;;
689         samba_4*)
690                 sw_config="$config --enable-socket-wrapper"
691                 sw_config="$sw_config --enable-nss-wrapper"
692                 sw_config="$sw_config --enable-uid-wrapper"
693                 ;;
694         samba_3*)
695                 sw_config="$config --enable-socket-wrapper"
696                 sw_config="$sw_config --enable-nss-wrapper"
697                 ;;
698         samba-gtk)
699                 PKG_CONFIG_PATH="$test_root/prefix/samba_4_0_test.$compiler/lib/pkgconfig"
700                 export PKG_CONFIG_PATH
701                 ;;
702         *)
703                 testsuite=testsuite
704                 ;;
705         esac
706
707         if [ "$LCOV_REPORT" = "yes" ]; then
708                 GCOV_FLAGS="--coverage"
709                 CFLAGS="$CFLAGS $GCOV_FLAGS" 
710                 LDFLAGS="$LDFLAGS $GCOV_FLAGS" 
711                 export CFLAGS LDFLAGS
712         fi
713
714         config_and_prefix="$sw_config --prefix=$prefix"
715
716         # see if we need to rebuild
717         sum_tree $test_root $tree $sum $scm
718         echo "CFLAGS=$CFLAGS $config_and_prefix" >> $sum
719
720         if [ -f "$sum.old" ] && cmp "$sum" "$sum.old" > /dev/null; then
721                 echo "skip: $tree.$compiler nothing changed"
722                 cd $test_root
723                 send_logs_skip "$log" "$err"
724                 unlock_file "$lck"
725                 echo "Ending build of $tree.$compiler in process $$ at `date`"
726                 return
727         fi
728
729         # we do need to rebuild - save the old sum
730         [ -f $sum.old ] && /bin/rm -f $sum.old
731         mv $sum $sum.old
732
733         #Action == what to do ie. configure config_log ...
734         actions="$*"
735
736         if [ "$actions" = "" ]; then
737                 actions="configure config_log config_header build install test"
738         fi
739
740         # start the build
741         (
742         {
743                 # we all want to be able to read the output...
744                 LANG=C
745                 export LANG
746
747                 uname -a
748
749                 echo ""
750                 echo "build_test                  : $build_test_id"
751                 echo "build_test.fns      : $build_test_fns_id"
752                 echo "local settings file : $build_test_settings_local_file"
753                 echo "local functions file: $build_test_fns_local_file"
754                 echo "used .fns file      : $build_test_used_fns_file"
755                 echo ""
756
757                 # we need to be able to see if a build farm machine is accumulating
758                 # stuck processes. We do this in two ways, as we don't know what style
759                 # of ps it will have
760                 ps xfuw 2> /dev/null
761                 ps -fu $USER 2> /dev/null
762
763                 echo "building $tree with CC=$compiler on $host at "`date`
764                 echo "builddir=$builddir"
765                 echo "prefix=$prefix"
766
767                 echo "Showing limits"
768                 ulimit -a 2> /dev/null
769
770                 # the following is for non-samba builds only
771                 if [ "$scm" = "svn" -a -r $test_root/$tree.svn ]; then
772                         h_rev=`grep 'Revision: ' $test_root/$tree.svn | cut -d ':' -f2 | cut -d ' ' -f2 | sed 1q`
773                         if [ -n "$h_rev" ]; then
774                                 echo "HIGHEST SVN REVISION: $h_rev"
775                         fi
776                         rev=`grep 'Last Changed Rev: ' $test_root/$tree.svn | cut -d ':' -f2 | cut -d ' ' -f2 | sed 1q`
777                         if [ -n "$rev" ]; then
778                         echo "BUILD REVISION: $rev"
779                         fi
780                 elif [ "$scm" = "git" -a -r $test_root/$tree.git ]; then
781                         csha1=`cat $test_root/$tree.git |head -3 | tail -1`
782                         if [ -n "$csha1" ]; then
783                                 echo "BUILD COMMIT REVISION: $csha1"
784                         fi
785                         cdate=`cat $test_root/$tree.git |head -4 | tail -1`
786                         if [ -n "$cdate" ]; then
787                                 echo "BUILD COMMIT DATE: $cdate"
788                         fi
789                         ctime=`cat $test_root/$tree.git |head -2 | tail -1`
790                         if [ -n "$ctime" ]; then
791                                 echo "BUILD COMMIT TIME: $ctime"
792                   fi
793                 fi
794
795                 if [ -x $builddir/killbysubdir ]; then
796                         echo "$builddir/killbysubdir $builddir in `pwd`"
797                         $builddir/killbysubdir $builddir
798                 fi
799
800                 for action in $actions; do
801
802                         echo Running action $action
803
804                         date
805
806                         cd $builddir || exit 1
807                         export srcdir
808                         df .
809                         mount
810                         vmstat
811
812                         if [ "x$PREHOOKS" != "x" ]; then
813                                 for hooks in $PREHOOKS; do
814                                         if [ "x$hooks" = "x$action" ]; then
815                                                 ( prehook_$action )
816                                         fi
817                                 done
818                         fi
819
820                         ( action_$action )
821                         action_status=$?
822
823                         if [ "x$POSTHOOKS" != "x" ]; then
824                                 for hooks in $POSTHOOKS; do
825                                         if [ "x$hooks" = "x$action" ]; then
826                                                 ( posthook_$action )
827                                         fi
828                                 done
829                         fi
830
831                         df .
832
833                         if [ $action_status != 0 ]; then
834                                 echo "ACTION FAILED: $action";
835                                 echo " return code $action_status $action";
836                         else
837                                 echo "ACTION PASSED: $action";
838                         fi
839
840                         if [ $action_status != 0 ]; then 
841                                 break;
842                         fi
843                 done
844
845
846                 if [ "$noclean" = "yes" ]; then
847                         echo cleanup skipped!
848                 else
849                         echo cleaning up
850                         do_make clean
851                 fi
852                 date
853         } 3>&2 2>&1 1>&3 | tee "$err"
854         ) > "$log" 2>&1
855         # be aware the above channel swap may sometimes result in unordered
856         # stdout/stderr merge
857
858         if [ "$LCOV_REPORT" = "yes" ]; then
859                 chmod u=rwX,g=rX,o=rX -R $builddir/coverage
860                 rsync -rct -q --password-file=.password -z --timeout=200 \
861                         $builddir/coverage/ $host@build.samba.org::lcov_data/$host/$tree/
862         fi
863
864         cd $test_root
865
866         /bin/rm -rf $prefix
867         if [ "$usingtmpbuild" = "1" ]; then
868                 if [ "$noclean" = "yes" ]; then
869                         echo builddir cleanup skipped!
870                 else
871                         /bin/rm -rf $builddir
872                 fi
873         fi
874         # send the logs to the master site
875         send_logs "$log" "$err"
876
877         # cleanup
878         echo "Ending build of $tree.$compiler in process $$ at `date`"
879         unlock_file "$lck"
880 }
881
882 #########################################################
883 # if you want to build only one project at a time
884 # add 'global_lock' after 'per_run_hook' and
885 # 'global_unlock' to the end of the file
886 #########################################################
887
888 global_lock() {
889         lock_file "global.lck" || {
890                 exit 0
891         }
892 }
893
894 global_unlock() {
895         unlock_file "global.lck"
896 }
897
898 delete_old_tree() {
899         otree=$1
900         test -z "$otree" && return 0;
901
902         rm -rf $otree
903         rm -rf $otree.svn
904         rm -rf $otree.*.svn
905         rm -rf $otree.git
906         rm -rf $otree.*.git
907         rm -rf build.$otree.*
908 }
909
910 # this is a special fn that allows us to add a "special" hook to the build
911 # farm that we want to do to the build farm. never leave it empty. instead,
912 # use ":" as the fn body.
913 per_run_hook() {
914         # kill old processes on systems with a known problem
915         case $host in
916         nohost)
917                 echo "just a placeholder";
918                 ;;
919         deckchair)
920                 rm -f deckchair.fns
921                 ;;
922         esac
923
924         # trim the log if too large
925         if [ "`wc -c < build.log`" -gt 2000000 ]; then
926         rm -f build.log
927         fi
928
929         old_trees="web popt distcc samba-gtk smb-build lorikeet-heimdal samba_3_2"
930         old_trees="$old_tree samba_3_2_test samba4 samba_4_0_waf samba_4_0_waf.metze"
931         old_trees="$old_tree samba_3_X_test samba_3_X_devel samba_3_X_devel"
932         for d in $old_trees; do
933                 delete_old_tree $d
934         done
935 }
936
937
938 ######################################################
939 # main code that is run on each call to the build code
940 ######################################################
941 rsync --timeout=200 -q -az build.samba.org::build_farm/*.c .
942
943
944 # build.log can grow to an excessive size, trim it beyond 50M
945 if [ -f build.log ]; then
946         find build.log -size +100000 -exec /bin/rm '{}' \;
947 fi