--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+
+#test_tree samba source gcc
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba4 source gcc
+config="" test_tree rsync . gcc
--- /dev/null
+test_tree samba4 source gcc
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree rsync . gcc
+test_tree distcc . gcc
+test_tree ccache . gcc
--- /dev/null
+This is the build system for build.samba.org
+
+tridge@samba.org, April 2001
+
+To set it up on a new box you need to do this:
+
+1) create an account on the box (I'll assume its called "build")
+2) copy over build_test to ~build/build_farm/
+3) put the right password in ~build/build_farm/.password
+4) arrange for ~build/build_farm/build_test to be run regularly
+ from cron
+5) add the host to build.pl on dp.samba.org
+6) create a HOSTNAME.fns file that defines what gets built on
+ build.samba.org
+
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree samba4 source gcc
+
+export config="--with-utmp --with-pam --with-quotas --with-smbmount"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
+config="" test_tree rsync . gcc
+
--- /dev/null
+test_tree samba4 source cc
+
+export config="--with-utmp"
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+config="" test_tree rsync . cc
--- /dev/null
+test_tree samba4 source cc
+
+export config="--with-acl-support --with-utmp"
+export CFLAGS="-O -64"
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+config="" test_tree rsync . cc
+
+export CFLAGS="-O -Wall"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba4 source gcc
+config="" test_tree rsync . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount --enable-krb5developer"
+
+test_tree samba source gcc
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount"
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
--- /dev/null
+#!/bin/bash
+# this is the main build script for build.samba.org
+# it gets run on all the build boxes via cron
+
+# any errors get put in build.log
+
+# we used a fixed path that is a superset of the required paths.
+export PATH=~/bin:/usr/local/bin:/usr/bin:/bin:/opt/SUNWspro/bin:/usr/ccs/bin:/sbin:/usr/sbin:/usr/local/sbin
+
+# go to our main directory
+cd ~/build_farm || exit 1
+
+(
+
+ echo
+ date
+
+ # we only want the short name of the host - use cut for portability
+ host=`hostname | cut -d. -f1`
+
+ # make sure the password isn't readable by anyone
+ chmod 600 .password
+
+ # grab the latest versions of the scripts
+ rsync --timeout=200 -q -az samba.org::build_farm/*.fns .
+
+ # load general functions
+ . build_test.fns
+
+ if [ -f $host.fns ]; then
+ # load host specific functions
+ . $host.fns
+ else
+ . generic.fns
+ fi
+
+) >> build.log 2>&1
--- /dev/null
+# -*- mode: shell-script; sh-indentation: 8; indent-tabs-mode: t; -*-
+
+# build_farm -- distributed build/test architecture for samba, rsync, etc
+
+# Copyright (C) 2001 by Andrew Tridgell <tridge@samba.org>
+# Copyright (C) 2001 by Andrew Bartlett <abartlet@samba.org>
+# Copyright (C) 2001, 2003 by Martin Pool <mbp@samba.org>
+
+
+#############################
+# build a signature of a tree, used to see if we
+# need to rebuild
+sum_tree() {
+ sum_tree_test_root=$1
+ sum_tree_tree=$2
+ sum_tree_testsuite=$3
+ sum_tree_sum=$4
+ find $sum_tree_test_root/$sum_tree_tree -type f -print | grep -v '.svn/' | xargs sum > $sum_tree_sum
+ sum build_test build_test.fns >> $sum_tree_sum
+
+ if [ -f "$host.fns" ]; then
+ sum $host.fns >> $sum_tree_sum
+ fi
+
+ if [ -d "$sum_tree_testsuite" ]; then
+ find $sum_tree_test_root/$sum_tree_testsuite -type f -print | grep -v '.svn/' | xargs sum >> $sum_tree_sum
+ fi
+}
+
+#############################
+# send the logs to the master site
+send_logs() {
+ if [ "$nologreturn" = "yes" ]; then
+ echo "skipping log transfer"
+ else
+ log="$1"
+ err="$2"
+ chmod 0644 "$log" "$err"
+ rsync -q --password-file=.password -atz --timeout=200 \
+ "$log" "$err" $host@samba.org::build_farm_data/
+ fi
+}
+
+############################
+# fetch the latest copy of the tree
+fetch_tree() {
+ if [ "$norsync" = "yes" ]; then
+ echo "skipping tree transfer"
+ else
+ tree=$1
+ if rsync -q --partial --timeout=200 -az --delete --ignore-errors \
+ samba.org::ftp/unpacked/$tree $test_root; then
+ echo "transferred $tree OK"
+ else
+ echo "transfer of $tree failed code $?"
+ return 1
+ fi
+ fi
+ return 0
+}
+
+############################
+# grab a lock file. Not atomic, but close :)
+# tries to cope with NFS
+lock_file() {
+ lck="$1"
+ machine=`cat "$lck" 2> /dev/null | cut -d: -f1`
+ pid=`cat "$lck" 2> /dev/null | cut -d: -f2`
+
+ if [ -f "$lck" ] &&
+ ( [ $machine != $host ] || kill -0 $pid ) 2> /dev/null; then
+ echo "lock file $lck is valid for $machine:$pid"
+ return 1
+ fi
+ /bin/rm -f "$lck"
+ echo "$host:$$" > "$lck"
+ return 0
+}
+
+############################
+# unlock a lock file
+unlock_file() {
+ lck="$1"
+ /bin/rm -f "$lck"
+}
+
+############################
+# run make, and print trace
+do_make() {
+ if [ x$MAKE = x ]
+ then
+ MAKE=make
+ fi
+
+ for t in $*; do
+ echo "$MAKE $t"
+ "$MAKE" "$t"
+ status=$?
+ if [ $status != 0 ]; then
+ return $status;
+ fi
+ done
+ return 0
+}
+
+############################
+# configure the tree
+action_configure() {
+ if [ ! -x configure ]; then
+ ./autogen.sh
+ fi
+ echo "CFLAGS=$CFLAGS"
+ echo configure options: $config_and_prefix
+ echo CC="$compiler" ./configure $config_and_prefix
+ CC="$compiler"
+ export CC
+ ./configure $config_and_prefix
+ cstatus=$?
+ echo "CONFIGURE STATUS: $cstatus"
+ if [ $cstatus != 0 ]; then
+ echo "contents of config.log:"
+ cat config.log
+ fi
+ return $cstatus;
+}
+
+############################
+# build the tree
+action_build() {
+ case "$tree" in
+ samba4)
+ do_make proto everything
+ ;;
+ samba|samba_3_0)
+ do_make proto everything torture
+ ;;
+ samba_2_2)
+ do_make everything bin/smbtorture
+ ;;
+ *)
+ do_make all
+ ;;
+ esac
+
+ bstatus=$?
+ echo "BUILD STATUS: $bstatus"
+ return $bstatus
+}
+
+############################
+# install the tree
+action_install() {
+ if [ -d $prefix ]; then
+ if [ "$noclean" != "yes" ]; then
+ rm -rf $prefix
+ fi
+ fi
+
+ do_make install
+ istatus=$?
+ echo "INSTALL STATUS: $istatus"
+ return $istatus;
+}
+
+############################
+# run each test, allow for reruns
+each_test() {
+ echo "--==--==--==--==--==--==--==--==--==--==--"
+ echo "Running test $test (level $loglevel stdout)"
+ echo "--==--==--==--==--==--==--==--==--==--==--"
+ echo "--==--==--==--==--==--==--==--==--==--==--" >> $logfile
+ echo "Running test $test (level $loglevel log)" >> $logfile
+ echo "--==--==--==--==--==--==--==--==--==--==--" >> $logfile
+ date
+
+ /bin/rm -rf $testdir
+ mkdir $testdir
+
+ case "$tree" in
+ samba*)
+ /bin/rm -rf $prefix/lib
+ mkdir $prefix/lib
+ ;;
+ esac
+
+ (
+ cd $test_root/$tree/$testsuite || exit 1
+ echo "running tests in "`pwd`
+ echo " test_root=$test_root"
+ echo " tree=$tree"
+ echo " testsuite=$testsuite"
+ export prefix
+ export host
+ export testdir
+ export test
+ export whoami
+ export loglevel
+ . $test.test
+ )
+ tstatus=$?
+
+ echo "=========================================="
+ echo "==========================================" >> $logfile
+
+ if [ $tstatus != 0 ]; then
+ FAILED_TESTS="$FAILED_TESTS $test"
+ echo "TEST FAILED: $test (status $tstatus)"
+ echo "TEST FAILED: $test (status $tstatus)" >> $logfile
+ else
+ echo "TEST PASSED: $test"
+ echo "TEST PASSED: $test" >> $logfile
+ fi
+
+ echo "=========================================="
+ echo "==========================================" >> $logfile
+
+}
+
+#############################
+# do pre-test cleanup work for samba and samba_2_2 and samba_3_0
+# then run the tests
+action_test_samba() {
+ logfile="$prefix/var/log.smbd"
+
+ LIBSMB_PROG=$prefix/sbin/smbd
+ export LIBSMB_PROG
+
+ if [ \! -d "$prefix/var" ]
+ then
+ mkdir "$prefix/var"
+ fi
+
+ if [ -f "$logfile" ]
+ then
+ rm -f $logfile
+ fi
+
+ testdir="$prefix/testdir"
+
+ runlist_file="$test_root/$tree/$testsuite/runlist"
+ if [ ! -f "$runlist_file" ]; then
+ echo "No testsuite defined in $runlist_file"
+ return 0;
+ fi
+
+ # some special magic for transitioning across to cssified
+ # output
+ echo "*build_farm transition magic*"
+
+ . $test_root/$tree/$testsuite/runlist
+ testhost=TEST_$host
+# testlist=${!testhost}
+ if [ "$testlist" = "" ]; then
+ testlist=$TEST_ALL
+ fi
+
+ tstatus=0
+ totalfailed=0
+ loglevel=1
+ for test in $testlist; do
+ each_test $test;
+ if [ $tstatus != 0 ]; then
+ totalfailed=`expr $totalfailed + 1`;
+ loglevel=10
+ each_test $test
+ loglevel=1
+ fi
+ done
+ echo "contents of $logfile:"
+ cat $logfile
+ echo "FAILED TESTS: $FAILED_TESTS"
+ echo "TEST STATUS: $totalfailed"
+ return $totalfailed
+}
+
+
+action_test_generic() {
+ CC="$compiler"
+ export CC
+ do_make installcheck
+ totalstatus=$?
+ echo "TEST STATUS: $totalstatus"
+ return "$totalstatus"
+}
+
+
+#############################
+# attempt some basic tests of functionaility
+# starting as basic as possible, and getting incresingly complex
+
+action_test() {
+ # Samba needs crufty code of its own for backward
+ # compatiblity. I think a better way to do this in the future
+ # is to just call 'make installcheck'.
+ case "$tree" in
+ samba*)
+ action_test_samba
+ ;;
+ *)
+ action_test_generic
+ ;;
+ esac
+}
+
+###########################
+# do a test build of a particular tree
+test_tree() {
+ tree=$1
+ source=$2
+ compiler="$3"
+ shift
+ shift
+ shift
+
+ # limit our resource usage
+ ulimit -t 300
+ ulimit -m 50000
+
+ # Keep stuff private
+ umask 077
+
+ if [ -z "$test_root" ]; then
+ test_root=`pwd`
+ fi
+
+ log="build.$tree.$host.$compiler.log"
+ err="build.$tree.$host.$compiler.err"
+ sum="build.$tree.$host.$compiler.sum"
+ lck="$test_root/build.$tree.lck"
+
+ if ! lock_file "$lck"; then
+ return
+ fi
+
+ # pull the tree
+ if ! fetch_tree "$tree"; then
+ unlock_file "$lck"
+ return
+ fi
+
+ if [ ! $USER = "" ]; then
+ whoami=$USER
+ else
+ if [ ! $LOGNAME = "" ]; then
+ whoami=$LOGNAME
+ else
+ whoami=build
+ fi
+ fi
+
+ prefix="$test_root/prefix"
+ if [ ! -d $prefix ]; then
+ mkdir $prefix
+ fi
+ prefix="$prefix/$tree"
+
+ case "$tree" in
+ samba|samba_3_0)
+ testsuite=testsuite/build_farm
+ ;;
+ samba_2_2)
+ testsuite=testsuite/build_farm
+ config="$config --with-codepagedir=$prefix/codepages"
+ ;;
+ *)
+ testsuite=testsuite
+ ;;
+ esac
+
+ config_and_prefix="$config --prefix=$prefix"
+
+ # see if we need to rebuild
+ sum_tree $test_root $tree $testsuite $sum
+ echo "CFLAGS=$CFLAGS $config_and_prefix" >> $sum
+
+ if cmp "$sum" "$sum.old" > /dev/null; then
+ echo "skip: $tree.$compiler nothing changed"
+ touch "$log" "$err"
+ send_logs "$log" "$err"
+ unlock_file "$lck"
+ return
+ fi
+
+ # we do need to rebuild - save the old sum
+ /bin/rm -f $sum.old
+ mv $sum $sum.old
+
+ actions="$*"
+
+ if [ "$actions" = "" ]; then
+ actions="configure build install test"
+ fi
+
+ # start the build
+ (
+ uname -a
+
+ # some special magic for transitioning across to cssified
+ # output
+ echo "*build_farm transition magic*"
+
+ echo "building $tree with CC=$compiler on $host at "`date`
+ for action in $actions; do
+
+ echo Running action $action
+
+ date
+ srcdir=$test_root/$tree/$source
+ cd $srcdir
+ export srcdir
+ df .
+
+ ( action_$action )
+ action_status=$?
+
+ if [ $action_status != 0 ]; then
+ echo "ACTION FAILED: $action";
+ else
+ echo "ACTION PASSED: $action";
+ fi
+
+ if [ $action_status != 0 ]; then
+ break;
+ fi
+
+ done
+
+ if [ "$noclean" = "yes" ]; then
+ echo cleanup skipped!
+ else
+ echo cleaning up
+ do_make clean
+ /bin/rm -rf $prefix
+ fi
+ date
+ ) > "$log" 2> "$err"
+
+ # send the logs to the master site
+ send_logs "$log" "$err"
+
+ # cleanup
+ unlock_file "$lck"
+}
--- /dev/null
+export config="--with-acl-support --with-pam --with-utmp"
+
+export CFLAGS="-O -Wall"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba source gcc
+config="" test_tree samba4 source gcc
+config="" test_tree rsync . gcc
+config="" test_tree ccache . gcc
+
--- /dev/null
+#!/usr/bin/perl -w
+# This CGI script presents the results of the build_farm build
+# tridge@samba.org, April 2001
+
+use strict;
+use util;
+use POSIX;
+use Data::Dumper;
+use File::stat;
+use Date::Parse;
+
+####################################
+# parse a CVS date
+sub cvs_parse_date($)
+{
+ my $s = shift;
+
+ if (! ($s =~ /@/)) {
+ return str2time($s);
+ }
+
+ if ($s =~ /(.*) (.*) ([0-9]+), ([0-9]+) @ ([0-9]+):([0-9]+)/) {
+ my $day = $1;
+ my $month = $2;
+ my $mday = $3;
+ my $year = $4;
+ my $hour = $5;
+ my $min = $6;
+ my (%months) = ('January' => 1, 'February' => 2, 'March' => 3, 'April' => 4,
+ 'May' => 5, 'June' => 6, 'July' => 7, 'August' => 8, 'September' => 9,
+ 'October' => 10, 'November' => 11, 'December' => 12);
+ my $t = mktime(0, $min, $hour, $mday, $months{$month}-1, $year-1900);
+ return $t;
+ }
+
+ print "ERROR: bad date format $s\n";
+ return 0;
+}
+
+
+####################################
+# push an entry onto the array
+
+# FIXME: This incorrectly handles multiple commits with the same log
+# message. The cvslog output only shows the revisions for the last
+# commit, but actually we want to either not coalesce, or show the
+# overall delta.
+
+sub push_entry($$$$$)
+{
+ my $entry = shift;
+ my $log = shift;
+ my $days = shift;
+ my $tree = shift;
+ my $tag = shift;
+ my $lastentry = $log->[$#{$log}];
+
+ if ($lastentry->{DATE} && $lastentry->{AUTHOR} &&
+ ($lastentry->{DATE} > $entry->{DATE}-600) &&
+ ($lastentry->{AUTHOR} eq $entry->{AUTHOR}) &&
+ ((!$lastentry->{TAG} && !$entry->{TAG}) ||
+ ($lastentry->{TAG} eq $entry->{TAG})) &&
+ ((!$lastentry->{MESSAGE} && !$entry->{MESSAGE}) ||
+ ($lastentry->{MESSAGE} eq $entry->{MESSAGE}))) {
+
+ if (exists $lastentry->{FILES}) {
+ $lastentry->{FILES} .= " $entry->{FILES}";
+ } else {
+ $lastentry->{FILES} = $entry->{FILES};
+ }
+
+ if (exists $lastentry->{ADDED}) {
+ $lastentry->{ADDED} .= " $entry->{ADDED}";
+ } else {
+ $lastentry->{ADDED} = $entry->{ADDED};
+ }
+
+ if (exists $lastentry->{REMOVED}) {
+ $lastentry->{REMOVED} .= " $entry->{REMOVED}";
+ } else {
+ $lastentry->{REMOVED} = $entry->{REMOVED};
+ }
+
+ if (exists $lastentry->{REVISIONS}) {
+ $lastentry->{REVISIONS} = {%{$lastentry->{REVISIONS}},%{$entry->{REVISIONS}}};
+ } else {
+ $lastentry->{REVISIONS} = $entry->{REVISIONS};
+ }
+ } else {
+ if (($entry->{DATE} > time() - $days*24*60*60) &&
+ ((!$entry->{TAG} && !$tag) ||
+ ($entry->{TAG} eq $tag)) &&
+ ($entry->{TREE} eq $tree)) {
+ push(@{$log}, $entry);
+ }
+ }
+ return $log;
+}
+
+####################################
+# return an array of logfile entries given a cvs log file.
+# Only return entries newer than $days old
+sub cvs_parse($$$$)
+{
+ my $file = shift;
+ my $days = shift;
+ my $tree = shift;
+ my $tag = shift;
+ my $log;
+ my $entry;
+
+ open(FILE, "< $file");
+ while (<FILE>) {
+ my $line = $_;
+
+ # ignore separator lines
+ if ($line =~ /^[*]+/) { next; }
+
+ if ($line =~ /^Date:\s*(.*)/) {
+ if ($entry->{DATE}) {
+ $log = push_entry($entry, $log, $days, $tree, $tag);
+ }
+ $entry = {};
+ $entry->{DATE} = cvs_parse_date($1);
+ $entry->{DIR} = "";
+ next;
+ }
+
+ if ($line =~ /^Author:\s*(.*)/) {
+ $entry->{AUTHOR} = $1;
+ next;
+ }
+
+ if ($line =~ /^Update of (.*)/) {
+ $entry->{TREE} = $1;
+ if ($entry->{TREE} =~ /\/(data|home)\/cvs\/([^\/]*)\/?(.*)/) {
+ $entry->{TREE} = $2;
+ $entry->{DIR} = $3;
+ if ($entry->{DIR}) { $entry->{DIR} .= "/"; }
+ } elsif ($entry->{TREE} =~ /\/home\/tridge\/cvstest\/([^\/]*)\/?(.*)/) {
+ $entry->{TREE} = $1;
+ $entry->{DIR} = $2;
+ if ($entry->{DIR}) { $entry->{DIR} .= "/"; }
+ } else {
+ print "badly formed tree $entry->{TREE}\n";
+ }
+ if (! $entry->{DIR}) { $entry->{DIR} = ""; }
+ next;
+ }
+
+ if ($line =~ /^Modified Files:/) {
+ while (<FILE>) {
+ $line = $_;
+ if ($line =~ /^[*A-Z]/) { last; }
+
+ if ($line =~ /^\s*Tag: (.*)/) {
+ $entry->{TAG} = $1;
+ next;
+ }
+
+ while ($line =~ /\s*([^\s]+)(.*)/) {
+ if ($entry->{FILES}) {
+ $entry->{FILES} .= " $entry->{DIR}$1";
+ } else {
+ $entry->{FILES} = "$entry->{DIR}$1";
+ }
+ $line = $2;
+ }
+ }
+ }
+
+ if ($line =~ /^Added Files:/) {
+ while (<FILE>) {
+ $line = $_;
+ if ($line =~ /^[*A-Z]/) { last; }
+
+ if ($line =~ /^\s*Tag: (.*)/) {
+ $entry->{TAG} = $1;
+ next;
+ }
+
+ while ($line =~ /\s*([^\s]+)(.*)/) {
+ if ($entry->{ADDED}) {
+ $entry->{ADDED} .= " $entry->{DIR}$1";
+ } else {
+ $entry->{ADDED} = "$entry->{DIR}$1";
+ }
+ $line = $2;
+ }
+ }
+ }
+
+ if ($line =~ /^Removed Files:/) {
+ while (<FILE>) {
+ $line = $_;
+ if ($line =~ /^[*A-Z]/) { last; }
+
+ if ($line =~ /^\s*Tag: (.*)/) {
+ $entry->{TAG} = $1;
+ next;
+ }
+
+ while ($line =~ /\s*([^\s]+)(.*)/) {
+ if ($entry->{REMOVED}) {
+ $entry->{REMOVED} .= " $entry->{DIR}$1";
+ } else {
+ $entry->{REMOVED} = "$entry->{DIR}$1";
+ }
+ $line = $2;
+ }
+ }
+ }
+
+ if ($line =~ /^Log Message:/) {
+ while (<FILE>) {
+ $line = $_;
+ if ($line eq "****************************************\n") { last; }
+ if ($line =~ /^Revisions:/) { last; }
+ $entry->{MESSAGE} .= $line;
+ }
+ }
+
+ if ($line =~ /^Revisions:/) {
+ while (<FILE>) {
+ $line = $_;
+ if ($line =~ /^[*]/) { last; }
+ if ($line =~ /^\s*http/) { next; }
+ if ($line =~ /^\s*(.*?)\s*(NONE|[0-9][0-9.]*) => (NONE|[0-9][0-9.]*)/) {
+ my $file = "$entry->{DIR}$1";
+ my $rev1 = $2;
+ my $rev2 = $3;
+ $entry->{REVISIONS}->{$file}->{REV1} = $rev1;
+ $entry->{REVISIONS}->{$file}->{REV2} = $rev2;
+ }
+ }
+ }
+ }
+
+ if ($entry->{DATE}) {
+ $log = push_entry($entry, $log, $days, $tree, $tag);
+ }
+
+ close(FILE);
+
+ # cleanup the messages
+ for (my $line=0; $line <= $#{$log}; $line++) {
+ $entry = $log->[$line];
+ if ($entry->{MESSAGE}) {
+ while (chomp($entry->{MESSAGE})) { }
+ }
+ }
+
+ return $log;
+}
+
+
+######################################
+# main program
+if ($#ARGV < 4) {
+ print "
+Usage: cvslog.pl <file> <days> <tree> <tag> <dest>
+}";
+ exit(1);
+}
+
+my $file = $ARGV[0];
+my $days = $ARGV[1];
+my $tree = $ARGV[2];
+my $tag = $ARGV[3];
+my $dest = $ARGV[4];
+
+my $log = cvs_parse($ARGV[0], $days, $tree, $tag);
+
+util::SaveStructure($dest, $log);
--- /dev/null
+test_tree rsync . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+test_tree samba4 source gcc
+export config="--with-utmp --with-pam"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
+config="" test_tree rsync . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree samba4 source gcc
+export config="--with-utmp"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
+config="" test_tree rsync . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-utmp --with-pam --with-quotas --with-smbmount"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
+config="" test_tree rsync . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba4 source gcc
+test_tree rsync . gcc
+test_tree distcc . gcc
+test_tree ccache . gcc
--- /dev/null
+test_tree samba4 source gcc
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree rsync . gcc
+test_tree distcc . gcc
+test_tree ccache . gcc
--- /dev/null
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+test_tree samba4 source cc
+test_tree rsync . cc
+test_tree distcc . cc
+test_tree ccache . cc
+
--- /dev/null
+#!/bin/bash
+
+# This script converts log files produced by CVS into Perl DataDumper
+# files that can be easily loaded by the buildfarm web interface.
+
+cd $HOME/master || exit 1
+
+(
+
+./cvslog.pl /data/cvs/CVSROOT/samba.updates 60 samba "" cache/history.samba
+./cvslog.pl /data/cvs/CVSROOT/samba.updates 60 samba "SAMBA_2_2" cache/history.samba_2_2
+./cvslog.pl /data/cvs/CVSROOT/samba.updates 60 samba "SAMBA_3_0" cache/history.samba_3_0
+./cvslog.pl /data/cvs/CVSROOT/samba-docs.updates 60 samba-docs "" cache/history.samba-docs
+./cvslog.pl /data/cvs/CVSROOT/samba4.updates 60 samba4 "" cache/history.samba4
+./cvslog.pl /data/cvs/CVSROOT/rsync.updates 60 rsync "" cache/history.rsync
+./cvslog.pl /data/cvs/CVSROOT/distcc.updates 60 distcc "" cache/history.distcc
+./cvslog.pl /data/cvs/CVSROOT/ccache.updates 60 ccache "" cache/history.ccache
+
+) > history.log 2>&1
+
+
+
--- /dev/null
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+test_tree samba4 source cc
+test_tree rsync . cc
+test_tree distcc . cc
+test_tree ccache . cc
+
+export CFLAGS="-O -Wall"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba4 source cc
+test_tree rsync . gcc
+test_tree distcc . gcc
+test_tree ccache . gcc
--- /dev/null
+export config="--with-acl-support --with-pam --with-utmp"
+
+export CFLAGS="-O -Wall"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba source gcc
+config="" test_tree samba4 source gcc
+config="" test_tree rsync . gcc
+config="" test_tree ccache . gcc
+
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree samba4 source gcc
+export config="--with-utmp"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
+config="" test_tree rsync . gcc
--- /dev/null
+test_tree samba source gcc
+test_tree samba4 source gcc
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree rsync . gcc
+test_tree distcc . gcc
+test_tree ccache . gcc
--- /dev/null
+export CFLAGS="-D_POSIX_C_SOURCE=199506L -D_SYSV -D__VOS__"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba4 source gcc
+test_tree rsync . gcc
--- /dev/null
+test_tree samba_2_2 source cc
+test_tree samba4 source cc
+
+config="--with-pam" test_tree samba_3_0 source cc
+
+test_tree rsync . cc
+MAKE=gmake test_tree distcc . gcc
+test_tree ccache . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount --enable-krb5developer"
+
+test_tree samba source gcc
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+export config="--with-quotas --with-smbmount"
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba4 source gcc
+
--- /dev/null
+export config="--with-acl-support --with-pam --with-utmp"
+
+export CFLAGS="-O -Wall"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba source gcc
+config="" test_tree samba4 source gcc
+config="" test_tree rsync . gcc
+config="" test_tree ccache . gcc
+
--- /dev/null
+test_tree samba4 source gcc
+
+# (vance) added LDFLAGS=-bnoquiet Wed Jun 23 2004
+# to help trouble shoot the compile of 2_2
+export config="--with-utmp LDFLAGS=-bnoquiet"
+test_tree samba_2_2 source gcc
+export config=""
+test_tree samba_3_0 source gcc
+config="" test_tree rsync . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree samba4 source gcc
+
+export config="--with-utmp --with-pam --with-syslog --with-quotas --with-smbmount --with-netatalk --with-ssl --with-sslinc=/usr/include/openssl"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
+config="" test_tree rsync . gcc
--- /dev/null
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+test_tree samba4 source cc
+test_tree rsync . cc
+MAKE=gmake test_tree distcc . gcc
+test_tree ccache . gcc
--- /dev/null
+config="--with-pam --with-pam_smbpass --with-utmp"
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+test_tree samba4 source cc
+config="" test_tree rsync . cc
+config="" test_tree distcc . cc
+config="" test_tree ccache . cc
+
+export CFLAGS="-O -Wall"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba4 source gcc
+config="" test_tree rsync . gcc
+config="" test_tree distcc . gcc
+config="" test_tree ccache . gcc
--- /dev/null
+export config="--with-acl-support --with-pam --with-utmp"
+
+export CFLAGS="-O -Wall"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba source gcc
+config="" test_tree samba4 source gcc
+config="" test_tree rsync . gcc
+config="" test_tree ccache . gcc
+
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-utmp --with-pam"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree samba4 source gcc
+export config="--with-utmp --with-pam"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
+config="" test_tree rsync . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount"
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
--- /dev/null
+export config="--with-utmp"
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+config="" test_tree rsync . cc
+
+export CFLAGS="-O -Wall -Wno-comment"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba4 source gcc
+config="" test_tree rsync . gcc
--- /dev/null
+export config="--with-utmp"
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+config="" test_tree rsync . cc
+
+export CFLAGS="-g -O -Wall -Wno-comment"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba4 source gcc
+config="" test_tree rsync . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount"
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
--- /dev/null
+test_tree samba4 source gcc
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree rsync . gcc
+test_tree distcc . gcc
+test_tree ccache . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount --enable-krb5developer"
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount --enable-krb5developer"
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount --enable-krb5developer"
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount --enable-krb5-developer"
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
--- /dev/null
+test_tree samba4 source cc
+
+export config="--with-acl-support --with-pam --with-utmp"
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+config="" test_tree rsync . cc
+config="" test_tree ccache . cc
+
+export CFLAGS="-O -Wall"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+config="" test_tree samba4 source gcc
+config="" test_tree rsync . gcc
+config="" test_tree ccache . gcc
+
--- /dev/null
+export CFLAGS="-O -Wall"
+export MAKEFLAGS="-j 4"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-utmp --with-pam"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
--- /dev/null
+test_tree ccache . gcc
+test_tree distcc . gcc
+
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+test_tree rsync . cc
+test_tree samba4 source cc
+
--- /dev/null
+test_tree ccache . gcc
+test_tree distcc . gcc
+
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+test_tree rsync . cc
+test_tree samba4 source cc
+
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-utmp --with-pam"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
+config="" test_tree rsync . gcc
--- /dev/null
+test_tree samba4 source gcc
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree rsync . gcc
+test_tree distcc . gcc
+test_tree ccache . gcc
--- /dev/null
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba4 source gcc
+test_tree rsync . gcc
--- /dev/null
+export PATH="/usr/freeware/bin:$PATH"
+
+test_tree samba4 source cc
+export config="--with-utmp --with-acl-support"
+test_tree samba_2_2 source cc
+test_tree samba_3_0 source cc
+config="" test_tree rsync . cc
+
+export CFLAGS="-O -Wall"
+
+config="" test_tree ccache . gcc
+MAKE=gmake config="" test_tree distcc . gcc
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+test_tree samba4 source gcc
+MAKEFLAGS="-k" config="" test_tree rsync . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree samba4 source gcc
+export config="--with-utmp --with-pam"
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
+config="" test_tree rsync . gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount --with-acl-support --enable-krb5developer"
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+
--- /dev/null
+test_tree samba_2_2 source gcc
+test_tree samba4 source gcc
+config="--with-pam" test_tree samba_3_0 source gcc
+test_tree rsync . gcc
+MAKE=gmake test_tree distcc . gcc
+test_tree ccache . gcc
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<HEAD><TITLE>samba.org build farm</TITLE></HEAD>
+<BODY bgcolor="white" TEXT="#000000" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
+<IMG ALT="Samba Banner" BORDER=0 ALIGN=MIDDLE SRC="http://www.samba.org/samba/images/samba_banner.gif">
+<br><p>
+
+<h2>About the build farm</h2>
+
+The samba.org build farm is designed to test the configuration and
+build of some projects hosted on samba.org in real time. Each host in
+the build farm builds each of the projects regularly (currently every
+15 minutes for some hosts) and uploads the results of the configure and
+build to the central site (build.samba.org) for display.
+
+<p>This allows team members to check on the build status on a wide
+variety of operating systems and architectures without the drudgery of
+logging into each machine after each CVS commit.
+
+<p>The build farm pulls the source code from the <a
+href="http://www.samba.org/ftp/unpacked/">unpacked CVS repository</a>
+and does a clean configure and build whenever a change is detected in
+the tree. The results shown give information on the status of the
+configure and build process, plus any error logs.
+
+<p>In future we plan on expanding the build farm to do basic runtime testing as well.
+
+<p>The author of the build farm is <a
+href="mailto:tridge@samba.org">Andrew Tridgell</a>. The source for the
+build farm is available in the build_farm cvs tree on the
+<a href="http://pserver.samba.org/">samba.org CVS server</a>.
+
+<p>The build farm is now maintained by <a href="mailto:vance@samba.org">Vance
+Lankhaar</a>. He replaces long-time maintainer <a href="mailto:abartlet@samba.org">Andrew
+Bartlett</a>, allowing Andrew to focus more time on Samba development. </p>
+
+<p>If you have a machine that you wish to participate in our build farm
+then please read these <a href="instructions.html">instructions</a>.
+
+</BODY>
+</HTML>
--- /dev/null
+#!/usr/bin/perl -w
+# This CGI script presents the results of the build_farm build
+#
+# Copyright (C) Andrew Tridgell <tridge@samba.org> 2001
+# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001
+# Copyright (C) Vance Lankhaar <vance@samba.org> 2002-2004
+# Copyright (C) Martin Pool <mbp@samba.org> 2001
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# TODO: Allow filtering of the "Recent builds" list to show
+# e.g. only broken builds or only builds that you care about.
+
+
+my $BASEDIR = "/home/build/master";
+my $CACHEDIR = "/home/build/master/cache";
+
+use strict qw{vars};
+use lib "$BASEDIR/web";
+use util;
+use history;
+use POSIX;
+use Data::Dumper;
+use CGI::Form;
+use File::stat;
+
+my $req = new CGI::Form;
+
+my $HEADCOLOR = "#a0a0e0";
+my $OLDAGE = 60*60*4;
+my $DEADAGE = 60*60*24*4;
+
+##############################################
+# this defines what it is possible to build
+# and what boxes. Should be in a config file
+my $compilers = ['cc', 'gcc', 'gcc3', 'gcc-3.4', 'insure'];
+
+my (%hosts) = ('sun1' => "Solaris 8 UltraSparc",
+ 'Isis' => "Solaris 8 i386",
+ 'gc20' => "Solaris 2.6 Sparc",
+# 'sco1' => "SysV 3.2 i386",
+# 'sco2' => "UnixWare 7.1.0 i386",
+
+ 'aix1' => "AIX 4.3 PPC",
+ 'mungera' => "AIX 5.2 IBM POWER4+",
+
+ 'us4' => "IRIX 6.5 MIPS",
+ 'au2' => "IRIX 6.4 MIPS",
+
+ 'smbo2000' => "IRIX 6.5 MIPS",
+
+ 'wayne' => "RedHat 6.1 Sparc 10 (Kernel 2.2.18)",
+ 'yowiee' => "RedHat 9.0 i386",
+# 'insure' => "RedHat 6.2 vmware (insure)",
+ 'svamp' => "RedHat 7.0 i386",
+
+ 'rhonwyn' => "Debian Linux unstable i686",
+ 'boiccu' => "Debian Linux testing/unstable IA64",
+ 'yurok' => "Debian Linux 3.0 stable i386",
+ 'samba-s390' => "Debian Linux 3.0 stable s390",
+
+ 'fusberta' => "Debian Linux 3.0 Alpha",
+
+ 'sparc-woody' => "Debian Linux 3.0 (woody) Sparc64",
+ 'sparc-sarge' => "Debian Linux sarge/testing Sparc64",
+ 'sparc-sid' => "Debian Linux sid/unstable Sparc64",
+
+ 'flame' => "OpenBSD 3.0 Sparc",
+ 'pandemonium' => "OpenBSD-current Sparc64",
+
+ 'kimchi' => "NetBSD 1.5 i386",
+
+ 'gc8' => "FreeBSD 3.3-RELEASE i386",
+ 'gc4' => "FreeBSD 4.3-STABLE i386",
+ 'gwalcmai' => "FreeBSD 5.2-RELEASE i586",
+
+ 'manhattan' => "FreeBSD 4.8-RELEASE i386",
+
+ 'sbf' => "FreeBSD 5.2.1 i386",
+ 'smartserv1' => 'FreeBSD 5.2-CURRENT i386',
+
+ 'woko' => "Cray SV1 UNICOS 10.0.0.8",
+
+ 'hpntc9I' => "HP-UX 11.11",
+ 'gwen' => "HP-UX 11.11",
+
+ 'g6usr30' => "RedHat 7.2 IBM s390 (Kernel 2.4.9)",
+
+ 'belle' => "RedHat 8.0 i686",
+ 'manjra' => "RedHat 8.0 i686",
+
+ 'suse71ppc' => "SuSE 7.1 ppc gcc2.95.2",
+ 'metze01' => "SuSE 8.2 i386 (athlon)",
+ 'metze02' => "SuSE 7.3 i386 (PIII)",
+
+ 'l390vme1' => "SuSE SLES 8 (S/390)",
+
+ 'PCS1' => "SuSE Linux 9.1 Professional (i586)",
+
+ 'cyberone' => "Cygwin i686 (MS WinXP Pro)",
+
+ 'trip' => "Mandrake 9.2 i386 GCC 3.3.1",
+
+ 'm30' => "Stratus VOS HP PA-RISC",
+
+# 'sprinkhaan' => "FreeBSD 4.7-STABLE i386",
+# 'vlo' => "FreeBSD 5.0-RELEASE i386 #0",
+
+ 'jarret' => "Solaris 8 UltraSparc",
+ 'previn' => "Solaris 8 UltraSparc",
+ 'mundroo' => "Solaris 8 i386",
+ 'cat' => "Solaris 9 i386",
+
+# 'paros' => "Solaris 9 UltraSparc",
+
+ 'superego' => "Debian PPC/64 (Power3)",
+ 'quango' => "Debian PPC/32 (Power3)",
+
+#Compaq Test Drive systems (discontinued, for now)
+# 'spe140' => "Debian Linux 2.2R6 i386",
+# 'spe141' => "RedHat Linux 7.3 i386",
+# 'spe148' => "RedHat Linux 7.1 Alpha (ev6)",
+# 'spe149' => "FreeBSD 4.6-RELEASE Alpha",
+# 'spe150' => "SUSE Linux 8.0 i386",
+# 'spe151' => "FreeBSD 4.6-RELEASE i386",
+# 'spe158' => "SuSE Linux 7.1 Alpha",
+# 'spe160' => "Slackware Linux 8.0 i386",
+# 'spe161' => "Debian Linux 2.2R6 Alpha",
+# 'spe188' => "Mandrake ProSuite 8.2 i386",
+# 'spe190' => "RedHat Linux 7.2 ia64",
+# 'spe223' => "Red Hat Linux Advanced Server 2.1AS i386",
+
+ 'packetstorm' => "Slackware Linux 9.0 i386",
+
+ 'tardis' => "Gentoo i686"
+ );
+
+
+my @hosts = sort { $hosts{$a} cmp $hosts{$b} } keys %hosts;
+
+my (%trees) = (
+#'samba' => "",
+ 'samba' => "",
+ 'samba4' => "",
+ 'samba-docs' => "",
+ 'samba_3_0' => "SAMBA_3_0",
+ 'samba_2_2' => "SAMBA_2_2",
+ 'rsync' => "",
+ 'distcc' => "",
+ 'ccache' => "");
+
+# this is automatically filled in
+my (@deadhosts) = ();
+
+###############################################
+# work out a URL so I can refer to myself in links
+my $myself = $req->self_url;
+if ($myself =~ /(.*)[?].*/) {
+ $myself = $1;
+}
+if ($myself =~ /http:\/\/.*\/(.*)/) {
+ $myself = $1;
+}
+
+$myself = "http://build.samba.org/";
+
+################################################
+# start CGI headers
+sub cgi_headers() {
+ print "Content-type: text/html\r\n";
+
+ util::cgi_gzip();
+
+ print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<link rel="shortcut icon" href="/favicon.ico">
+<style type="text/css">
+.entry {
+ background-color: #f0f0ff;
+ width: 80%;
+ text-align: left;
+ margin: 15px 0px 15px 0px;
+ border: 1px solid gray;
+}
+.entry TABLE {
+ width: 100%;
+}
+.entry TABLE TD {
+ vertical-align: top;
+ text-align: left;
+}
+.entry TABLE TH {
+ vertical-align: top;
+ width: 5em;
+ text-align: left;
+}
+
+TABLE.header {
+ border: 1px solid black;
+}
+TABLE.header TH {
+ font-weight: normal;
+ width: 12em;
+ text-align: left;
+}
+TABLE.header TD {
+}
+#log .name,.status {
+ display: inline;
+ font-weight: bold;
+ font-family: sans-serif;
+}
+#log .status.failed {
+ color: rgb(153, 0, 0);;
+}
+#log .status.passed {
+ color: rgb(0, 153, 0);
+}
+#log .output {
+ color: rgb(0, 0, 0);
+ font-family: monospace;
+}
+#log div.unit {
+ margin: 5px;
+ padding: 10px;
+ border: 2px solid black;
+}
+#log div.unit.passed {
+ background-color: rgb(180, 255, 180);
+}
+#log div.unit.failed {
+ background-color: rgb(255, 180, 180);
+}
+#log .unit.failed .output {
+ display: block;
+}
+#log .unit.passed .output {
+ display: none;
+}
+#log div.output#output-stderr-0 {
+ display: none;
+}
+
+#log img {
+ border: none;
+}
+#log a {
+ text-decoration: none;
+}
+#log a:hover,a:active {
+ text-decoration: underline;
+}
+</style>
+<script type="text/javascript">
+<!-- begin hiding from browsers
+
+
+function handle(name)
+{
+ action = document.getElementById("output-" + name);
+ img = document.getElementById("img-" + name);
+ old_src = img.getAttribute("src");
+
+ current_display = action.style.display;
+
+ // try to handle the case where the display is not explicitly set
+ if (current_display == "") {
+ if (action.currentStyle) { // ack, IE
+ current_display = action.currentStyle.display;
+ }
+ else if (document.defaultView.getComputedStyle) { // oooh, DOM
+ var style_list = document.defaultView.getComputedStyle(action, "");
+
+ // konqueor has getComputedStyle, but it does not work
+ if (style_list != null) {
+ current_display = style_list.getPropertyValue("display");
+ }
+ }
+ // in the case than neither works, we will do nothing. it just
+ // means the user will have to click twice to do the initial closing
+ }
+
+ if (current_display == "block") {
+ action.style.display = "none";
+ img.setAttribute("src", old_src.replace("hide", "unhide"));
+ }
+ else {
+ action.style.display = "block";
+ img.setAttribute("src", old_src.replace("unhide", "hide"));
+ }
+}
+// -- end hiding from browsers -->
+</script>
+<title>samba.org build farm</title></head>
+<body bgcolor="white" text="#000000" link="#0000EE" vlink="#551A8B" alink="#FF0000">
+<table border=0>
+<tr>
+<td><img alt="Samba Banner" border=0 align="left" src="http://www.samba.org/samba/images/samba_banner.gif"></td>
+<td>
+<ul>
+<li><a href="about.html">About the build farm</a>
+<li><a href="instructions.html">Adding a new machine</a>
+<li><a href="http://pserver.samba.org/">Samba CVS repository</a>
+<li><a href="http://www.samba.org/">Samba Web pages</a>
+</ul>
+</td>
+</tr>
+</table>
+';
+
+}
+
+################################################
+# start CGI headers for diffs
+sub cgi_headers_diff() {
+ print "Content-type: application/x-diff\r\n";
+ print "\n";
+}
+
+################################################
+# end CGI
+sub cgi_footers() {
+ print "</body>";
+ print "</html>\n";
+}
+
+################################################
+# print an error on fatal errors
+sub fatal($) {
+ my $msg=shift;
+ print "ERROR: $msg<br>\n";
+ cgi_footers();
+ exit(0);
+}
+
+##############################################
+# get the age of build from ctime
+sub build_age($$$)
+{
+ my $host=shift;
+ my $tree=shift;
+ my $compiler=shift;
+ my $file="build.$tree.$host.$compiler";
+ my $age = -1;
+ my $st;
+
+ if ($st = stat("$file.log")) {
+ $age = time() - $st->ctime;
+ }
+
+ return $age;
+}
+
+##############################################
+# get the svn revision of build
+sub build_revision($$$)
+{
+ my $host=shift;
+ my $tree=shift;
+ my $compiler=shift;
+ my $file="build.$tree.$host.$compiler";
+ my $log;
+ my $rev = "unknown";
+
+ my $st1 = stat("$file.log");
+ my $st2 = stat("$CACHEDIR/$file.revision");
+
+ if ($st1 && $st2 && $st1->ctime <= $st2->ctime) {
+ return util::FileLoad("$CACHEDIR/$file.revision");
+ }
+
+ $log = util::FileLoad("$file.log");
+
+ if (! $log) { return 0; }
+
+ if ($log =~ /BUILD REVISION:(.*)/) {
+ $rev = $1;
+ }
+
+ util::FileSave("$CACHEDIR/$file.revision", "$rev");
+
+ return $rev;
+}
+
+#############################################
+# get the overall age of a host
+sub host_age($)
+{
+ my $host = shift;
+ my $ret = -1;
+ for my $compiler (@{$compilers}) {
+ for my $tree (sort keys %trees) {
+ my $age = build_age($host, $tree, $compiler);
+ if ($age != -1 && ($age < $ret || $ret == -1)) {
+ $ret = $age;
+ }
+ }
+ }
+ return $ret;
+}
+
+#############################################
+# show an age as a string
+sub red_age($)
+{
+ my $age = shift;
+
+ if ($age > $OLDAGE) {
+ return sprintf("<font color=\"#b00000\">%s</font>", util::dhm_time($age));
+ }
+ return util::dhm_time($age);
+}
+
+
+##############################################
+# get status of build
+sub build_status($$$)
+{
+ my $host=shift;
+ my $tree=shift;
+ my $compiler=shift;
+ my $file="build.$tree.$host.$compiler";
+ my $cachefile="$CACHEDIR/build.$tree.$host.$compiler";
+ my $cstatus = "?";
+ my $bstatus = "?";
+ my $istatus = "?";
+ my $tstatus = "?";
+ my $sstatus = "/?";
+
+ my $log;
+ my $ret;
+
+ my $st1 = stat("$file.log");
+ my $st2 = stat("$cachefile.status");
+
+ if ($st1 && $st2 && $st1->ctime <= $st2->ctime) {
+ return util::FileLoad("$cachefile.status");
+ }
+
+ $log = util::FileLoad("$file.log");
+
+ unlink("$CACHEDIR/FAILED.test.$tree.$host.$compiler");
+ if ($log =~ /TEST STATUS:(.*)/) {
+ if ($1 == 0) {
+ $tstatus = "<font color=green>ok</font>";
+ } else {
+ $tstatus = "<font color=red>$1</font>";
+ system("touch $CACHEDIR/FAILED.test.$tree.$host.$compiler");
+ }
+ }
+
+ unlink("$CACHEDIR/FAILED.install.$tree.$host.$compiler");
+ if ($log =~ /INSTALL STATUS:(.*)/) {
+ if ($1 == 0) {
+ $istatus = "<font color=green>ok</font>";
+ } else {
+ $istatus = "<font color=red>$1</font>";
+ system("touch $CACHEDIR/FAILED.install.$tree.$host.$compiler");
+ }
+ }
+
+ unlink("$CACHEDIR/FAILED.build.$tree.$host.$compiler");
+ if ($log =~ /BUILD STATUS:(.*)/) {
+ if ($1 == 0) {
+ $bstatus = "<font color=green>ok</font>";
+ } else {
+ $bstatus = "<font color=red>$1</font>";
+ system("touch $CACHEDIR/FAILED.build.$tree.$host.$compiler");
+ }
+ }
+
+ unlink("$CACHEDIR/FAILED.configure.$tree.$host.$compiler");
+ if ($log =~ /CONFIGURE STATUS:(.*)/) {
+ if ($1 == 0) {
+ $cstatus = "<font color=green>ok</font>";
+ } else {
+ $cstatus = "<font color=red>$1</font>";
+ system("touch $CACHEDIR/FAILED.configure.$tree.$host.$compiler");
+ }
+ }
+
+ unlink("$CACHEDIR/FAILED.internalerror.$tree.$host.$compiler");
+ if ($log =~ /INTERNAL ERROR:(.*)/ || $log =~ /PANIC:(.*)/) {
+ $sstatus = "/<font color=red><b>PANIC</b></font>";
+ system("touch $CACHEDIR/FAILED.internalerror.$tree.$host.$compiler");
+ } else {
+ $sstatus = "";
+ }
+
+ $ret = "<a href=\"$myself?function=View+Build&host=$host&tree=$tree&compiler=$compiler\">$cstatus/$bstatus/$istatus/$tstatus$sstatus</a>";
+
+
+ util::FileSave("$CACHEDIR/$file.status", $ret);
+
+ return $ret;
+}
+
+
+##############################################
+# get status of build
+sub err_count($$$)
+{
+ my $host=shift;
+ my $tree=shift;
+ my $compiler=shift;
+ my $file="build.$tree.$host.$compiler";
+ my $err;
+
+ my $st1 = stat("$file.err");
+ my $st2 = stat("$CACHEDIR/$file.errcount");
+
+ if ($st1 && $st2 && $st1->ctime <= $st2->ctime) {
+ return util::FileLoad("$CACHEDIR/$file.errcount");
+ }
+
+ $err = util::FileLoad("$file.err");
+
+ if (! $err) { return 0; }
+
+ my $ret = util::count_lines($err);
+
+ util::FileSave("$CACHEDIR/$file.errcount", "$ret");
+
+ return $ret;
+}
+
+
+
+##############################################
+# view build summary
+sub view_summary() {
+ my $i = 0;
+ my $list = `ls`;
+
+ my $cols = 2;
+
+ my $broken = 0;
+
+ # set up counters
+ my %broken_count;
+ my %panic_count;
+ my %host_count;
+
+ # zero broken and panic counters
+ for my $tree (sort keys %trees) {
+ $broken_count{$tree} = 0;
+ $panic_count{$tree} = 0;
+ $host_count{$tree} = 0;
+ }
+
+ #set up a variable to store the broken builds table's code, so we can output when we want
+ my $broken_table;
+
+ my $host_os;
+ my $last_host = "";
+
+ for my $host (@hosts) {
+ for my $compiler (@{$compilers}) {
+ for my $tree (sort keys %trees) {
+ my $status = build_status($host, $tree, $compiler);
+ my $age = build_age($host, $tree, $compiler);
+ if ($age != -1 && $age < $DEADAGE) {
+ $host_count{$tree}++;
+ }
+ if ($age < $DEADAGE && $status =~ /color=red/) {
+ if (!$broken) {
+ $broken_table .= sprintf "<b>Currently broken builds:</b><p>\n";
+ $broken_table .= sprintf "<table border=2><tr
+ bgcolor=\"$HEADCOLOR\"><th colspan=3>Target</th><th>Build Age</th><th>Status<br>config/build/install/test</th><th>warnings</th></tr>\n";
+ $broken = 1;
+ }
+ $broken_count{$tree}++;
+ if ($status =~ /PANIC/) {
+ $panic_count{$tree}++;
+ }
+ my $warnings = err_count($host, $tree, $compiler);
+
+ $broken_table .= sprintf "<tr>";
+
+ $host_os = $hosts{$host};
+ if ($host eq $last_host) {
+ $broken_table .= sprintf "<td colspan=2></td>";
+ } else {
+ $broken_table .= sprintf "<td>$host_os</td><td><a href=\"#$host\">$host</a></td>";
+ }
+ $broken_table .= sprintf "<td><b>$tree</b>/$compiler</td><td align=right>" . red_age($age) . "</td><td align=center>$status</td><td align=center>$warnings</td></tr>\n";
+
+ $last_host = $host;
+
+ }
+ }
+ }
+ }
+
+ if ($broken) {
+ $broken_table .= sprintf("</table><p>\n");
+ }
+
+ print "<b>Build counts:</b><p>";
+ print "<table border=2 width=250><tr bgcolor=\"$HEADCOLOR\"><th>Tree</th><th>Total</th><th>Broken</th><th>Panic</th></tr>\n";
+ for my $tree (sort keys %trees) {
+ print "<tr><td>$tree</td><td align=center>$host_count{$tree}</td><td align=center>$broken_count{$tree}</td><td align=center>";
+ if ($panic_count{$tree}) {
+ print "<font color=red><b>$panic_count{$tree}</b></font>";
+ } else {
+ print "0";
+ }
+ print "</td></tr>\n";
+ }
+ print "</table><p>\n";
+
+
+ print $broken_table;
+
+ print "<b>Build summary:</b>\n\n";
+
+ print '<table border=0><tr>';
+ for my $host (@hosts) {
+ # make sure we have some data from it
+ if (! ($list =~ /$host/)) { print "\n<!-- skipping $host --!>\n"; next; }
+
+ if ($i == $cols) {
+ $i = 0;
+ print "</tr><tr>";
+ }
+
+ my $row = 0;
+
+ for my $compiler (@{$compilers}) {
+ for my $tree (sort keys %trees) {
+ my $age = build_age($host, $tree, $compiler);
+ my $warnings = err_count($host, $tree, $compiler);
+ if ($age != -1 && $age < $DEADAGE) {
+ my $status = build_status($host, $tree, $compiler);
+ if ($row == 0) {
+ print "<td valign=top><br><b><a name=\"$host\">$host</a> - $hosts{$host}</b><br><table border=2>
+<tr bgcolor=\"$HEADCOLOR\"><th>Target</th><th>Build Age</th><th>Status<br>config/build<br>install/test</th><th>warnings</th></tr>
+";
+ }
+ print "<tr align=center><td align=left><b>$tree</b>/$compiler</td><td align=right>" . red_age($age) . "</td><td>$status</td><td>$warnings</td></tr>\n";
+ $row++;
+ }
+ }
+ }
+ if ($row != 0) {
+ print "</table></td>\n";
+ $i++;
+ } else {
+ push(@deadhosts, $host);
+ }
+ }
+ print '</tr></table>';
+
+ draw_dead_hosts(@deadhosts);
+}
+
+##############################################
+# Draw the "recent builds" view
+
+sub view_recent_builds() {
+ my $i = 0;
+ my $list = `ls`;
+
+ my $cols = 2;
+
+ my $broken = 0;
+
+ my $host_os;
+ my $last_host = "";
+ my @all_builds = ();
+ my $tree=$req->param("tree");
+
+ # Convert from the DataDumper tree form to an array that
+ # can be sorted by time.
+
+ for my $host (@hosts) {
+ for my $compiler (@{$compilers}) {
+ my $status = build_status($host, $tree, $compiler);
+ my $age = build_age($host, $tree, $compiler);
+ my $revision = build_revision($host, $tree, $compiler);
+ push @all_builds, [$age, $hosts{$host}, "<a href=\"$myself?function=Summary&host=$host&tree=$tree&compiler=$compiler#$host\">$host</a>", $compiler, $tree, $status, $revision]
+ unless $age == -1 or $age >= $DEADAGE;
+ }
+ }
+
+ @all_builds = sort {$$a[0] <=> $$b[0]} @all_builds;
+
+
+ print "<h2>Recent builds of $tree</h2>";
+ print '<table border=2>';
+ print "<tr bgcolor=\"$HEADCOLOR\">";
+ print "<th>Age</th>";
+ print "<th>Revision</th>";
+ print "<th colspan=4>Target</th>";
+ print "<th>Status</th>";
+ print "</tr>\n";
+
+ for my $build (@all_builds) {
+ my $age = $$build[0];
+ my $rev = $$build[6];
+ printf "<tr>";
+ print "<td>" .
+ util::dhm_time($age)."<td>"; # goes straight to stdout
+ print $rev."<td>";
+ print join "<td>", @$build[4, 1, 2, 3, 5];
+ print "</tr>\n";
+ }
+ print "</table>\n";
+}
+
+
+##############################################
+# Draw the "dead hosts" table
+sub draw_dead_hosts() {
+ my @deadhosts = @_;
+ print "<br><b>Dead Hosts:</b><br>\n";
+ print '<table border=2><tr>';
+ print "<tr bgcolor=\"$HEADCOLOR\"><th>Host</th><th>OS</th><th>Min Age</th></tr>
+";
+ for my $host (@deadhosts) {
+ my $age = host_age($host);
+ printf("<tr><td>$host</td><td>$hosts{$host}</td><td align=right>%s</td>\n", util::dhm_time($age));
+ }
+ print "</table>\n";
+}
+
+
+##############################################
+# view one build in detail
+sub view_build() {
+ my $host=$req->param("host");
+ my $tree=$req->param("tree");
+ my $compiler=$req->param("compiler");
+ my $file="build.$tree.$host.$compiler";
+ my $log;
+ my $err;
+ my $uname="";
+ my $cflags="";
+ my $config="";
+ my $age = build_age($host, $tree, $compiler);
+ my $rev = build_revision($host, $tree, $compiler);
+ my $status = build_status($host, $tree, $compiler);
+
+ util::InArray($host, [keys %hosts]) || fatal("unknown host");
+ util::InArray($compiler, $compilers) || fatal("unknown compiler");
+ util::InArray($tree, [sort keys %trees]) || fatal("unknown tree");
+
+ $log = util::FileLoad("$file.log");
+ $err = util::FileLoad("$file.err");
+
+ if ($log) {
+ $log = util::cgi_escape($log);
+
+ if ($log =~ /(.*)/) { $uname=$1; }
+ if ($log =~ /CFLAGS=(.*)/) { $cflags=$1; }
+ if ($log =~ /configure options: (.*)/) { $config=$1; }
+ }
+
+ if ($err) {
+ $err = util::cgi_escape($err);
+ }
+
+ print util::FileLoad("../web/$host.html");
+
+ print "
+<table>
+<tr><td>Host:</td><td><a href=\"$myself?function=Summary&host=$host&tree=$tree&compiler=$compiler#$host\">$host</a> - $hosts{$host}</td></tr>
+<tr><td>Uname:</td><td>$uname</td></tr>
+<tr><td>Tree:</td><td>$tree</td></tr>
+<tr><td>Build Revision:</td><td>" . $rev . "</td></tr>
+<tr><td>Build age:</td><td>" . red_age($age) . "</td></tr>
+<tr><td>Status:</td><td>$status</td></tr>
+<tr><td>Compiler:</td><td>$compiler</td></tr>
+<tr><td>CFLAGS:</td><td>$cflags</td></tr>
+<tr><td>configure options: </td><td>$config</td></tr>
+</table>
+";
+
+ # check the head of the output for our magic string
+ my $prettyPrintableLogs = ((substr $log, 0, 500) =~ /\*build_farm transition magic\*/);
+
+ if ($prettyPrintableLogs) {
+
+ print "<div id=\"log\">\n";
+ print "<div id=\"actionList\">\n";
+ # These can be pretty wide -- perhaps we need to
+ # allow them to wrap in some way?
+ if ($err eq "") {
+ print "<b>No error log available</b><br>\n";
+ } else {
+ print "<h2>Error log:</h2>\n";
+ print make_action_html("stderr", $err, "stderr-0");;
+ }
+
+ if ($log eq "") {
+ print "<b>No build log available</b><br>\n";
+ } else {
+ print "<h2>Build log:</h2>\n";
+ print_log_pretty($log);
+ }
+
+ print "<p><small>Some of the above icons derived from the <a href=\"http://www.gnome.org\">Gnome Project</a>'s stock icons.</p>";
+ print "</div>\n";
+ print "</div>\n";
+ }
+ else {
+ if ($err eq "") {
+ print "<b>No error log available</b><br>\n";
+ } else {
+ print "<h2>Error log:</h2>\n";
+ print "<tt><pre>" . join('', $err) . "</pre></tt>\n";
+ }
+ if ($log eq "") {
+ print "<b>No build log available</b><br>\n";
+ }
+ else {
+ print "<h2>Build log:</h2>\n";
+ print "<tt><pre>" . join('', $log) . "</pre></tt><p>\n";
+ }
+ }
+ print "</body>\n";
+}
+
+##############################################
+# prints the log in a visually appealing manner
+sub print_log_pretty() {
+ my $log = shift;
+
+
+ # do some pretty printing for the actions
+ my $id = 1;
+ $log =~ s{ Running\ action\s+([\w\-]+)
+ (.*?)
+ ACTION\ (PASSED|FAILED):\ ([\w\-]+)
+ }{make_action_html($1, $2, $id++, $3)}exgs;
+
+ $log =~ s{
+ --==--==--==--==--==--==--==--==--==--==--.*?
+ Running\ test\ ([\w-]+)\ \(level\ (\d+)\ (\w+)\).*?
+ --==--==--==--==--==--==--==--==--==--==--
+ (.*?)
+ ==========================================.*?
+ TEST\ (FAILED|PASSED):(\ \(status\ (\d+)\))?.*?
+ ==========================================\s+
+ }{make_test_html($1, $4, $id++, $5)}exgs;
+
+
+ print join('', $log) . "\n";
+}
+
+##############################################
+# generate html for a test section
+sub make_test_html {
+ my $name = shift;
+ my $output = shift;
+ my $id = shift;
+ my $status = shift;
+
+ my $return = "</pre>" . # don't want the pre openned by action affecting us
+ "<div class=\"test unit \L$status\E\" id=\"test-$id\">" .
+ "<a href=\"javascript:handle('$id');\">" .
+ "<img id=\"img-$id\" src=\"";
+ if (defined $status && $status eq "PASSED") {
+ $return .= "icon_unhide_16.png";
+ }
+ else {
+ $return .= "icon_hide_16.png";
+ }
+ $return .= "\"> " .
+ "<div class=\"test name\">$name</div> " .
+ "</a> " .
+ "<div class=\"test status \L$status\E\">$status</div>" .
+ "<div class=\"test output\" id=\"output-$id\">" .
+ "<pre>$output</pre>" .
+ "</div>" .
+ "</div>" .
+ "<pre>"; # open the pre back up
+
+ return $return;
+}
+
+##############################################
+# generate html for an action section
+sub make_action_html {
+
+ my $name = shift;
+ my $output = shift;
+ my $id = shift;
+ my $status = shift;
+ my $return = "<div class=\"action unit \L$status\E\" id=\"action-$id\">" .
+ "<a href=\"javascript:handle('$id');\">" .
+ "<img id=\"img-$id\" src=\"";
+
+ if (defined $status && ($status =~ /failed/i)) {
+ $return .= 'icon_hide_24.png';
+ }
+ else {
+ $return .= 'icon_unhide_24.png';
+ }
+
+ $return .= "\"> " .
+ "<div class=\"action name\">$name</div>" .
+ "</a> ";
+
+ if (defined $status) {
+ $return .= "<div class=\"action status \L$status\E\">$status</div>";
+ }
+
+ $return .= "<div class=\"action output\" id=\"output-$id\">" .
+ "<pre>Running action $name$output ACTION $status: $name</pre>" .
+ "</div>".
+ "</div>";
+
+ return $return
+}
+
+##############################################
+# main page
+sub main_menu() {
+ print $req->startform("GET");
+ print $req->popup_menu(-name=>'host',
+ -values=>\@hosts,
+ -labels=>\%hosts);
+ print $req->popup_menu("tree", [sort keys %trees]);
+ print $req->popup_menu("compiler", $compilers);
+
+ print $req->submit('function', 'View Build');
+ print " " . $req->submit('function', 'Recent Checkins');
+ print " " . $req->submit('function', 'Summary');
+ print " " . $req->submit('function', 'Recent Builds');
+
+ print $req->endform();
+}
+
+###############################################
+# display top of page
+sub page_top() {
+ cgi_headers();
+ chdir("$BASEDIR/data") || fatal("can't change to data directory");
+ main_menu();
+}
+###############################################
+# main program
+
+if (defined $req->param("function")) {
+ my $fn_name = $req->param("function");
+ if ($fn_name eq "View Build") {
+ page_top();
+ view_build();
+ cgi_footers();
+ } elsif ($fn_name eq "Recent Builds") {
+ page_top();
+ view_recent_builds();
+ cgi_footers();
+ } elsif ($fn_name eq "Recent Checkins") {
+ page_top();
+ history::cvs_history($req->param('tree'));
+ cgi_footers();
+ } elsif ($fn_name eq "diff") {
+ page_top();
+ history::cvs_diff($req->param('author'), $req->param('date'), $req->param('tree'), "html");
+ cgi_footers();
+ } elsif ($fn_name eq "text_diff") {
+ cgi_headers_diff();
+ chdir("$BASEDIR/data") || fatal("can't change to data directory");
+ history::cvs_diff($req->param('author'), $req->param('date'), $req->param('tree'), "text");
+ } else {
+ page_top();
+ view_summary();
+ cgi_footers();
+ }
+} else {
+ page_top();
+ view_summary();
+ cgi_footers();
+}
+
--- /dev/null
+# Copyright (C) Andrew Tridgell <tridge@samba.org> 2001
+# Copyright (C) Martin Pool <mbp@samba.org> 2003
+# script to show recent checkins in cvs
+
+package history;
+
+my $BASEDIR = "/home/build/master";
+my $HISTORYDIR = "/home/build/master/cache";
+my $TIMEZONE = "PST";
+my $TIMEOFFSET = 0;
+
+use strict qw{vars};
+use util;
+use POSIX;
+use Data::Dumper;
+use CGI::Form;
+use File::stat;
+
+my $req = new CGI::Form;
+
+my $HEADCOLOR = "#a0a0e0";
+my $CVSWEB_BASE = "http://pserver.samba.org/cgi-bin/cvsweb";
+
+my (%tree_base) = ('samba' => "samba",
+ 'samba_2_2' => "samba",
+ 'samba_3_0' => "samba",
+ 'samba-docs' => "samba-docs",
+ 'samba4' => "samba4",
+ 'rsync' => "rsync",
+ 'distcc' => 'distcc',
+ 'ccache' => 'ccache');
+
+my $unpacked_dir = "/home/ftp/pub/unpacked";
+
+###############################################
+# work out a URL so I can refer to myself in links
+my $myself = $req->self_url;
+if ($myself =~ /(.*)[?].*/) {
+ $myself = $1;
+}
+if ($myself =~ /http:\/\/.*\/(.*)/) {
+ $myself = $1;
+}
+
+$myself = "http://build.samba.org/";
+
+################################################
+# start CGI headers
+sub cgi_headers() {
+ print "Content-type: text/html\r\n";
+
+ util::cgi_gzip();
+
+ print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head><title>recent checkins</title></head>
+<body bgcolor="white" text="#000000" link="#0000EE" vlink="#551A8B" alink="#FF0000">
+';
+
+}
+
+################################################
+# end CGI
+sub cgi_footers() {
+ print "</body>";
+ print "</html>\n";
+}
+
+################################################
+# print an error on fatal errors
+sub fatal($) {
+ my $msg=shift;
+ print "ERROR: $msg<br>\n";
+ cgi_footers();
+ exit(0);
+}
+
+
+###############################################
+# pretty up a cvs diff -u
+sub cvs_pretty($)
+{
+ my $diff = shift;
+ my $ret = "";
+ my @lines = split(/$/m, $diff);
+
+ my (%colors) = (
+ '^diff.*' => 'red',
+ '^=.*' => 'blue',
+ '^Index:.*' => 'blue',
+ '^\-.*' => '#a00000',
+ '^\+.*' => '#00a000'
+ );
+
+ for (my $i=0; $i <= $#lines; $i++) {
+ my $line = $lines[$i];
+
+ for my $r (keys %colors) {
+ if ($line =~ /$r/m) {
+ $line = "<font color=\"$colors{$r}\">$line</font>";
+ last;
+ }
+ }
+ $ret .= $line;
+ }
+ return $ret;
+}
+
+sub cvsweb_paths($$)
+{
+ my $tree = shift;
+ my $paths = shift;
+ my $ret = "";
+ while ($paths =~ /\s*([^\s]+)(.*)/) {
+ $ret .= "<a href=\"$CVSWEB_BASE/$tree_base{$tree}/$1\">$1</a> ";
+ $paths = $2;
+ }
+
+ return $ret;
+}
+
+#############################################
+# show one row of history table
+sub history_row($$)
+{
+ my $entry = shift;
+ my $tree = shift;
+ my $msg = util::cgi_escape($entry->{MESSAGE});
+ my $t = POSIX::asctime(POSIX::gmtime($entry->{DATE}));
+ my $age = util::dhm_time(time()-$entry->{DATE});
+
+ $t =~ s/\ / /g;
+
+ print "
+<p><table bgcolor=\"\#f0f0ff\" width=\"80%\" class=\"entry\">
+ <tr>
+ <td>
+ <b>$t</b><br>$age ago<br>
+ </td>
+ </tr>
+ <tr>
+ <td valign=top align=left>
+<b><a href=$myself?function=diff&tree=$tree&date=$entry->{DATE}&author=$entry->{AUTHOR}>show diffs</a></b><br>
+<a href=$myself?function=text_diff&tree=$tree&date=$entry->{DATE}&author=$entry->{AUTHOR}>download diffs</a><br>
+ <pre>$msg</pre>
+ </td>
+ </tr>
+
+ <tr><td><em>Author: </em>$entry->{AUTHOR}</td></tr>";
+
+ if ($entry->{FILES}) {
+ print "<tr><td><em>Modified: </em>";
+ print cvsweb_paths($tree, $entry->{FILES});
+ print "</td></tr>\n";
+ }
+
+ if ($entry->{ADDED}) {
+ print "<tr><td><em>Added:</em> ";
+ print cvsweb_paths($tree, $entry->{ADDED});
+ print "</td></tr>\n";
+ }
+
+ if ($entry->{REMOVED}) {
+ print "<tr><td><em>Removed: </em>";
+ print cvsweb_paths($tree, $entry->{REMOVED});
+ print "</td></tr>\n";
+ }
+
+ print "</table>\n";
+}
+
+
+#############################################
+# show one row of history table
+sub history_row_text($$)
+{
+ my $entry = shift;
+ my $tree = shift;
+ my $msg = util::cgi_escape($entry->{MESSAGE});
+ my $t = POSIX::asctime(POSIX::gmtime($entry->{DATE}));
+ my $age = util::dhm_time(time()-$entry->{DATE});
+
+ print "Author: $entry->{AUTHOR}\n";
+ print "Mofified: $entry->{FILES}\n";
+ print "Added: $entry->{ADDED}\n";
+ print "Removed: $entry->{REMOVED}\n";
+ print "\n\n$msg\n\n\n";
+}
+
+
+###############################################
+# show recent cvs entries
+sub cvs_diff($$$$)
+{
+ my $author = shift;
+ my $date = shift;
+ my $tree = shift;
+ my $text_html = shift;
+ my $cmd;
+ my $module;
+
+ util::InArray($tree, [keys %tree_base]) || fatal("unknown tree");
+
+ my $log = util::LoadStructure("$HISTORYDIR/history.$tree");
+
+ chdir("$unpacked_dir/$tree") || fatal("no tree $unpacked_dir/$tree available");
+
+ $module = $tree_base{$tree};
+
+ for (my $i=0; $i <= $#{$log}; $i++) {
+ my $entry = $log->[$i];
+ if ($author eq $entry->{AUTHOR} &&
+ $date == $entry->{DATE}) {
+ my $t1;
+ my $t2;
+
+ chomp($t1 = POSIX::ctime($date-60+($TIMEOFFSET*60*60)));
+ chomp($t2 = POSIX::ctime($date+60+($TIMEOFFSET*60*60)));
+
+ if ($text_html eq "html") {
+ print "<h2>CVS Diff in $tree for $t1</h2>\n";
+
+ print "<table border=0><tr>\n";
+ history_row($entry, $tree);
+ print "</tr></TABLE>\n";
+ } else {
+ history_row_text($entry, $tree);
+ }
+
+ if (! ($entry->{TAG} eq "") && !$entry->{REVISIONS}) {
+ print '
+<br>
+<b>sorry, cvs diff on branches not currently possible due to a limitation
+in cvs</b>
+<br>';
+ }
+
+ $ENV{'CVS_PASSFILE'} = "$BASEDIR/.cvspass";
+
+ if ($entry->{REVISIONS}) {
+ for my $f (keys %{$entry->{REVISIONS}}) {
+ my $cmd;
+ my $diff;
+ my $fix_diff = 0;
+ if ($entry->{REVISIONS}->{$f}->{REV1} eq "NONE") {
+ $cmd = "cvs rdiff -u -r 0 -r $entry->{REVISIONS}->{$f}->{REV2} $module/$f";
+ $fix_diff = 1;
+ } elsif ($entry->{REVISIONS}->{$f}->{REV2} eq "NONE") {
+ $cmd = "cvs rdiff -u -r $entry->{REVISIONS}->{$f}->{REV1} -r 0 $module/$f";
+ $fix_diff = 1;
+ } elsif ($text_html eq "html") {
+ $cmd = "cvs diff -b -u -r $entry->{REVISIONS}->{$f}->{REV1} -r $entry->{REVISIONS}->{$f}->{REV2} $f";
+ } else {
+ $cmd = "cvs diff -u -r $entry->{REVISIONS}->{$f}->{REV1} -r $entry->{REVISIONS}->{$f}->{REV2} $f";
+ }
+
+ $diff = `$cmd 2> /dev/null`;
+ if ($fix_diff) {
+ $diff =~ s/^--- $module\//--- /mg;
+ $diff =~ s/^\+\+\+ $module\//\+\+\+ /mg;
+ }
+
+ if ($text_html eq "html") {
+ print "<!-- $cmd --!>\n";
+ $diff = util::cgi_escape($diff);
+ $diff = cvs_pretty($diff);
+ print "<pre>$diff</pre>\n";
+ } else {
+ print "$diff\n";
+ }
+ }
+ } else {
+ if ($text_html eq "html") {
+ my $cmd = "cvs diff -b -u -D \"$t1 $TIMEZONE\" -D \"$t2 $TIMEZONE\" $entry->{FILES}";
+ } else {
+ my $cmd = "cvs diff -u -D \"$t1 $TIMEZONE\" -D \"$t2 $TIMEZONE\" $entry->{FILES}";
+ }
+
+ my $diff = `$cmd 2> /dev/null`;
+
+ if ($text_html eq "html") {
+ print "<!-- $cmd --!>\n";
+ $diff = util::cgi_escape($diff);
+ $diff = cvs_pretty($diff);
+ }
+
+ print "<pre>$diff</pre>\n";
+ }
+
+ return;
+ }
+ }
+}
+
+
+###############################################
+# show recent cvs entries
+sub cvs_history($)
+{
+ my $tree = shift;
+ my (%authors) = ('ALL' => 1);
+ my $author;
+
+ util::InArray($tree, [keys %tree_base]) || fatal("unknown tree");
+
+ my $log = util::LoadStructure("$HISTORYDIR/history.$tree");
+
+ for (my $i=$#{$log}; $i >= 0; $i--) {
+ $authors{$log->[$i]->{AUTHOR}} = 1;
+ }
+
+ print $req->startform("GET");
+ print "Select Author: ";
+ print $req->popup_menu("author", [sort keys %authors]);
+ print $req->submit('sub_function', 'Refresh');
+ print $req->hidden('tree', $tree);
+ print $req->hidden('function', 'Recent Checkins');
+ print $req->endform();
+
+ print "<h2>Recent checkins for $tree</h2>\n";
+
+ print "
+";
+
+ $author = $req->param("author");
+
+ for (my $i=$#{$log}; $i >= 0; $i--) {
+ my $entry = $log->[$i];
+ if (! $author ||
+ ($author eq "ALL") ||
+ ($author eq $entry->{AUTHOR})) {
+ history_row($entry, $tree);
+ }
+ }
+ print '
+';
+}
+
+
+#cvs_diff($req->param('author'), $req->param('date'), $req->param('tree'));
+#cvs_history("trinity");
+
+
+1;
--- /dev/null
+Many thanks to <a href="http://www.hp.com/">Hewlett-Packard</a> for
+providing and maintaining this machine in the Build Farm.
--- /dev/null
+Many thanks to <a href="http://www.hp.com/">Hewlett-Packard</a> for
+providing and maintaining this machine in the Build Farm.
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<HEAD><TITLE>samba.org build farm</TITLE></HEAD>
+<BODY bgcolor="white" TEXT="#000000" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
+<p><IMG ALT="Samba Banner" BORDER=0 ALIGN=MIDDLE SRC="http://www.samba.org/samba/images/samba_banner.gif">
+<p>
+
+<br>
+<p>
+<h2>Adding a machine to the build farm</h2>
+
+
+If you have a machine that you wish to add to our build farm then please follow the following instructions:
+
+<ul>
+
+<li>Decide if your machine is suitable for the task:
+<ul>
+<li>Is it a production machine?
+<li>Is it security-sensitive?
+<li>Look at the output from the existing machines - would publishing file-system locations and
+IPs be a concern?
+<li>The nature of the task is that executable code is downloaded from
+(a site claiming to be) samba.org, and run on your machine by cron.
+Does this bother you?
+<li>Is this somebody else's machine?
+</ul>
+If you answer yes to any of these these questions, then we probably
+should not include it on the build farm.
+
+<li>See if it is an OS/architecture combination that we already
+have. If it is then we won't need it unless the current machine we
+have covering that combination goes away for some reason.
+
+<li>Make sure your machine is able to open an outgoing TCP connection
+to build.samba.org on port 873 (the rsync port). Test this by running
+<pre>
+ rsync build.samba.org::
+</pre>
+and seeing if you get back the list of rsync modules.
+
+<li>If all is OK then create an account called "build" on the
+machine. If you can't create accounts then you can use an existing
+account, no special privileges are needed, just change ~build to your
+home directory in the instructions below.
+
+<li>Make sure a recent version of <a href="http://rsync.samba.org/">rsync</a> is installed on the machine
+
+<li>Create a directory ~build/build_farm/. You will need about 120MB of
+free space for this directory.
+
+<li>(optional) Install <a href="http://ccache.samba.org">ccache</a>
+and set a reasonable cache size (300MB would be plenty). This
+massively reduces the compilation times and system load for certain changes.
+
+<li>Grab the script build_test from cvs or from <a
+href="http://www.samba.org/ftp/unpacked/build_farm/build_test">http://www.samba.org/ftp/unpacked/build_farm/build_test</a>
+and put it in ~build/build_farm/
+
+<li>Edit the script if necessary to update the location of the build_farm directory
+
+<li>Tell <a href="mailto:vance@samba.org">Vance Lankhaar</a> the name of your
+machine (as given by the hostname command) and its OS and architecture
+plus what C compilers are installed. He will send you a
+password. Put that in a file called ".password" in the build_farm
+directory.
+
+<li>Run the script build_test once manually and make sure the build ran OK. Look in build.log for errors.
+
+<li>Setup a cron job to run build_test regularly. You may wish to use
+"nice" to reduce its priority, for example I use the following cron
+entry:
+<pre>
+ 0,30 * * * * /bin/nice /home/build/build_farm/build_test 2> /home/build/cron.err
+</pre>
+
+<li>Check that <a href="http://build.samba.org/">build.samba.org</a>
+is showing your new host and that it is being updated regularly.
+</ul>
+
+Note that only a very small amount of bandwidth is used.
+Andrew Bartlett reports having seen 6 of the boxes in the farm from behind a
+modem, and it only used a tiny proportion of that modems bandwidth.
+He also reports having had 2 of the machines behind a modem - dial-up links
+are fine too.
+
+<p>Thanks!
+
+</BODY>
+</HTML>
--- /dev/null
+<img src="vmware.gif" align=right><br>
+Many thanks to <a href="http://www.vmware.com/">VMware</a> for
+providing a GSX server license for this machine
--- /dev/null
+# Please don't crawl the build farm.. running the cgis takes a lot of
+# work
+
+User-Agent: *
+Disallow: /
--- /dev/null
+<b>ROPEABLE</b> is a dual PIII/650 in Canberra, Australia. Kindly provided by <a href="http://www.valinux.com">VA Linux Systems</a><br>
--- /dev/null
+<img src=compaq-testdrive.gif align=right><br>
+This machine kindly provided by <a href="http://www.testdrive.compaq.com">Compaq Test Drive</a>
\ No newline at end of file
--- /dev/null
+<img src=compaq-testdrive.gif align=right><br>
+This machine kindly provided by <a href="http://www.testdrive.compaq.com">Compaq Test Drive</a>
\ No newline at end of file
--- /dev/null
+<img src=compaq-testdrive.gif align=right><br>
+This machine kindly provided by <a href="http://www.testdrive.compaq.com">Compaq Test Drive</a>
\ No newline at end of file
--- /dev/null
+<img src=compaq-testdrive.gif align=right><br>
+This machine kindly provided by <a href="http://www.testdrive.compaq.com">Compaq Test Drive</a>
\ No newline at end of file
--- /dev/null
+<img src=compaq-testdrive.gif align=right><br>
+This machine kindly provided by <a href="http://www.testdrive.compaq.com">Compaq Test Drive</a>
\ No newline at end of file
--- /dev/null
+<img src=compaq-testdrive.gif align=right><br>
+This machine kindly provided by <a href="http://www.testdrive.compaq.com">Compaq Test Drive</a>
\ No newline at end of file
--- /dev/null
+<img src=compaq-testdrive.gif align=right><br>
+This machine kindly provided by <a href="http://www.testdrive.compaq.com">Compaq Test Drive</a>
\ No newline at end of file
--- /dev/null
+<img src=compaq-testdrive.gif align=right><br>
+This machine kindly provided by <a href="http://www.testdrive.compaq.com">Compaq Test Drive</a>
\ No newline at end of file
--- /dev/null
+<img src=compaq-testdrive.gif align=right><br>
+This machine kindly provided by <a href="http://www.testdrive.compaq.com">Compaq Test Drive</a>
\ No newline at end of file
--- /dev/null
+<b>SVAMP</b> is a dual PIII/550 in Canberra, Australia<br>
--- /dev/null
+###################################################
+# utility functions to support pidl
+# Copyright (C) tridge@samba.org, 2001
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+package util;
+
+use Data::Dumper;
+
+#####################################################################
+# check if a string is in an array
+sub InArray($$)
+{
+ my $s = shift;
+ my $a = shift;
+ for my $v (@{$a}) {
+ if ($v eq $s) { return 1; }
+ }
+ return 0;
+}
+
+#####################################################################
+# flatten an array of arrays into a single array
+sub FlattenArray($)
+{
+ my $a = shift;
+ my @b;
+ for my $d (@{$a}) {
+ for my $d1 (@{$d}) {
+ push(@b, $d1);
+ }
+ }
+ return \@b;
+}
+
+#####################################################################
+# flatten an array of hashes into a single hash
+sub FlattenHash($)
+{
+ my $a = shift;
+ my %b;
+ for my $d (@{$a}) {
+ for my $k (keys %{$d}) {
+ $b{$k} = $d->{$k};
+ }
+ }
+ return \%b;
+}
+
+
+#####################################################################
+# return the modification time of a file
+sub FileModtime($)
+{
+ my($filename) = shift;
+ return (stat($filename))[9];
+}
+
+
+#####################################################################
+# read a file into a string
+sub FileLoad($)
+{
+ my($filename) = shift;
+ local(*INPUTFILE);
+ open(INPUTFILE, $filename) || return "";
+ my($saved_delim) = $/;
+ undef $/;
+ my($data) = <INPUTFILE>;
+ close(INPUTFILE);
+ $/ = $saved_delim;
+ return $data;
+}
+
+#####################################################################
+# write a string into a file
+sub FileSave($$)
+{
+ my($filename) = shift;
+ my($v) = shift;
+ local(*FILE);
+ open(FILE, ">$filename") || die "can't open $filename";
+ print FILE $v;
+ close(FILE);
+}
+
+#####################################################################
+# return a filename with a changed extension
+sub ChangeExtension($$)
+{
+ my($fname) = shift;
+ my($ext) = shift;
+ if ($fname =~ /^(.*)\.(.*?)$/) {
+ return "$1.$ext";
+ }
+ return "$fname.$ext";
+}
+
+#####################################################################
+# save a data structure into a file
+sub SaveStructure($$)
+{
+ my($filename) = shift;
+ my($v) = shift;
+ FileSave($filename, Dumper($v));
+}
+
+#####################################################################
+# load a data structure from a file (as saved with SaveStructure)
+sub LoadStructure($)
+{
+ return eval FileLoad(shift);
+}
+
+
+####################################################################
+# setup for gzipped output of a web page if possible.
+# based on cvsweb.pl method
+# as a side effect this function adds the final line ot the HTTP headers
+sub cgi_gzip()
+{
+ my $paths = ['/usr/bin/gzip', '/bin/gzip'];
+ my $GZIPBIN;
+ my $Browser = $ENV{'HTTP_USER_AGENT'} || "";
+
+# newer browsers accept gzip content encoding
+# and state this in a header
+# (netscape did always but didn't state it)
+# It has been reported that these
+# braindamaged MS-Internet Exploders claim that they
+# accept gzip .. but don't in fact and
+# display garbage then :-/
+# Turn off gzip if running under mod_perl. piping does
+# not work as expected inside the server. One can probably
+# achieve the same result using Apache::GZIPFilter.
+ my $maycompress = (($ENV{'HTTP_ACCEPT_ENCODING'} =~ m|gzip|
+ || $Browser =~ m%^Mozilla/3%)
+ && ($Browser !~ m/MSIE/)
+ && !defined($ENV{'MOD_PERL'}));
+
+ if (!$maycompress) { print "\r\n"; return; }
+
+ for my $p (@{$paths}) {
+ if (stat($p)) { $GZIPBIN = $p; }
+ }
+
+ my $fh = do {local(*FH);};
+
+ if (stat($GZIPBIN) && open($fh, "|$GZIPBIN -1 -c")) {
+ print "Content-encoding: x-gzip\r\n";
+ print "Vary: Accept-Encoding\r\n"; #RFC 2068, 14.43
+ print "\r\n"; # Close headers
+ $| = 1; $| = 0; # Flush header output
+ select ($fh);
+ } else {
+ print "\r\n";
+ }
+}
+
+##########################################
+# escape a string for cgi
+sub cgi_escape($)
+{
+ my $s = shift;
+
+ $s =~ s/&/&/mg;
+ $s =~ s/</</mg;
+ $s =~ s/>/>/mg;
+ $s =~ s/"/"/mg;
+
+ return $s;
+}
+
+##########################################
+# count the number of lines in a buffer
+sub count_lines($)
+{
+ my $s = shift;
+ my $count;
+ $count = split(/$/m, $s);
+ return $count;
+}
+
+################
+# display a time as days, hours, minutes
+sub dhm_time($)
+{
+ my $sec = shift;
+ my $days = int($sec / (60*60*24));
+ my $hour = int($sec / (60*60)) % 24;
+ my $min = int($sec / 60) % 60;
+
+ my $ret = "";
+
+ if ($sec < 0) {
+ return "-";
+ }
+
+ if ($days != 0) {
+ return sprintf("%dd %dh %dm", $days, $hour, $min);
+ }
+ if ($hour != 0) {
+ return sprintf("%dh %dm", $hour, $min);
+ }
+ if ($min != 0) {
+ return sprintf("%dm", $min);
+ }
+ return sprintf("%ds", $sec);
+}
+
+1;
+
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount --enable-krb5developer"
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
--- /dev/null
+export CFLAGS="-O -Wall"
+
+test_tree ccache . gcc
+test_tree distcc . gcc
+test_tree rsync . gcc
+
+test_tree samba4 source gcc
+export config="--with-quotas --with-pam --with-pam_smbpass --with-smbmount"
+
+test_tree samba_2_2 source gcc
+test_tree samba_3_0 source gcc
+