The tinderbox has moved to projcvs.
This commit is contained in:
parent
b96008e410
commit
a693fbc197
@ -50,7 +50,6 @@ recoverdisk Copy as much data as possible from a deffective disk.
|
||||
scsi-defects Get at the primary or grown defect list of a SCSI disk.
|
||||
sysdoc Build a manual page with available sysctls for a specific
|
||||
kernel configuration.
|
||||
tinderbox Sample script for nightly test builds.
|
||||
vop_table Generates a HTML document that shows all the VOP's in
|
||||
the kernel.
|
||||
whereintheworld Summarizes "make world" output.
|
||||
|
@ -1,2 +0,0 @@
|
||||
tbmaster.1.gz
|
||||
tinderbox.1.gz
|
@ -1,15 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
BINDIR ?= ${HOME}/bin
|
||||
BINOWN ?= ${USER}
|
||||
BINGRP ?= ${USER}
|
||||
SCRIPTS = tbmaster.pl tinderbox.pl
|
||||
|
||||
MANDIR ?= ${HOME}/man/man
|
||||
MANOWN ?= ${USER}
|
||||
MANGRP ?= ${USER}
|
||||
MAN = tbmaster.1 tinderbox.1
|
||||
|
||||
SUBDIR = etc www
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,18 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
ETCFILES =
|
||||
ETCFILES += default.rc
|
||||
ETCFILES += releng_4.rc update_releng_4.rc
|
||||
ETCFILES += releng_5.rc update_releng_5.rc
|
||||
ETCFILES += releng_6.rc update_releng_6.rc
|
||||
ETCFILES += head.rc update_head.rc
|
||||
ETCDIR ?= ${HOME}/etc
|
||||
ETCOWN ?= ${USER}
|
||||
ETCGRP ?= ${USER}
|
||||
|
||||
realinstall:
|
||||
.for FILE in ${ETCFILES}
|
||||
${INSTALL} -m0644 -o${ETCOWN} -g${ETCGRP} ${.CURDIR}/${FILE} ${ETCDIR}
|
||||
.endfor
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,21 +0,0 @@
|
||||
#
|
||||
# Tinderbox defaults
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
comment = %%branch%% tinderbox
|
||||
|
||||
# Paths
|
||||
sandbox = %%HOME%%
|
||||
logdir = %%HOME%%/logs
|
||||
|
||||
# Tinderbox options
|
||||
options = --verbose
|
||||
targets = cleanobj, update, world, lint, kernel:GENERIC
|
||||
#timeout = 7200
|
||||
|
||||
# Reporting
|
||||
sender = FreeBSD Tinderbox <tinderbox@freebsd.org>
|
||||
recipient = %%SENDER%%
|
||||
subject = [%%COMMENT%%] failure on %%arch%%/%%machine%%
|
@ -1,12 +0,0 @@
|
||||
#
|
||||
# HEAD tinderbox setup
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
branches = HEAD
|
||||
platforms = amd64, i386/i386, i386/pc98, sparc64
|
||||
cflags = -O2 -pipe
|
||||
coptflags = %%CFLAGS%%
|
||||
targets += kernel:PAE
|
||||
recipient = %%SENDER%%,<current@freebsd.org>,<%%arch%%@freebsd.org>
|
@ -1,9 +0,0 @@
|
||||
#
|
||||
# RELENG_4 tinderbox setup
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
branches = RELENG_4_11, RELENG_4
|
||||
platforms = alpha, i386/i386, i386/pc98
|
||||
recipient = %%SENDER%%,<stable@freebsd.org>,<%%arch%%@freebsd.org>
|
@ -1,9 +0,0 @@
|
||||
#
|
||||
# RELENG_5 tinderbox setup
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
branches = RELENG_5_4, RELENG_5_5, RELENG_5
|
||||
platforms = alpha, amd64, i386/i386, i386/pc98, sparc64
|
||||
recipient = %%SENDER%%,<stable@freebsd.org>,<%%arch%%@freebsd.org>
|
@ -1,11 +0,0 @@
|
||||
#
|
||||
# RELENG_6 tinderbox setup
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
branches = RELENG_6_0, RELENG_6_1, RELENG_6
|
||||
platforms = alpha, amd64, i386/i386, i386/pc98, sparc64
|
||||
cflags = -O2 -pipe
|
||||
coptflags = %%CFLAGS%%
|
||||
recipient = %%SENDER%%,<stable@freebsd.org>,<%%arch%%@freebsd.org>
|
@ -1,4 +0,0 @@
|
||||
# $FreeBSD$
|
||||
branches = HEAD
|
||||
platforms = amd64, i386/i386, i386/pc98, sparc64
|
||||
targets = update
|
@ -1,4 +0,0 @@
|
||||
# $FreeBSD$
|
||||
branches = RELENG_4_11, RELENG_4
|
||||
platforms = alpha, i386/i386, i386/pc98
|
||||
targets = update
|
@ -1,4 +0,0 @@
|
||||
# $FreeBSD$
|
||||
branches = RELENG_5_4, RELENG_5_5, RELENG_5
|
||||
platforms = alpha, amd64, i386/i386, i386/pc98, sparc64
|
||||
targets = update
|
@ -1,4 +0,0 @@
|
||||
# $FreeBSD$
|
||||
branches = RELENG_6_0, RELENG_6_1, RELENG_6
|
||||
platforms = alpha, amd64, i386/i386, i386/pc98, sparc64
|
||||
targets = update
|
@ -1,59 +0,0 @@
|
||||
$FreeBSD$
|
||||
|
||||
Index: contrib/gcc/config/rs6000/freebsd.h
|
||||
===================================================================
|
||||
RCS file: /home/ncvs/src/contrib/gcc/config/rs6000/freebsd.h,v
|
||||
retrieving revision 1.1.1.2
|
||||
diff -u -r1.1.1.2 freebsd.h
|
||||
--- contrib/gcc/config/rs6000/freebsd.h 11 Jul 2003 03:40:53 -0000 1.1.1.2
|
||||
+++ contrib/gcc/config/rs6000/freebsd.h 9 Sep 2003 06:51:49 -0000
|
||||
@@ -43,6 +43,23 @@
|
||||
#undef LINK_SHLIB_SPEC
|
||||
#define LINK_SHLIB_SPEC "%{shared:-shared} %{!shared: %{static:-static}}"
|
||||
|
||||
+/* We don't want _BIG_ENDIAN or _LITTLE_ENDIAN to be defined. */
|
||||
+#undef RS6000_CPU_CPP_ENDIAN_BUILTINS
|
||||
+#define RS6000_CPU_CPP_ENDIAN_BUILTINS() \
|
||||
+ do \
|
||||
+ { \
|
||||
+ if (BYTES_BIG_ENDIAN) \
|
||||
+ { \
|
||||
+ builtin_define ("__BIG_ENDIAN__"); \
|
||||
+ builtin_assert ("machine=bigendian"); \
|
||||
+ } \
|
||||
+ else \
|
||||
+ { \
|
||||
+ builtin_define ("__LITTLE_ENDIAN__"); \
|
||||
+ builtin_assert ("machine=littleendian"); \
|
||||
+ } \
|
||||
+ } \
|
||||
+ while (0)
|
||||
|
||||
/************************[ Target stuff ]***********************************/
|
||||
|
||||
@@ -58,6 +75,9 @@
|
||||
|
||||
#undef WCHAR_TYPE_SIZE
|
||||
#define WCHAR_TYPE_SIZE 32
|
||||
+
|
||||
+#undef DEFAULT_SIGNED_CHAR
|
||||
+#define DEFAULT_SIGNED_CHAR 1
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (FreeBSD/PowerPC ELF)");
|
||||
Index: contrib/gcc/config/rs6000/sysv4.h
|
||||
===================================================================
|
||||
RCS file: /home/ncvs/src/contrib/gcc/config/rs6000/sysv4.h,v
|
||||
retrieving revision 1.1.1.6
|
||||
diff -u -r1.1.1.6 sysv4.h
|
||||
--- contrib/gcc/config/rs6000/sysv4.h 11 Jul 2003 03:40:53 -0000 1.1.1.6
|
||||
+++ contrib/gcc/config/rs6000/sysv4.h 9 Sep 2003 06:51:49 -0000
|
||||
@@ -21,8 +21,6 @@
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
-/* Header files should be C++ aware in general. */
|
||||
-#define NO_IMPLICIT_EXTERN_C
|
||||
|
||||
/* Yes! We are ELF. */
|
||||
#define TARGET_OBJECT_FORMAT OBJECT_ELF
|
@ -1,289 +0,0 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 2003-2006 Dag-Erling Coïdan Smørgrav
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 2, 2006
|
||||
.Dt TBMASTER 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm tbmaster
|
||||
.Nd manage tinderbox runs
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op options
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
script manages
|
||||
.Xr tinderbox 1
|
||||
runs, generates log summaries, and mails out failure reports.
|
||||
.Pp
|
||||
The following options are recognized:
|
||||
.Bl -tag -width 12n
|
||||
.It Fl c Ar NAME , Fl -config Ns = Ns Ar NAME
|
||||
The name of the configuration to use.
|
||||
If specified multiple times, all listed configurations will be run in
|
||||
sequence.
|
||||
The default is the hostname minus the domain part.
|
||||
.It Fl d , Fl -dump
|
||||
Dumps the configuration and exits without running the tinderbox.
|
||||
.It Fl e Ar DIR , Fl -etcdir Ns = Ns Ar DIR
|
||||
The directory where configuration files are located.
|
||||
The default is
|
||||
.Pa $HOME/etc .
|
||||
.It Fl l Ar FILE
|
||||
The name of a file to lock upon startup.
|
||||
If the lock is already held by another process,
|
||||
.Nm
|
||||
will terminate immediately rather than block.
|
||||
.El
|
||||
.Ss Configuration
|
||||
The
|
||||
.Nm
|
||||
script uses named configurations located in individual files named for
|
||||
the setup they describe, with a
|
||||
.Pa .rc
|
||||
suffix.
|
||||
For instance, the
|
||||
.Dq snoosnoo
|
||||
configuration is contained in
|
||||
.Pa snoosnoo.rc .
|
||||
.Pp
|
||||
In addition,
|
||||
.Nm
|
||||
attempts to read
|
||||
.Pa default.rc
|
||||
and
|
||||
.Pa site.rc
|
||||
before reading the actual configuration file; thus, these files may be
|
||||
used to specify default values shared by multiple configurations.
|
||||
.Pp
|
||||
The configuration consists of a list of single- or multiple-value
|
||||
variable assignments:
|
||||
.Bl -tag
|
||||
.It Va single_variable = Ar value
|
||||
.It Va multi_variable = Ar value1 , Ar value2, ...
|
||||
.It Va multi_variable += Ar value3 , ...
|
||||
.El
|
||||
.Pp
|
||||
Whitespace around the equal sign and around the commas separating
|
||||
multiple values is optional.
|
||||
.Pp
|
||||
Blank lines are ignored, as is anything following a hash sign
|
||||
.Pq Dq # .
|
||||
.Pp
|
||||
The following configuration variables are defined:
|
||||
.Bl -tag -width 12n
|
||||
.It ARCH
|
||||
.Pq Vt single
|
||||
The architecture currently being built for.
|
||||
Read-only.
|
||||
.It BRANCH
|
||||
.Pq Vt single
|
||||
The branch currently being built.
|
||||
Read-only.
|
||||
.It BRANCHES
|
||||
.Pq Vt multiple
|
||||
A list of source branches to build.
|
||||
The default value is
|
||||
.Dq HEAD .
|
||||
.It CFLAGS
|
||||
.Pq Vt single
|
||||
The desired value for the
|
||||
.Va CFLAGS
|
||||
.Xr make 1
|
||||
variable.
|
||||
This is equivalent to specifying
|
||||
.Va CFLAGS
|
||||
in
|
||||
.Va ENV .
|
||||
No default value.
|
||||
.It COPTFLAGS
|
||||
.Pq Vt single
|
||||
The desired value for the
|
||||
.Va COPTFLAGS
|
||||
.Xr make 1
|
||||
variable.
|
||||
This is equivalent to specifying
|
||||
.Va COPTFLAGS
|
||||
in
|
||||
.Va ENV .
|
||||
No default value.
|
||||
.It COMMENT
|
||||
.Pq Vt single
|
||||
A terse comment describing the setup.
|
||||
No default value.
|
||||
.It CVSUP
|
||||
.Pq Vt single
|
||||
The name of the
|
||||
.Xr cvsup 1
|
||||
server to use.
|
||||
No default value.
|
||||
.It DATE
|
||||
.Pq Vt single
|
||||
The date to use when checking out sources, or
|
||||
.Dq today
|
||||
for today's sources.
|
||||
If left undefined, the top of each branch is used.
|
||||
No default value.
|
||||
.It ENV
|
||||
.Pq Vt multiple
|
||||
A list of environment variables to pass to the
|
||||
.Xr tinderbox 1
|
||||
script.
|
||||
Each value is the name and value of an environment variable, separated
|
||||
by an equal sign
|
||||
.Pq Dq = .
|
||||
No default value.
|
||||
.It HOME
|
||||
.Pq Vt single
|
||||
The current user's home directory, as specified by the
|
||||
.Ev HOME
|
||||
environment variable.
|
||||
Note that it will not be defined unless it passes some simple sanity
|
||||
checks.
|
||||
Read-only.
|
||||
.It HOSTNAME
|
||||
.Pq Vt single
|
||||
The name of the host running the tinderbox.
|
||||
This defaults to the name reported by the
|
||||
.Fl n
|
||||
option of the
|
||||
.Xr uname 1
|
||||
command, and is only used for cosmetic purposes.
|
||||
.It JOBS
|
||||
The maximum number of concurrent
|
||||
.Xr make 1
|
||||
jobs to run.
|
||||
No default value.
|
||||
.It LOGDIR
|
||||
.Pq Vt single
|
||||
The location of the log directory.
|
||||
The default value is
|
||||
.Pa %%SANDBOX%%/logs .
|
||||
.It MACHINE
|
||||
.Pq Vt single
|
||||
The machine currently being built for.
|
||||
Read-only.
|
||||
.It OPTIONS
|
||||
.Pq Vt multiple
|
||||
A list of additional options to pass to the
|
||||
.Xr tinderbox 1
|
||||
script.
|
||||
No default value.
|
||||
.It PATCH
|
||||
.Pq Vt single
|
||||
The file name (either absolute, or relative to the sandbox directory)
|
||||
of the patch to apply if the
|
||||
.Dq patch
|
||||
command is specified.
|
||||
No default value.
|
||||
.It PLATFORMS
|
||||
.Pq Vt multiple
|
||||
Which architectures and machines to build for.
|
||||
Each value is the name of an architecture, optionally followed by a
|
||||
forward slash
|
||||
.Pq Dq /
|
||||
and a machine name.
|
||||
If the machine name is not specified, it is assumed to be identical to
|
||||
the architecture name.
|
||||
The default value is
|
||||
.Dq i386 .
|
||||
.It RECIPIENT
|
||||
.Pq Vt single
|
||||
The address to which failure reports should be mailed.
|
||||
No default value.
|
||||
.It REPOSITORY
|
||||
.Pq Vt single
|
||||
The location of the
|
||||
.Xr cvs 1
|
||||
repository.
|
||||
No default value.
|
||||
.It SANDBOX
|
||||
.Pq Vt single
|
||||
The location of the sandbox directory.
|
||||
The default value is
|
||||
.Pa /tmp/tinderbox .
|
||||
.It SENDER
|
||||
.Pq Vt single
|
||||
The envelope sender to use when mailing out failure reports.
|
||||
This should be a single email address.
|
||||
No default value.
|
||||
.It SUBJECT
|
||||
.Pq Vt single
|
||||
The subject to use on failure reports.
|
||||
The default value is
|
||||
.Dq Tinderbox failure on %%arch%%/%%machine%% .
|
||||
.It TARGETS
|
||||
.Pq Vt multiple
|
||||
A list of targets (commands) to specify to the
|
||||
.Xr tinderbox 1
|
||||
script.
|
||||
The default is
|
||||
.Dq world .
|
||||
.It TIMEOUT
|
||||
The number of seconds after which each tinderbox invocation will time
|
||||
out.
|
||||
No default value.
|
||||
.It TINDERBOX
|
||||
The location of the
|
||||
.Xr tinderbox 1
|
||||
script.
|
||||
The default value is
|
||||
.Dq %%HOME%%/bin/tinderbox .
|
||||
.El
|
||||
.Pp
|
||||
Fields which are left undefined are filled in from the
|
||||
.Dq global
|
||||
setup.
|
||||
.Ss Variable Substitution
|
||||
All single-valued configuration variables are subject to variable
|
||||
substitution immediately before use.
|
||||
If a variable's value contains strings of the form
|
||||
.Va %%VAR%%
|
||||
or
|
||||
.Va %%var%% ,
|
||||
those strings are replaced with the values of the corresponding
|
||||
variables.
|
||||
The difference between the first and the second form is that the
|
||||
latter expands to lower-case.
|
||||
For instance,
|
||||
.Dq %%BRANCH%%
|
||||
might expand to
|
||||
.Dq RELENG_4
|
||||
while
|
||||
.Dq %%branch%%
|
||||
would expand to
|
||||
.Dq releng_4 .
|
||||
.Sh SEE ALSO
|
||||
.Xr perl 1 ,
|
||||
.Xr tinderbox 1
|
||||
.Sh AUTHORS
|
||||
.Nm
|
||||
was written by
|
||||
.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org .
|
||||
.Sh BUGS
|
||||
- part of a complete breakfast!
|
@ -1,590 +0,0 @@
|
||||
#!/usr/bin/perl -Tw
|
||||
#-
|
||||
# Copyright (c) 2003-2006 Dag-Erling Coïdan Smørgrav
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer
|
||||
# in this position and unchanged.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
use 5.006_001;
|
||||
use strict;
|
||||
use Fcntl qw(:DEFAULT :flock);
|
||||
use POSIX;
|
||||
use Getopt::Long;
|
||||
|
||||
my $VERSION = "2.3";
|
||||
my $COPYRIGHT = "Copyright (c) 2003-2006 Dag-Erling Smørgrav. " .
|
||||
"All rights reserved.";
|
||||
|
||||
my @configs; # Names of requested configations
|
||||
my $dump; # Dump configuration and exit
|
||||
my $etcdir; # Configuration directory
|
||||
my $lockfile; # Lock file name
|
||||
my $lock; # Lock file descriptor
|
||||
|
||||
my %INITIAL_CONFIG = (
|
||||
'BRANCHES' => [ 'HEAD' ],
|
||||
'CFLAGS' => '',
|
||||
'COPTFLAGS' => '',
|
||||
'COMMENT' => '',
|
||||
'CVSUP' => '',
|
||||
'DATE' => '',
|
||||
'ENV' => [],
|
||||
'HOSTNAME' => '',
|
||||
'JOBS' => '',
|
||||
'LOGDIR' => '%%SANDBOX%%/logs',
|
||||
'OPTIONS' => [],
|
||||
'PATCH' => '',
|
||||
'PLATFORMS' => [ 'i386' ],
|
||||
'RECIPIENT' => '',
|
||||
'REPOSITORY'=> '',
|
||||
'SANDBOX' => '/tmp/tinderbox',
|
||||
'SENDER' => '',
|
||||
'SUBJECT' => 'Tinderbox failure on %%arch%%/%%machine%%',
|
||||
'TARGETS' => [ 'update', 'world' ],
|
||||
'TIMEOUT' => '',
|
||||
'TINDERBOX' => '%%HOME%%/bin/tinderbox',
|
||||
);
|
||||
my %CONFIG;
|
||||
|
||||
###
|
||||
### Expand a path
|
||||
###
|
||||
sub realpath($;$);
|
||||
sub realpath($;$) {
|
||||
my $path = shift;
|
||||
my $base = shift || "";
|
||||
|
||||
my $realpath = ($path =~ m|^/|) ? "" : $base;
|
||||
my @parts = split('/', $path);
|
||||
while (defined(my $part = shift(@parts))) {
|
||||
if ($part eq '' || $part eq '.') {
|
||||
# nothing
|
||||
} elsif ($part eq '..') {
|
||||
$realpath =~ s|/[^/]+$||
|
||||
or die("'$path' is not a valid path relative to '$base'\n");
|
||||
} elsif (-l "$realpath/$part") {
|
||||
my $target = readlink("$realpath/$part")
|
||||
or die("unable to resolve symlink '$realpath/$part': $!\n");
|
||||
$realpath = realpath($target, $realpath);
|
||||
} else {
|
||||
$part =~ m/^([\w.-]+)$/
|
||||
or die("unsafe path '$realpath/$part'\n");
|
||||
$realpath .= "/$1";
|
||||
}
|
||||
}
|
||||
return $realpath;
|
||||
}
|
||||
|
||||
###
|
||||
### Perform variable expansion
|
||||
###
|
||||
sub expand($);
|
||||
sub expand($) {
|
||||
my $key = shift;
|
||||
|
||||
return "??$key??"
|
||||
unless exists($CONFIG{uc($key)});
|
||||
return $CONFIG{uc($key)}
|
||||
if (ref($CONFIG{uc($key)}));
|
||||
my $str = $CONFIG{uc($key)};
|
||||
while ($str =~ s/\%\%(\w+)\%\%/expand($1)/eg) {
|
||||
# nothing
|
||||
}
|
||||
return ($key =~ m/[A-Z]/) ? $str : lc($str);
|
||||
}
|
||||
|
||||
###
|
||||
### Reset the configuration to initial values
|
||||
###
|
||||
sub clearconf() {
|
||||
|
||||
%CONFIG = %INITIAL_CONFIG;
|
||||
}
|
||||
|
||||
###
|
||||
### Read in a configuration file
|
||||
###
|
||||
sub readconf($) {
|
||||
my $fn = shift;
|
||||
|
||||
local *CONF;
|
||||
sysopen(CONF, $fn, O_RDONLY)
|
||||
or return undef;
|
||||
my $line = "";
|
||||
my $n = 0;
|
||||
while (<CONF>) {
|
||||
++$n;
|
||||
chomp();
|
||||
s/\s*(\#.*)?$//;
|
||||
$line .= $_;
|
||||
if (length($line) && $line !~ s/\\$/ /) {
|
||||
die("$fn: syntax error on line $n\n")
|
||||
unless ($line =~ m/^(\w+)\s*([+]?=)\s*(.*)$/);
|
||||
my ($key, $op, $val) = (uc($1), $2, $3);
|
||||
$val = ''
|
||||
unless defined($val);
|
||||
die("$fn: unknown keyword on line $n\n")
|
||||
unless (exists($CONFIG{$key}));
|
||||
if (ref($CONFIG{$key})) {
|
||||
my @a = split(/\s*,\s*/, $val);
|
||||
foreach (@a) {
|
||||
s/^\'([^\']*)\'$/$1/;
|
||||
}
|
||||
if ($op eq '=') {
|
||||
$CONFIG{$key} = \@a;
|
||||
} elsif ($op eq '+=') {
|
||||
push(@{$CONFIG{$key}}, @a);
|
||||
} else {
|
||||
die("can't happen\n");
|
||||
}
|
||||
} else {
|
||||
$val =~ s/^\'([^\']*)\'$/$1/;
|
||||
if ($op eq '=') {
|
||||
$CONFIG{$key} = $val;
|
||||
} elsif ($op eq '+=') {
|
||||
die("$fn: invalid operator on line $n\n");
|
||||
} else {
|
||||
die("can't happen\n");
|
||||
}
|
||||
}
|
||||
$line = "";
|
||||
}
|
||||
}
|
||||
close(CONF);
|
||||
return 1;
|
||||
}
|
||||
|
||||
###
|
||||
### Record a tinderbox result in the history file
|
||||
###
|
||||
sub history($$$) {
|
||||
my $start = shift;
|
||||
my $end = shift;
|
||||
my $success = shift;
|
||||
|
||||
my $history = expand('HOSTNAME') . "\t";
|
||||
$history .= expand('CONFIG') . "\t";
|
||||
$history .= strftime("%Y-%m-%d %H:%M:%S\t", localtime($start));
|
||||
$history .= strftime("%Y-%m-%d %H:%M:%S\t", localtime($end));
|
||||
$history .= expand('ARCH') . "\t";
|
||||
$history .= expand('MACHINE') . "\t";
|
||||
my $date = expand('DATE');
|
||||
if ($date) {
|
||||
$date =~ s/\s+/ /g;
|
||||
$history .= expand('BRANCH') . ":" . expand('DATE') . "\t";
|
||||
} else {
|
||||
$history .= expand('BRANCH') . "\t";
|
||||
}
|
||||
$history .= $success ? "OK\n" : "FAIL\n";
|
||||
|
||||
my $fn = expand('LOGDIR') . "/history";
|
||||
local *HISTORY;
|
||||
if (sysopen(HISTORY, $fn, O_WRONLY|O_APPEND|O_CREAT, 0644)) {
|
||||
syswrite(HISTORY, $history, length($history));
|
||||
close(HISTORY);
|
||||
} else {
|
||||
print(STDERR "failed to record result to history file:\n$history\n");
|
||||
}
|
||||
}
|
||||
|
||||
###
|
||||
### Report a tinderbox failure
|
||||
###
|
||||
sub report($$$$) {
|
||||
my $sender = shift;
|
||||
my $recipient = shift;
|
||||
my $subject = shift;
|
||||
my $message = shift;
|
||||
|
||||
if (!$message) {
|
||||
print(STDERR "[empty report, not sent by email]\n\n]");
|
||||
return;
|
||||
}
|
||||
if (length($message) < 128) {
|
||||
print(STDERR "[suspiciously short report, not sent by email]\n\n");
|
||||
print(STDERR $message);
|
||||
return;
|
||||
}
|
||||
|
||||
local *PIPE;
|
||||
if (open(PIPE, "|-", "/usr/sbin/sendmail", "-i", "-t", "-f$sender")) {
|
||||
print(PIPE "Sender: $sender\n");
|
||||
print(PIPE "From: $sender\n");
|
||||
print(PIPE "To: $recipient\n");
|
||||
print(PIPE "Subject: $subject\n");
|
||||
print(PIPE "Precedence: bulk\n");
|
||||
print(PIPE "\n");
|
||||
print(PIPE "$message\n");
|
||||
close(PIPE);
|
||||
} else {
|
||||
print(STDERR "[failed to send report by email]\n\n");
|
||||
print(STDERR $message);
|
||||
}
|
||||
}
|
||||
|
||||
###
|
||||
### Run the tinderbox
|
||||
###
|
||||
sub tinderbox($$$) {
|
||||
my $branch = shift;
|
||||
my $arch = shift;
|
||||
my $machine = shift;
|
||||
|
||||
my $config = expand('CONFIG');
|
||||
my $start = time();
|
||||
|
||||
$0 = "tbmaster: building $branch for $arch/$machine";
|
||||
|
||||
$CONFIG{'BRANCH'} = $branch;
|
||||
$CONFIG{'ARCH'} = $arch;
|
||||
$CONFIG{'MACHINE'} = $machine;
|
||||
|
||||
# Open log files: one for the full log and one for the summary
|
||||
my $logfile = expand('LOGDIR') .
|
||||
"/tinderbox-$config-$branch-$arch-$machine";
|
||||
local (*FULL, *BRIEF);
|
||||
if (!open(FULL, ">", "$logfile.full.$$")) {
|
||||
warn("$logfile.full.$$: $!\n");
|
||||
return undef;
|
||||
}
|
||||
select(FULL);
|
||||
$| = 1;
|
||||
select(STDOUT);
|
||||
if (!open(BRIEF, ">", "$logfile.brief.$$")) {
|
||||
warn("$logfile.brief.$$: $!\n");
|
||||
return undef;
|
||||
}
|
||||
select(BRIEF);
|
||||
$| = 1;
|
||||
select(STDOUT);
|
||||
|
||||
# Open a pipe for the tinderbox process
|
||||
local (*RPIPE, *WPIPE);
|
||||
if (!pipe(RPIPE, WPIPE)) {
|
||||
warn("pipe(): $!\n");
|
||||
unlink("$logfile.brief.$$");
|
||||
close(BRIEF);
|
||||
unlink("$logfile.full.$$");
|
||||
close(FULL);
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Fork and start the tinderbox
|
||||
my @args = @{$CONFIG{'OPTIONS'}};
|
||||
push(@args, "--hostname=" . expand('HOSTNAME'));
|
||||
push(@args, "--sandbox=" . realpath(expand('SANDBOX')));
|
||||
push(@args, "--arch=$arch");
|
||||
push(@args, "--machine=$machine");
|
||||
push(@args, "--cvsup=" . expand('CVSUP'))
|
||||
if ($CONFIG{'CVSUP'});
|
||||
push(@args, "--repository=" . expand('REPOSITORY'))
|
||||
if ($CONFIG{'REPOSITORY'});
|
||||
push(@args, "--branch=$branch");
|
||||
push(@args, "--date=" . expand('DATE'))
|
||||
if ($CONFIG{'DATE'});
|
||||
push(@args, "--patch=" . expand('PATCH'))
|
||||
if ($CONFIG{'PATCH'});
|
||||
push(@args, "--jobs=" . expand('JOBS'))
|
||||
if ($CONFIG{'JOBS'});
|
||||
push(@args, "--timeout=" . expand('TIMEOUT'))
|
||||
if ($CONFIG{'TIMEOUT'});
|
||||
push(@args, @{$CONFIG{'TARGETS'}});
|
||||
push(@args, @{$CONFIG{'ENV'}});
|
||||
push(@args, "CFLAGS=" . expand('CFLAGS'))
|
||||
if ($CONFIG{'CFLAGS'});
|
||||
push(@args, "COPTFLAGS=" . expand('COPTFLAGS'))
|
||||
if ($CONFIG{'COPTFLAGS'});
|
||||
my $pid = fork();
|
||||
if (!defined($pid)) {
|
||||
warn("fork(): $!\n");
|
||||
unlink("$logfile.brief.$$");
|
||||
close(BRIEF);
|
||||
unlink("$logfile.full.$$");
|
||||
close(FULL);
|
||||
return undef;
|
||||
} elsif ($pid == 0) {
|
||||
close(RPIPE);
|
||||
open(STDOUT, ">&WPIPE");
|
||||
open(STDERR, ">&WPIPE");
|
||||
$| = 1;
|
||||
exec(expand('TINDERBOX'), @args);
|
||||
die("child: exec(): $!\n");
|
||||
}
|
||||
|
||||
# Process the output
|
||||
close(WPIPE);
|
||||
my @lines = ();
|
||||
my $error = 0;
|
||||
my $summary = "";
|
||||
my $root = realpath(expand('SANDBOX') . "/$branch/$arch/$machine");
|
||||
while (<RPIPE>) {
|
||||
s/\Q$root\E\/(src|obj)/\/$1/g;
|
||||
print(FULL $_);
|
||||
if (/^TB ---/ || /^>>> /) {
|
||||
if ($error) {
|
||||
$summary .= join('', @lines);
|
||||
print(BRIEF join('', @lines));
|
||||
@lines = ();
|
||||
$error = 0;
|
||||
}
|
||||
$summary .= $_;
|
||||
print(BRIEF $_);
|
||||
@lines = ();
|
||||
next;
|
||||
}
|
||||
if (/^Stop in /) {
|
||||
$error = 1;
|
||||
}
|
||||
if (@lines > 10 && !$error) {
|
||||
shift(@lines);
|
||||
$lines[0] = "[...]\n";
|
||||
}
|
||||
push(@lines, $_);
|
||||
}
|
||||
close(RPIPE);
|
||||
if ($error) {
|
||||
$summary .= join('', @lines);
|
||||
print(BRIEF join('', @lines));
|
||||
}
|
||||
|
||||
# Done...
|
||||
if (waitpid($pid, 0) == -1) {
|
||||
warn("waitpid(): $!\n");
|
||||
} elsif ($? & 0xff) {
|
||||
my $msg = "tinderbox caught signal " . ($? & 0x7f) . "\n";
|
||||
print(BRIEF $msg);
|
||||
print(FULL $msg);
|
||||
$error = 1;
|
||||
} elsif ($? >> 8) {
|
||||
my $msg = "tinderbox returned exit code " . ($? >> 8) . "\n";
|
||||
print(BRIEF $msg);
|
||||
print(FULL $msg);
|
||||
$error = 1;
|
||||
}
|
||||
close(BRIEF);
|
||||
close(FULL);
|
||||
|
||||
my $end = time();
|
||||
|
||||
# Record result in history file
|
||||
history($start, $end, !$error);
|
||||
|
||||
# Mail out error reports
|
||||
if ($error && $CONFIG{'RECIPIENT'}) {
|
||||
my $sender = expand('SENDER');
|
||||
my $recipient = expand('RECIPIENT');
|
||||
my $subject = expand('SUBJECT');
|
||||
report($sender, $recipient, $subject, $summary);
|
||||
}
|
||||
|
||||
rename("$logfile.full.$$", "$logfile.full");
|
||||
rename("$logfile.brief.$$", "$logfile.brief");
|
||||
}
|
||||
|
||||
###
|
||||
### Open and lock a file reliably
|
||||
###
|
||||
sub open_locked($;$$) {
|
||||
my $fn = shift; # File name
|
||||
my $flags = shift; # Open flags
|
||||
my $mode = shift; # File mode
|
||||
|
||||
local *FILE; # File handle
|
||||
my (@sb1, @sb2); # File status
|
||||
|
||||
for (;; close(FILE)) {
|
||||
sysopen(FILE, $fn, $flags || O_RDONLY, $mode || 0640)
|
||||
or last;
|
||||
if (!(@sb1 = stat(FILE))) {
|
||||
# Huh? shouldn't happen
|
||||
last;
|
||||
}
|
||||
if (!flock(FILE, LOCK_EX|LOCK_NB)) {
|
||||
# A failure here means the file can't be locked, or
|
||||
# something really weird happened, so just give up.
|
||||
last;
|
||||
}
|
||||
if (!(@sb2 = stat($fn))) {
|
||||
# File was pulled from under our feet, though it may
|
||||
# reappear in the next pass
|
||||
next;
|
||||
}
|
||||
if ($sb1[0] != $sb2[0] || $sb1[1] != $sb2[1]) {
|
||||
# File changed under our feet, try again
|
||||
next;
|
||||
}
|
||||
return *FILE{IO};
|
||||
}
|
||||
close(FILE);
|
||||
return undef;
|
||||
}
|
||||
|
||||
###
|
||||
### Print a usage message and exit
|
||||
###
|
||||
sub usage() {
|
||||
|
||||
print(STDERR "This is the FreeBSD tinderbox manager, version $VERSION.
|
||||
$COPYRIGHT
|
||||
|
||||
Usage:
|
||||
$0 [options] [parameters]
|
||||
|
||||
Options:
|
||||
-d, --dump Dump the processed configuration
|
||||
|
||||
Parameters:
|
||||
-c, --config=NAME Configuration name
|
||||
-e, --etcdir=DIR Configuration directory
|
||||
-l, --lockfile=FILE Lock file name
|
||||
|
||||
Report bugs to <des\@freebsd.org>.
|
||||
");
|
||||
print(STDERR "usage: tbmaster\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
###
|
||||
### Main loop
|
||||
###
|
||||
sub tbmaster($) {
|
||||
my $config = shift;
|
||||
|
||||
clearconf();
|
||||
readconf('default.rc');
|
||||
readconf('site.rc');
|
||||
readconf("$config.rc")
|
||||
or die("$config.rc: $!\n");
|
||||
$CONFIG{'CONFIG'} = $config;
|
||||
$CONFIG{'ETCDIR'} = $etcdir;
|
||||
|
||||
if ($dump) {
|
||||
foreach my $key (sort(keys(%CONFIG))) {
|
||||
printf("%-12s = ", uc($key));
|
||||
if (!defined($CONFIG{$key})) {
|
||||
print("(undef)");
|
||||
} elsif (ref($CONFIG{$key})) {
|
||||
print(join(", ", @{$CONFIG{$key}}));
|
||||
} else {
|
||||
print($CONFIG{$key});
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!length(expand('TINDERBOX')) || !-x expand('TINDERBOX')) {
|
||||
die("Where is the tinderbox script?\n");
|
||||
}
|
||||
|
||||
my $stopfile = expand('SANDBOX') . "/stop";
|
||||
foreach my $branch (@{$CONFIG{'BRANCHES'}}) {
|
||||
foreach my $platform (@{$CONFIG{'PLATFORMS'}}) {
|
||||
if (-e $stopfile || -e "$stopfile.$config") {
|
||||
die("stop file found, aborting\n");
|
||||
}
|
||||
my ($arch, $machine) = split('/', $platform, 2);
|
||||
$machine = $arch
|
||||
unless defined($machine);
|
||||
if (-e "$stopfile.$arch" || -e "$stopfile.$arch.$machine") {
|
||||
warn("stop file for $arch/$machine found, skipping\n");
|
||||
next;
|
||||
}
|
||||
tinderbox($branch, $arch, $machine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
###
|
||||
### Main
|
||||
###
|
||||
MAIN:{
|
||||
# Set defaults
|
||||
$ENV{'TZ'} = "UTC";
|
||||
$ENV{'PATH'} = "/usr/bin:/usr/sbin:/bin:/sbin";
|
||||
$INITIAL_CONFIG{'HOSTNAME'} = `/usr/bin/uname -n`;
|
||||
if ($INITIAL_CONFIG{'HOSTNAME'} =~ m/^([0-9a-z-]+(?:\.[0-9a-z-]+)*)$/) {
|
||||
$INITIAL_CONFIG{'HOSTNAME'} = $1;
|
||||
} else {
|
||||
$INITIAL_CONFIG{'HOSTNAME'} = 'unknown';
|
||||
}
|
||||
if ($ENV{'HOME'} =~ m/^((?:\/[\w\.-]+)+)\/*$/) {
|
||||
$INITIAL_CONFIG{'HOME'} = realpath($1);
|
||||
$etcdir = "$1/etc";
|
||||
$ENV{'PATH'} = "$1/bin:$ENV{'PATH'}"
|
||||
if (-d "$1/bin");
|
||||
}
|
||||
|
||||
# Get options
|
||||
{Getopt::Long::Configure("auto_abbrev", "bundling");}
|
||||
GetOptions(
|
||||
"c|config=s" => \@configs,
|
||||
"d|dump" => \$dump,
|
||||
"e|etcdir=s" => \$etcdir,
|
||||
"l|lockfile=s" => \$lockfile,
|
||||
) or usage();
|
||||
if (@ARGV) {
|
||||
usage();
|
||||
}
|
||||
|
||||
# Check options
|
||||
if (@configs) {
|
||||
@configs = split(/,/, join(',', @configs));
|
||||
} else {
|
||||
$configs[0] = `/usr/bin/uname -n`;
|
||||
chomp($configs[0]);
|
||||
$configs[0] =~ s/^(\w+)(\..*)?/$1/;
|
||||
}
|
||||
if (defined($etcdir)) {
|
||||
if ($etcdir !~ m/^([\w\/\.-]+)$/) {
|
||||
die("invalid etcdir\n");
|
||||
}
|
||||
$etcdir = $1;
|
||||
chdir($etcdir)
|
||||
or die("$etcdir: $!\n");
|
||||
}
|
||||
for (my $n = 0; $n < @configs; ++$n) {
|
||||
$configs[$n] =~ m/^(\w+)$/
|
||||
or die("invalid config: $configs[$n]\n");
|
||||
$configs[$n] = $1;
|
||||
}
|
||||
|
||||
# Acquire lock
|
||||
if (defined($lockfile)) {
|
||||
if ($lockfile !~ m/^([\w\/\.-]+)$/) {
|
||||
die("invalid lockfile\n");
|
||||
}
|
||||
$lockfile = $1;
|
||||
$lock = open_locked($lockfile, O_WRONLY|O_CREAT, 0600)
|
||||
or die("unable to acquire lock on $lockfile\n");
|
||||
# Lock will be released upon termination.
|
||||
}
|
||||
|
||||
# Run all specified or implied configurations
|
||||
foreach my $config (@configs) {
|
||||
tbmaster($config);
|
||||
}
|
||||
exit(0);
|
||||
}
|
@ -1,319 +0,0 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 2003-2006 Dag-Erling Coïdan Smørgrav
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 7, 2006
|
||||
.Dt TINDERBOX 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm tinderbox
|
||||
.Nd build and release testing
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op options
|
||||
.Ar command Op ...
|
||||
.Op Ar variable Ns = Ns Ar value ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
script tests the
|
||||
.Fx
|
||||
build and release system by performing a cross-build (and optionally a
|
||||
cross-release) of an arbitrary branch of the source tree for an
|
||||
arbitrary target platform.
|
||||
.Pp
|
||||
The following options are recognized:
|
||||
.Bl -tag -width 12n
|
||||
.It Fl a Ar ARCH , Fl -arch Ns = Ns Ar ARCH
|
||||
Specifies the target architecture.
|
||||
The default value is whatever the host system's
|
||||
.Xr uname 1
|
||||
reports.
|
||||
.It Fl b Ar BRANCH , Fl -branch Ns = Ns Ar BRANCH
|
||||
The branch to specify to
|
||||
.Xr cvs 1
|
||||
or
|
||||
.Xr cvsup 1
|
||||
when updating the source tree.
|
||||
The default is to use
|
||||
.Fl A
|
||||
instead, to get the head.
|
||||
Specifying
|
||||
.Va HEAD
|
||||
as the argument to
|
||||
.Fl -branch
|
||||
is equivalent to leaving it unspecified.
|
||||
.It Fl c Ar NAME , Fl -cvsup Ns = Ns Ar NAME
|
||||
The name of the
|
||||
.Xr cvsup 1
|
||||
server from which to update the source tree
|
||||
.Cm update
|
||||
command is specified.
|
||||
The default is to use
|
||||
.Xr cvs 1
|
||||
instead.
|
||||
.It Fl d Ar DATE , Fl -date Ns = Ns Ar DATE
|
||||
The date to specify to
|
||||
.Xr cvs 1
|
||||
or
|
||||
.Xr cvsup 1
|
||||
when updating the source tree.
|
||||
As a special case, the value
|
||||
.Dq today
|
||||
corresponds to midnight UTC the day the run starts.
|
||||
The default is to use the top of whichever branch was specified.
|
||||
.It Fl h Ar NAME , Fl -hostname Ns = Ns Ar NAME
|
||||
The name of the host running the tinderbox.
|
||||
This defaults to the name reported by the
|
||||
.Fl n
|
||||
option of the
|
||||
.Xr uname 1
|
||||
command, and is only used for cosmetic purposes.
|
||||
.It Fl j Ar NUM , Fl -jobs Ns = Ns Ar NUM
|
||||
The maximum number of paralell jobs, as specified to
|
||||
.Xr make 1
|
||||
using the
|
||||
.Fl j
|
||||
option.
|
||||
The default is 1.
|
||||
.It Fl l Ar FILE , Fl -logfile Ns = Ns Ar FILE
|
||||
The name of a file to which the output and error messages produced by
|
||||
the build should be written.
|
||||
Note that this file can grow quite large.
|
||||
The default is to redirect all output to
|
||||
.Pa /dev/stdout .
|
||||
.It Fl m Ar MACHINE , Fl -machine Ns = Ns Ar MACHINE
|
||||
Specifies the target machine.
|
||||
The default value is whatever the host system's
|
||||
.Xr uname 1
|
||||
reports, unless a target architecture was specified with the
|
||||
.It Fl a
|
||||
option, in which case the target machine is set to the same value.
|
||||
.It Fl p Ar PATCH , Fl -patch Ns = Ns Ar PATCH
|
||||
The file name of a patch to apply to the source tree before building
|
||||
if the
|
||||
.Cm patch
|
||||
command is specified.
|
||||
The patch should be relative to the root of the source tree.
|
||||
When building a release, the patch is passed to the release process
|
||||
through the
|
||||
.Ev LOCAL_PATCHES
|
||||
environment variable (see
|
||||
.Xr release 7
|
||||
for more information), regardless of whether the
|
||||
.Cm patch
|
||||
command was specified.
|
||||
The default is to not apply any patches.
|
||||
.It Fl r Ar DIR , Fl -repository Ns = Ns Ar DIR
|
||||
The location of the
|
||||
.Xr cvs 1
|
||||
repository from which to update the source tree if the
|
||||
.Cm update
|
||||
command is specified.
|
||||
The default is
|
||||
.Pa /home/ncvs .
|
||||
.It Fl s Ar DIR , Fl -sandbox Ns = Ns Ar DIR
|
||||
The location of the sandbox in which the builds are to take place.
|
||||
This directory should reside on a reasonably fast disk with at least
|
||||
1.5 GB available (3 GB if building a release).
|
||||
.It Fl t Ar NUM , Fl -timeout Ns = Ns Ar NUM
|
||||
The maximum wall-time duration of the run, in seconds.
|
||||
The default is to continue until all targets are completed.
|
||||
.It Fl v , Fl -verbose
|
||||
Enable additional debugging output.
|
||||
.El
|
||||
.Pp
|
||||
Following the options on the command line, at least one of the
|
||||
following commands must be specified:
|
||||
.Bl -tag -width 12n
|
||||
.It Cm clean
|
||||
Delete the source and object trees.
|
||||
This is highly recommended when sources are patched, as successive
|
||||
builds will fail due to repeated application of the same patch to the
|
||||
same sources.
|
||||
.Pp
|
||||
Note that this does not remove the chroot tree created and populated
|
||||
by the release build.
|
||||
.It Cm update
|
||||
Update the sources using
|
||||
.Xr cvs 1 .
|
||||
This is highly recommended, for obvious reasons, if the
|
||||
.Cm clean
|
||||
command is specified.
|
||||
.It Cm patch
|
||||
Apply the patch specified with the
|
||||
.Fl -patch
|
||||
option to the source tree.
|
||||
If the specified patch file does not exist, the
|
||||
.Cm patch
|
||||
command will fail gracefully.
|
||||
.It Cm world
|
||||
Build the world.
|
||||
.It Cm lint
|
||||
Build a LINT kernel if available.
|
||||
In
|
||||
.Fx
|
||||
5 and newer, the
|
||||
.Pa LINT
|
||||
configuration file will first be generated from the corresponding
|
||||
.Pa NOTES
|
||||
file.
|
||||
If neither
|
||||
.Pa LINT
|
||||
nor
|
||||
.Pa NOTES
|
||||
exist in the kernel configuration directory, the
|
||||
.Cm lint
|
||||
command will fail gracefully.
|
||||
.It Cm kernel: Ns Ar CONF
|
||||
Build the
|
||||
.Ar CONF
|
||||
kernel.
|
||||
If a file named
|
||||
.Ar CONF
|
||||
does not exist in the kernel configuration directory, this command
|
||||
will fail gracefully.
|
||||
.It Cm generic
|
||||
Equivalent to
|
||||
.Cm kernel: Ns Ar GENERIC ,
|
||||
for backward compatibility.
|
||||
.It Cm release
|
||||
Build a release by following the procedure described in
|
||||
.Xr release 7 .
|
||||
Note that this is a lengthy process which requires root privileges.
|
||||
.El
|
||||
.Pp
|
||||
The commands are executed in the order in which they are listed above,
|
||||
regardless of the order in which they are listed on the command line.
|
||||
.Pp
|
||||
Finally, any arguments of the form
|
||||
.Ar variable Ns = Ns Ar value
|
||||
are interpreted as environment variables which are exported into the
|
||||
build environment.
|
||||
These variables are not allowed to override those set by the script
|
||||
itself (see
|
||||
.Sx ENVIRONMENT
|
||||
below).
|
||||
.Sh NOTES
|
||||
The
|
||||
.Nm
|
||||
script was originally written to perform daily build testing of
|
||||
.Fx
|
||||
4 and 5.
|
||||
It is not intended for use with older releases, and probably will not
|
||||
work with anything older than
|
||||
.Fx 4.2 .
|
||||
.Sh ENVIRONMENT
|
||||
The
|
||||
.Nm
|
||||
script clears its environment at startup and provides its child
|
||||
processes with a tailored environment.
|
||||
The following variables are set for all builds:
|
||||
.Bl -tag -width 18n
|
||||
.It PATH
|
||||
.Va /usr/bin:/usr/sbin:/bin:/sbin
|
||||
.It TZ
|
||||
.Va UTC
|
||||
.It __MAKE_CONF
|
||||
.Va /dev/null
|
||||
.It CFLAGS
|
||||
.Va -O -pipe
|
||||
.El
|
||||
.Pp
|
||||
In addition, if one or more of the
|
||||
.Cm generic ,
|
||||
.Cm lint
|
||||
or
|
||||
.Cm release
|
||||
command was specified, the following variables, which affect kernel
|
||||
builds, are set:
|
||||
.Bl -tag -width 18n
|
||||
.It COPTFLAGS
|
||||
.Va -O -pipe
|
||||
.El
|
||||
.Pp
|
||||
Finally, the following variables are set for release builds:
|
||||
.Bl -tag -width 18n
|
||||
.It CHROOTDIR
|
||||
.Va $SANDBOX/root
|
||||
.It CVSROOT
|
||||
As specified with the
|
||||
.Fl -repository
|
||||
option.
|
||||
.It RELEASETAG
|
||||
.Va -rBRANCH
|
||||
if
|
||||
.Fl -branch Ns = Ns Ar BRANCH
|
||||
was specified, or
|
||||
.Va -A
|
||||
otherwise.
|
||||
.It CVSCMDARGS
|
||||
.Va -DDATE
|
||||
if
|
||||
.Fl -date Ns = Ns Ar DATE
|
||||
was specified.
|
||||
.It WORLD_FLAGS , KERNEL_FLAGS
|
||||
Both of these are set to
|
||||
.Va -jN
|
||||
if
|
||||
.Fl -jobs Ns = Ns Ar N
|
||||
was specified, or
|
||||
.Va -B
|
||||
otherwise.
|
||||
.It LOCAL_PATCHES
|
||||
Set to the path of the patch that was specified with the
|
||||
.Fl -patch
|
||||
option, if any.
|
||||
.It PATCH_FLAGS
|
||||
Set to
|
||||
.Va -fs
|
||||
if a patch was specified.
|
||||
.It NOCDROM
|
||||
.Va YES
|
||||
.It NODOC
|
||||
.Va YES
|
||||
.It NOPORTS
|
||||
.Va YES
|
||||
.El
|
||||
.Pp
|
||||
Except for
|
||||
.Va CFLAGS
|
||||
and
|
||||
.Va COPTFLAGS ,
|
||||
none of these variables may be overridden by command-line arguments.
|
||||
.Sh SEE ALSO
|
||||
.Xr cvs 1 ,
|
||||
.Xr make 1 ,
|
||||
.Xr patch 1 ,
|
||||
.Xr tbmaster 1 ,
|
||||
.Xr build 7 ,
|
||||
.Xr release 7
|
||||
.Sh AUTHORS
|
||||
.Nm
|
||||
was written by
|
||||
.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org .
|
||||
.Sh BUGS
|
||||
are crunchy and nutritious.
|
@ -1,663 +0,0 @@
|
||||
#!/usr/bin/perl -Tw
|
||||
#-
|
||||
# Copyright (c) 2003-2006 Dag-Erling Coïdan Smørgrav
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer
|
||||
# in this position and unchanged.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
use 5.006_001;
|
||||
use strict;
|
||||
use Fcntl qw(:DEFAULT :flock);
|
||||
use POSIX;
|
||||
use Getopt::Long;
|
||||
|
||||
my $VERSION = "2.3";
|
||||
my $COPYRIGHT = "Copyright (c) 2003-2006 Dag-Erling Smørgrav. " .
|
||||
"All rights reserved.";
|
||||
|
||||
my $arch; # Target architecture
|
||||
my $branch; # CVS branch to check out
|
||||
my $cvsup; # Name of CVSup server
|
||||
my $date; # Date of sources to check out
|
||||
my $jobs; # Number of paralell jobs
|
||||
my $hostname; # Name of the host running the tinderbox
|
||||
my $logfile; # Path to log file
|
||||
my $machine; # Target machine
|
||||
my $patch; # Patch to apply before building
|
||||
my $repository; # Location of CVS repository
|
||||
my $sandbox; # Location of sandbox
|
||||
my $timeout; # Timeout in seconds
|
||||
my $verbose; # Verbose mode
|
||||
|
||||
my %children;
|
||||
|
||||
my %userenv;
|
||||
|
||||
my %cmds = (
|
||||
'clean' => 0,
|
||||
'cleansrc' => 0,
|
||||
'cleanobj' => 0,
|
||||
'cleanroot' => 0,
|
||||
'update' => 0,
|
||||
'patch' => 0,
|
||||
'world' => 0,
|
||||
'lint' => 0,
|
||||
'release' => 0,
|
||||
);
|
||||
my %kernels;
|
||||
|
||||
my $starttime;
|
||||
|
||||
BEGIN {
|
||||
($starttime) = POSIX::times();
|
||||
}
|
||||
|
||||
END {
|
||||
my ($endtime, $user, $system) = POSIX::times();
|
||||
my $ticks = POSIX::sysconf(&POSIX::_SC_CLK_TCK);
|
||||
printf(STDERR "TB --- %.2f user %.2f system %.2f real\n",
|
||||
$user / $ticks, $system / $ticks, ($endtime - $starttime) / $ticks);
|
||||
}
|
||||
|
||||
sub message(@) {
|
||||
|
||||
my $msg = join(' ', @_);
|
||||
chomp($msg);
|
||||
warn("$msg\n");
|
||||
}
|
||||
|
||||
sub warning(@) {
|
||||
|
||||
my $msg = join(' ', "WARNING:", @_);
|
||||
chomp($msg);
|
||||
warn("$msg\n");
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub error(@) {
|
||||
|
||||
my $msg = join(' ', "ERROR:", @_);
|
||||
chomp($msg);
|
||||
die("$msg\n");
|
||||
return undef;
|
||||
}
|
||||
|
||||
#
|
||||
# Open and lock a file reliably
|
||||
#
|
||||
sub open_locked($;$$) {
|
||||
my $fn = shift; # File name
|
||||
my $flags = shift; # Open flags
|
||||
my $mode = shift; # File mode
|
||||
|
||||
local *FILE; # File handle
|
||||
my (@sb1, @sb2); # File status
|
||||
|
||||
for (;; close(FILE)) {
|
||||
sysopen(FILE, $fn, $flags || O_RDONLY, $mode || 0640)
|
||||
or last;
|
||||
if (!(@sb1 = stat(FILE))) {
|
||||
# Huh? shouldn't happen
|
||||
warning("$fn: stat(): $!");
|
||||
last;
|
||||
}
|
||||
if (!flock(FILE, LOCK_EX|LOCK_NB)) {
|
||||
# A failure here means the file can't be locked, or
|
||||
# something really weird happened, so just give up.
|
||||
warning("$fn: flock(): $!");
|
||||
last;
|
||||
}
|
||||
if (!(@sb2 = stat($fn))) {
|
||||
# File was pulled from under our feet, though it may
|
||||
# reappear in the next pass
|
||||
next;
|
||||
}
|
||||
if ($sb1[0] != $sb2[0] || $sb1[1] != $sb2[1]) {
|
||||
# File changed under our feet, try again
|
||||
next;
|
||||
}
|
||||
return *FILE{IO};
|
||||
}
|
||||
close(FILE);
|
||||
return undef;
|
||||
}
|
||||
|
||||
#
|
||||
# Remove a directory and all its subdirectories
|
||||
#
|
||||
sub remove_dir($);
|
||||
sub remove_dir($) {
|
||||
my $dir = shift;
|
||||
|
||||
if (-l $dir || !-d $dir) {
|
||||
print("rm $dir\n")
|
||||
if ($verbose);
|
||||
if (!unlink($dir) && $! != ENOENT) {
|
||||
return warning("$dir: $!");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
local *DIR;
|
||||
opendir(DIR, $dir)
|
||||
or return warning("$dir: $!");
|
||||
my @entries = readdir(DIR);
|
||||
closedir(DIR)
|
||||
or return warning("$dir: $!");
|
||||
foreach my $ent (@entries) {
|
||||
next if ($ent eq '.' || $ent eq '..');
|
||||
$ent =~ m/(.*)/;
|
||||
remove_dir("$dir/$1")
|
||||
or return undef;
|
||||
}
|
||||
print("rmdir $dir\n")
|
||||
if ($verbose);
|
||||
rmdir($dir)
|
||||
or return warning("$dir: $!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub make_dir($);
|
||||
sub make_dir($) {
|
||||
my $dir = shift;
|
||||
|
||||
if (!-d $dir && $dir =~ m|^(\S*)/([^\s/]+)$|) {
|
||||
make_dir($1)
|
||||
or return undef;
|
||||
message("mkdir $dir");
|
||||
mkdir("$dir")
|
||||
or return undef;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub cd($) {
|
||||
my $dir = shift;
|
||||
|
||||
message("cd $dir");
|
||||
chdir($dir)
|
||||
or error("$dir: $!");
|
||||
}
|
||||
|
||||
#
|
||||
# Spawn a child and wait for it to finish
|
||||
#
|
||||
sub spawn($@) {
|
||||
my $cmd = shift; # Command to run
|
||||
my @args = @_; # Arguments
|
||||
|
||||
message($cmd, @args);
|
||||
my $pid = fork();
|
||||
if (!defined($pid)) {
|
||||
return warning("fork(): $!");
|
||||
} elsif ($pid == 0) {
|
||||
exec($cmd, @args);
|
||||
die("child: exec(): $!\n");
|
||||
}
|
||||
$children{$pid} = $pid;
|
||||
my $ret = waitpid($pid, 0);
|
||||
delete $children{$pid};
|
||||
if ($ret == -1) {
|
||||
return warning("waitpid(): $!\n");
|
||||
} elsif ($? & 0xff) {
|
||||
return warning("$cmd caught signal ", $? & 0x7f, "\n");
|
||||
} elsif ($? >> 8) {
|
||||
return warning("$cmd returned exit code ", $? >> 8, "\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub make($) {
|
||||
my $target = shift;
|
||||
|
||||
return spawn('/usr/bin/make',
|
||||
($jobs > 1) ? "-j$jobs" : "-B",
|
||||
$target);
|
||||
}
|
||||
|
||||
sub logstage($) {
|
||||
my $msg = shift;
|
||||
|
||||
chomp($msg);
|
||||
$0 = "tinderbox: [$branch $arch/$machine] $msg";
|
||||
print(STDERR strftime("TB --- %Y-%m-%d %H:%M:%S - $msg\n", localtime()));
|
||||
}
|
||||
|
||||
sub sigwarn {
|
||||
|
||||
logstage(shift);
|
||||
}
|
||||
|
||||
sub sigdie {
|
||||
|
||||
logstage(shift);
|
||||
logstage("tinderbox aborted");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sub timeout() {
|
||||
kill(15, keys(%children))
|
||||
if (%children);
|
||||
error("timed out after $timeout seconds");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sub usage() {
|
||||
|
||||
print(STDERR "This is the FreeBSD tinderbox script, version $VERSION.
|
||||
$COPYRIGHT
|
||||
|
||||
Usage:
|
||||
$0 [options] [parameters] command [...]
|
||||
|
||||
Options:
|
||||
-v, --verbose Verbose mode
|
||||
|
||||
Parameters:
|
||||
-a, --arch=ARCH Target architecture (e.g. i386)
|
||||
-b, --branch=BRANCH CVS branch to check out
|
||||
-d, --date=DATE Date of sources to check out
|
||||
-j, --jobs=NUM Maximum number of paralell jobs
|
||||
-h, --hostname=NAME Name of the host running the tinderbox
|
||||
-l, --logfile=FILE Path to log file
|
||||
-m, --machine=MACHINE Target machine (e.g. pc98)
|
||||
-p, --patch=PATCH Patch to apply before building
|
||||
-r, --repository=DIR Location of CVS repository
|
||||
-s, --sandbox=DIR Location of sandbox
|
||||
|
||||
Commands:
|
||||
clean Clean the sandbox
|
||||
update Update the source tree
|
||||
patch Patch the source tree
|
||||
world Build the world
|
||||
generic Build the GENERIC kernel
|
||||
lint Build the LINT kernel
|
||||
release Build a full release (run as root!)
|
||||
|
||||
Report bugs to <des\@freebsd.org>.
|
||||
");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
MAIN:{
|
||||
# Clear environment and set timezone
|
||||
%ENV = (
|
||||
'TZ' => "UTC",
|
||||
'PATH' => "/usr/bin:/usr/sbin:/bin:/sbin",
|
||||
);
|
||||
tzset();
|
||||
|
||||
# Set defaults
|
||||
$hostname = `/usr/bin/uname -n`;
|
||||
chomp($hostname);
|
||||
$branch = "HEAD";
|
||||
$jobs = 0;
|
||||
$repository = "/home/ncvs";
|
||||
$sandbox = "/tmp/tinderbox";
|
||||
$timeout = 0;
|
||||
|
||||
# Get options
|
||||
{Getopt::Long::Configure("auto_abbrev", "bundling");}
|
||||
GetOptions(
|
||||
"a|arch=s" => \$arch,
|
||||
"b|branch=s" => \$branch,
|
||||
"c|cvsup=s" => \$cvsup,
|
||||
"d|date=s" => \$date,
|
||||
"j|jobs=i" => \$jobs,
|
||||
"l|logfile=s" => \$logfile,
|
||||
"h|hostname=s" => \$hostname,
|
||||
"m|machine=s" => \$machine,
|
||||
"p|patch=s" => \$patch,
|
||||
"r|repository=s" => \$repository,
|
||||
"s|sandbox=s" => \$sandbox,
|
||||
"t|timeout=i" => \$timeout,
|
||||
"v|verbose+" => \$verbose,
|
||||
) or usage();
|
||||
|
||||
if ($jobs < 0) {
|
||||
error("invalid number of jobs");
|
||||
}
|
||||
if ($timeout < 0) {
|
||||
error("invalid timeout");
|
||||
}
|
||||
if ($branch !~ m|^(\w+)$|) {
|
||||
error("invalid source branch");
|
||||
}
|
||||
$branch = ($1 eq 'CURRENT') ? 'HEAD' : $1;
|
||||
if (!defined($arch)) {
|
||||
$arch = `/usr/bin/uname -p`;
|
||||
chomp($arch);
|
||||
if (!defined($machine)) {
|
||||
$machine = `/usr/bin/uname -m`;
|
||||
chomp($machine);
|
||||
}
|
||||
}
|
||||
if ($arch !~ m|^(\w+)$|) {
|
||||
error("invalid target architecture");
|
||||
}
|
||||
$arch = $1;
|
||||
if (!defined($machine)) {
|
||||
$machine = $arch;
|
||||
}
|
||||
if ($machine !~ m|^(\w+)$|) {
|
||||
error("invalid target machine");
|
||||
}
|
||||
$machine = $1;
|
||||
if (defined($date)) {
|
||||
if ($date eq 'today') {
|
||||
$date = strftime("%Y-%m-%d", localtime());
|
||||
} elsif ($date !~ m/^(\d{4}-\d{2}-\d{2})$/) {
|
||||
error("invalid checkout date");
|
||||
} else {
|
||||
$date = $1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!@ARGV) {
|
||||
usage();
|
||||
}
|
||||
|
||||
# Set up a timeout
|
||||
if ($timeout > 0) {
|
||||
$SIG{ALRM} = \&timeout;
|
||||
alarm($timeout);
|
||||
}
|
||||
|
||||
# Find out what we're expected to do
|
||||
foreach my $cmd (@ARGV) {
|
||||
if ($cmd =~ m/^([0-9A-Z_]+)=(.*)\s*$/) {
|
||||
$userenv{$1} = $2;
|
||||
next;
|
||||
}
|
||||
if ($cmd =~ m/^kernel:(\w+)$/) {
|
||||
$kernels{$1} = 1;
|
||||
next;
|
||||
}
|
||||
# backward compatibility
|
||||
# note that LINT is special, GENERIC is not
|
||||
if ($cmd eq 'generic') {
|
||||
$kernels{'GENERIC'} = 1;
|
||||
next;
|
||||
}
|
||||
if (!exists($cmds{$cmd})) {
|
||||
error("unrecognized command: '$cmd'");
|
||||
}
|
||||
$cmds{$cmd} = 1;
|
||||
}
|
||||
|
||||
# Open logfile
|
||||
open(STDIN, '<', "/dev/null")
|
||||
or error("/dev/null: $!\n");
|
||||
if (defined($logfile)) {
|
||||
if ($logfile !~ m|([\w./-]+)$|) {
|
||||
error("invalid log file name");
|
||||
}
|
||||
$logfile = $1;
|
||||
unlink($logfile);
|
||||
open(STDOUT, '>', $logfile)
|
||||
or error("$logfile: $!");
|
||||
}
|
||||
open(STDERR, ">&STDOUT");
|
||||
$| = 1;
|
||||
logstage("tinderbox $VERSION running on $hostname");
|
||||
logstage("starting $branch tinderbox run for $arch/$machine");
|
||||
$SIG{__DIE__} = \&sigdie;
|
||||
$SIG{__WARN__} = \&sigwarn;
|
||||
|
||||
# Take control of our sandbox
|
||||
if ($sandbox !~ m|^(/[\w./-]+)$|) {
|
||||
error("invalid sandbox directory");
|
||||
}
|
||||
$sandbox = "$1/$branch/$arch/$machine";
|
||||
$ENV{'HOME'} = $sandbox;
|
||||
make_dir($sandbox)
|
||||
or error("$sandbox: $!");
|
||||
my $lockfile = open_locked("$sandbox/lock", O_RDWR|O_CREAT);
|
||||
if (!defined($lockfile)) {
|
||||
error("unable to lock sandbox");
|
||||
}
|
||||
truncate($lockfile, 0);
|
||||
print($lockfile "$$\n");
|
||||
|
||||
# Clean up remains from old runs
|
||||
if ($cmds{'clean'} || $cmds{'cleansrc'}) {
|
||||
logstage("cleaning the source tree");
|
||||
if (-e "$sandbox/src") {
|
||||
remove_dir("$sandbox/src")
|
||||
or error("unable to remove old source directory");
|
||||
}
|
||||
}
|
||||
if ($cmds{'clean'} || $cmds{'cleanobj'}) {
|
||||
logstage("cleaning the object tree");
|
||||
if (-e "$sandbox/obj") {
|
||||
remove_dir("$sandbox/obj")
|
||||
or error("unable to remove old object directory");
|
||||
}
|
||||
}
|
||||
if ($cmds{'clean'} || $cmds{'cleanroot'}) {
|
||||
logstage("cleaning the chroot tree");
|
||||
if (-e "$sandbox/root") {
|
||||
spawn('/bin/chflags', '-R', '0', "$sandbox/root");
|
||||
remove_dir("$sandbox/root")
|
||||
or error("unable to remove old chroot directory");
|
||||
}
|
||||
}
|
||||
|
||||
# Check out new source tree
|
||||
if ($cmds{'update'}) {
|
||||
if (defined($cvsup)) {
|
||||
logstage("cvsupping the source tree");
|
||||
local *SUPFILE;
|
||||
open(SUPFILE, ">", "$sandbox/supfile")
|
||||
or error("$sandbox/supfile: $!");
|
||||
print(SUPFILE "*default host=$cvsup\n");
|
||||
print(SUPFILE "*default base=$sandbox\n");
|
||||
print(SUPFILE "*default prefix=$sandbox\n");
|
||||
print(SUPFILE "*default delete use-rel-suffix\n");
|
||||
print(SUPFILE "src-all release=cvs");
|
||||
if ($branch eq 'HEAD') {
|
||||
print(SUPFILE " tag=.");
|
||||
} else {
|
||||
print(SUPFILE " tag=$branch");
|
||||
}
|
||||
print(SUPFILE " date=$date")
|
||||
if defined($date);
|
||||
print(SUPFILE "\n");
|
||||
close(SUPFILE);
|
||||
my @cvsupargs = (
|
||||
"-1",
|
||||
"-g",
|
||||
"-L", ($verbose ? 2 : 1),
|
||||
"$sandbox/supfile"
|
||||
);
|
||||
spawn('/usr/local/bin/cvsup', @cvsupargs)
|
||||
or error("unable to cvsup the source tree");
|
||||
} else {
|
||||
logstage("checking out the source tree");
|
||||
cd("$sandbox");
|
||||
my @cvsargs = (
|
||||
"-f",
|
||||
"-R",
|
||||
$verbose ? "-q" : "-Q",
|
||||
"-d$repository",
|
||||
);
|
||||
if (-d "$sandbox/src") {
|
||||
push(@cvsargs, "update", "-Pd");
|
||||
} else {
|
||||
push(@cvsargs, "checkout", "-P");
|
||||
};
|
||||
push(@cvsargs, ($branch eq 'HEAD') ? "-A" : "-r$branch")
|
||||
if defined($branch);
|
||||
push(@cvsargs, "-D$date")
|
||||
if defined($date);
|
||||
push(@cvsargs, "src");
|
||||
spawn('/usr/bin/cvs', @cvsargs)
|
||||
or error("unable to check out the source tree");
|
||||
}
|
||||
}
|
||||
|
||||
# Patch sources
|
||||
if ($cmds{'patch'} && !defined($patch)) {
|
||||
warning("no patch specified");
|
||||
$cmds{'patch'} = 0;
|
||||
}
|
||||
if ($cmds{'patch'}) {
|
||||
$patch = "$sandbox/$patch"
|
||||
unless ($patch =~ m|^/|);
|
||||
if ($patch !~ m|^(/[\w./-]+)$|) {
|
||||
error("invalid patchfile path");
|
||||
}
|
||||
$patch = $1;
|
||||
if (-f $patch) {
|
||||
logstage("patching the sources");
|
||||
cd("$sandbox/src");
|
||||
spawn('/usr/bin/patch', "-f", "-s", "-i$patch")
|
||||
or error("failed to apply patch to source tree");
|
||||
} else {
|
||||
warning("$patch does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
# Prepare environment for make(1);
|
||||
%ENV = (
|
||||
'TZ' => "UTC",
|
||||
'PATH' => "/usr/bin:/usr/sbin:/bin:/sbin",
|
||||
|
||||
'__MAKE_CONF' => "/dev/null",
|
||||
'MAKEOBJDIRPREFIX' => "$sandbox/obj",
|
||||
|
||||
'TARGET' => $machine,
|
||||
'TARGET_ARCH' => $arch,
|
||||
);
|
||||
|
||||
# Kernel-specific variables
|
||||
if (%kernels || $cmds{'lint'} || $cmds{'release'}) {
|
||||
# None at the moment
|
||||
}
|
||||
|
||||
# Release-specific variables
|
||||
if ($cmds{'release'}) {
|
||||
$ENV{'CHROOTDIR'} = "$sandbox/root";
|
||||
$ENV{'CVSROOT'} = $repository;
|
||||
$ENV{'RELEASETAG'} = $branch
|
||||
if $branch ne 'HEAD';
|
||||
$ENV{'CVSCMDARGS'} = "-D$date"
|
||||
if defined($date);
|
||||
$ENV{'WORLD_FLAGS'} = $ENV{'KERNEL_FLAGS'} =
|
||||
($jobs > 1) ? "-j$jobs" : "-B";
|
||||
if ($patch) {
|
||||
$ENV{'LOCAL_PATCHES'} = $patch;
|
||||
$ENV{'PATCH_FLAGS'} = "-fs";
|
||||
}
|
||||
|
||||
# Save time and space
|
||||
$ENV{'NOCDROM'} = "YES";
|
||||
$ENV{'NODOC'} = "YES";
|
||||
$ENV{'NOPORTS'} = "YES";
|
||||
}
|
||||
|
||||
# User-supplied variables
|
||||
foreach my $key (keys(%userenv)) {
|
||||
if (exists($ENV{$key})) {
|
||||
warning("will not allow override of $key");
|
||||
} else {
|
||||
$ENV{$key} = $userenv{$key};
|
||||
}
|
||||
}
|
||||
|
||||
# Defaults for overridable variables
|
||||
if (!exists($ENV{'CFLAGS'})) {
|
||||
$ENV{'CFLAGS'} = "-O -pipe";
|
||||
}
|
||||
if (%kernels || $cmds{'lint'} || $cmds{'release'}) {
|
||||
if (!exists($ENV{'COPTFLAGS'})) {
|
||||
$ENV{'COPTFLAGS'} = "-O -pipe";
|
||||
}
|
||||
}
|
||||
|
||||
# List the environment when verbose
|
||||
if ($verbose && $verbose > 1) {
|
||||
foreach my $key (sort(keys(%ENV))) {
|
||||
message("$key=$ENV{$key}\n");
|
||||
}
|
||||
}
|
||||
|
||||
# Build the world, or at least the kernel toolchain
|
||||
if ($cmds{'world'}) {
|
||||
logstage("building world (CFLAGS=$ENV{'CFLAGS'})");
|
||||
cd("$sandbox/src");
|
||||
make('buildworld')
|
||||
or error("failed to build world");
|
||||
} elsif (%kernels || $cmds{'lint'}) {
|
||||
logstage("building kernel toolchain (CFLAGS=$ENV{'CFLAGS'})");
|
||||
cd("$sandbox/src");
|
||||
make('kernel-toolchain')
|
||||
or error("failed to build kernel toolchain");
|
||||
}
|
||||
|
||||
# Build LINT if requested
|
||||
if ($cmds{'lint'}) {
|
||||
if (-f "$sandbox/src/sys/$machine/conf/NOTES") {
|
||||
logstage("generating LINT kernel config");
|
||||
cd("$sandbox/src/sys/$machine/conf");
|
||||
make('LINT')
|
||||
or error("failed to generate LINT kernel config");
|
||||
}
|
||||
if (! -f "$sandbox/src/sys/$machine/conf/LINT") {
|
||||
warning("no kernel config for LINT");
|
||||
$cmds{'lint'} = 0;
|
||||
}
|
||||
}
|
||||
if ($cmds{'lint'}) {
|
||||
logstage("building LINT kernel (COPTFLAGS=$ENV{'COPTFLAGS'})");
|
||||
cd("$sandbox/src");
|
||||
spawn('/usr/bin/make', 'buildkernel', 'KERNCONF=LINT')
|
||||
or error("failed to build lint kernel");
|
||||
}
|
||||
|
||||
# Build additional kernels
|
||||
foreach my $kernel (sort(keys(%kernels))) {
|
||||
if (! -f "$sandbox/src/sys/$machine/conf/$kernel") {
|
||||
warning("no kernel config for $kernel");
|
||||
next;
|
||||
}
|
||||
logstage("building $kernel kernel (COPTFLAGS=$ENV{'COPTFLAGS'})");
|
||||
cd("$sandbox/src");
|
||||
spawn('/usr/bin/make', 'buildkernel', "KERNCONF=$kernel")
|
||||
or error("failed to build $kernel kernel");
|
||||
}
|
||||
|
||||
# Build a release if requested
|
||||
if ($cmds{'release'}) {
|
||||
logstage("building a release");
|
||||
cd("$sandbox/src/release");
|
||||
make('release')
|
||||
or error("failed to build release");
|
||||
}
|
||||
|
||||
# Exiting releases the lock file
|
||||
logstage("tinderbox run completed");
|
||||
exit(0);
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
daemon.png
|
||||
valid-css.png
|
||||
valid-xhtml10.png
|
@ -1,25 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
CGI = index.cgi
|
||||
DATA = tb.css
|
||||
IMAGES = daemon.png valid-css.png valid-xhtml10.png
|
||||
CLEANFILES += ${IMAGES}
|
||||
WWWDIR ?= ${HOME}/public_html
|
||||
WWWOWN ?= ${USER}
|
||||
WWWGRP ?= ${USER}
|
||||
|
||||
all: ${IMAGES}
|
||||
|
||||
realinstall:
|
||||
${INSTALL} -m0755 -o${WWWOWN} -g${WWWGRP} ${.CURDIR}/${CGI} ${WWWDIR}
|
||||
.for _data in ${DATA}
|
||||
${INSTALL} -m0644 -o${WWWOWN} -g${WWWGRP} ${.CURDIR}/${_data} ${WWWDIR}
|
||||
.endfor
|
||||
.for _image in ${IMAGES}
|
||||
${INSTALL} -m0644 -o${WWWOWN} -g${WWWGRP} ${_image} ${WWWDIR}
|
||||
.endfor
|
||||
|
||||
${IMAGES}: ${.TARGET}.uu
|
||||
uudecode ${.ALLSRC}
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,144 +0,0 @@
|
||||
begin 644 daemon.png
|
||||
MB5!.1PT*&@H````-24A$4@```%````!,"`8```#Z!3!-````!F)+1T0`_P#_
|
||||
M`/^@O:>3````"7!(67,```L2```+$@'2W7[\````!W1)344'TP8#"@(%BD"-
|
||||
MM```&#Q)1$%4>)SMG'E\'-65[[]5W:WNJNINJ;NU6K(LRPM&PF#`+`X$;-X`
|
||||
M!L*$$&P@@01",B2&,$`RGB3O@0,9>"],6$+&3#(A3!@@R8!9!H8EP,2.V10+
|
||||
M@HTMC['19EE;2]TM]5)5K:ZN^_ZH5MO"SL002=9\,K_/1Q]]JKKJUKV_.N>>
|
||||
M<\\YM^!_\.>-^^Z]3ZR^8)5XY+$GQ)'NRW];?/V&;XH5S<O$Z@M6B=:6UC\/
|
||||
M(M]]Y65QS^W_=](&>\655XD5S<O$Q4VGB'5K;YDV$N7I>M"!N/WV.\03W_M[
|
||||
M1H<')ZW-1Q_YN12N#).09`:>?XDUJ[XD^O?VK)FT!_P!3#N!Z];>(LQ7-Q$U
|
||||
MQOC6S7_[P&2V_86;KF4$BR$A4[:KC=O7?&/]5),XK02N_]FC8O/SKT(BR=QC
|
||||
MFE`::JZ;S/9/7G+\=:6*GX0D$[-M%N[MX4<W_.WZR7S&A^&>RL8/1$=WU\9+
|
||||
M+KZ2!F%3(<F$/G$B_//AW[OYY5>7=^[I9C`6)9@'I;*24$V$,X]IXOBSSY$`
|
||||
MMN]H6S\X`J7Y$?9@$_&7L6CW+NZX^FOB?__S/TI3,:XI:?106+WJ,C&TLYMR
|
||||
M/<D"(?C,KQ[FI%-/^B^??]^]]XG7GGV%6$IGU$CCU=.(C$FE7,FLB%V\[GW%
|
||||
MSYF?.(X=V_?0$8WBU=.HV)SJ+V-1/L=`F9\5]]S]1Y_W<3`M*KQI\^MB^[N#
|
||||
M&/H(I;)$U"63&<O^P>M__M,'Q8KF9>)7]_^$WJX.C+X>2H:&40T#2?.144;H
|
||||
MU77RI@%`12S*KY_[-;U='83T)``Z,E&?#SMK43DXPI9'GYB2L4V+"C^YX1EJ
|
||||
M\GWTNV8QF-99[$OQ^TVO'?+:KUYSK?CQG7<CLCD2EDD(#YHL0(:,[$8"(K@I
|
||||
ME?<+TP(A*'6Y:-8"`.S*6VS3T[AT'0!/)D/O>^].R=BF10*WO_D..C)!O0<`
|
||||
M%8GAAQ[AZV>>)Y[ZY8:BN[%N[2UBZV\V.S=9>4)XBFUD9#<I#\Q&Y@+9Q>G(
|
||||
MG.$MX6@]Q\*:<EP^A39O"4-E?A:YW)PE)/*JBNQU9"1JC$W)V*9E#ES1O$SH
|
||||
MB2&P\N!V46E'6>`I!PR_145Y%75>(9DQ%CA$PVCV9;^(4;(4601(Q!D4?2
|
||||
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
|
||||
3V`AEKF[CM`````!)14Y$KD)@@@``
|
||||
`
|
||||
end
|
@ -1,201 +0,0 @@
|
||||
#!/usr/bin/perl -Tw
|
||||
#-
|
||||
# Copyright (c) 2003-2006 Dag-Erling Coïdan Smørgrav
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer
|
||||
# in this position and unchanged.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
use 5.006_001;
|
||||
use strict;
|
||||
use POSIX qw(strftime);
|
||||
|
||||
my %CONFIGS;
|
||||
my %ARCHES;
|
||||
|
||||
my $DIR = ".";
|
||||
|
||||
sub success($) {
|
||||
my $log = shift;
|
||||
|
||||
local *FILE;
|
||||
if (open(FILE, "<", $log)) {
|
||||
while (<FILE>) {
|
||||
if (m/tinderbox run completed/) {
|
||||
close(FILE);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
close(FILE);
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub branch_sort($$) {
|
||||
my ($a, $b) = @_;
|
||||
|
||||
my @a = split('_', $a);
|
||||
my @b = split('_', $b);
|
||||
while (@a || @b) {
|
||||
($a, $b) = (shift(@a), shift(@b));
|
||||
return 1 unless defined($a);
|
||||
return -1 unless defined($b);
|
||||
next if $a eq $b;
|
||||
if ($a =~ m/^\d+$/ && $b =~ m/^\d+$/) {
|
||||
return $a <=> $b;
|
||||
} else {
|
||||
return $a cmp $b;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub inverse_branch_sort($$) {
|
||||
my ($a, $b) = @_;
|
||||
|
||||
return branch_sort($b, $a);
|
||||
}
|
||||
|
||||
sub do_config($) {
|
||||
my $config = shift;
|
||||
|
||||
my %branches = %{$CONFIGS{$config}};
|
||||
|
||||
print " <tr>
|
||||
<th>$config</th>
|
||||
";
|
||||
foreach my $arch (sort(keys(%ARCHES))) {
|
||||
foreach my $machine (sort(keys(%{$ARCHES{$arch}}))) {
|
||||
if ($arch eq $machine) {
|
||||
print " <th>$arch</th>\n";
|
||||
} else {
|
||||
print " <th>$arch<br />$machine</th>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
print " </tr>\n";
|
||||
|
||||
my $now = time();
|
||||
|
||||
foreach my $branch (sort(inverse_branch_sort keys(%branches))) {
|
||||
my $html = " <tr>
|
||||
<th>$branch</th>
|
||||
";
|
||||
foreach my $arch (sort(keys(%ARCHES))) {
|
||||
foreach my $machine (sort(keys(%{$ARCHES{$arch}}))) {
|
||||
my $log = "tinderbox-$config-$branch-$arch-$machine";
|
||||
my $links = "";
|
||||
if (-f "$DIR/$log.brief") {
|
||||
my @stat = stat("$DIR/$log.brief");
|
||||
my $class = success("$DIR/$log.brief") ? "ok" : "fail";
|
||||
my $age = int(($now - $stat[9]) / 1800);
|
||||
$age = 9
|
||||
if ($age > 9);
|
||||
$class .= "-$age";
|
||||
$links .= "<span class='$class'>" .
|
||||
strftime("%Y-%m-%d %H:%M UTC", gmtime($stat[9])) .
|
||||
"</span><br />";
|
||||
my $size = sprintf("[%.1f kB]", $stat[7] / 1024);
|
||||
$links .= " <span class='tiny'>" .
|
||||
"<a target='_top' href='$log.brief'>summary $size</a>" .
|
||||
"</span><br />";
|
||||
}
|
||||
if (-f "$DIR/$log.full") {
|
||||
my @stat = stat("$DIR/$log.full");
|
||||
my $size = sprintf("[%.1f MB]", $stat[7] / 1048576);
|
||||
$links .= " <span class='tiny'>" .
|
||||
"<a target='_top' href='$log.full'>full log $size</a>" .
|
||||
"</span><br />";
|
||||
}
|
||||
if ($links eq "") {
|
||||
$html .= " <td>n/a</td>\n";
|
||||
} else {
|
||||
$html .= " <td>$links</td>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
$html .= " </tr>\n";
|
||||
print $html;
|
||||
}
|
||||
}
|
||||
|
||||
MAIN:{
|
||||
if ($ENV{'GATEWAY_INTERFACE'}) {
|
||||
$| = 1;
|
||||
print "Content-Type: text/html\n\n";
|
||||
} else {
|
||||
if ($0 =~ m|^(/[\w/._-]+)/[^/]+$|) {
|
||||
$DIR = $1;
|
||||
}
|
||||
open(STDOUT, ">", "$DIR/index.html")
|
||||
or die("index.html: $!\n");
|
||||
}
|
||||
|
||||
local *DIR;
|
||||
opendir(DIR, $DIR)
|
||||
or die("$DIR: $!\n");
|
||||
foreach (readdir(DIR)) {
|
||||
next unless m/^tinderbox-(\w+)-(\w+)-(\w+)-(\w+)\.(brief|full)$/;
|
||||
$CONFIGS{$1}->{$2} = $ARCHES{$3}->{$4} = 1;
|
||||
}
|
||||
closedir(DIR);
|
||||
|
||||
print "<?xml version='1.0' encoding='iso-8859-1'?>
|
||||
<!DOCTYPE html
|
||||
PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
|
||||
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>FreeBSD tinderbox logs</title>
|
||||
<meta name='robots' content='nofollow' />
|
||||
<meta http-equiv='refresh' content='600' />
|
||||
<link rel='stylesheet' type='text/css' media='screen' href='tb.css' />
|
||||
<link rel='shortcut icon' type='image/png' href='daemon.png' />
|
||||
</head>
|
||||
<body>
|
||||
<!-- h1>FreeBSD tinderbox logs</h1 -->
|
||||
|
||||
<table border='1' cellpadding='3'>
|
||||
";
|
||||
foreach my $config (sort(keys(%CONFIGS))) {
|
||||
next if $config =~ m/^update_/;
|
||||
do_config($config);
|
||||
}
|
||||
my $date = strftime("%Y-%m-%d %H:%M UTC", gmtime());
|
||||
print "
|
||||
</table>
|
||||
<!-- p class='update'>Last updated: $date</p -->
|
||||
<!-- p>
|
||||
<a target='_top' href='http://validator.w3.org/check/referer'><img
|
||||
src='valid-xhtml10.png'
|
||||
alt='Valid XHTML 1.0!' height='31' width='88' /></a>
|
||||
<a target='_top' href='http://jigsaw.w3.org/css-validator/check/referer'><img
|
||||
src='valid-css.png'
|
||||
alt='Valid CSS!' height='31' width='88' /></a>
|
||||
</p -->
|
||||
</body>
|
||||
</html>
|
||||
";
|
||||
exit(0);
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
BODY, H1, H2, H3, H4, H5, H6, LI {
|
||||
font-family: Helvetica, sans-serif;
|
||||
font-style: normal;
|
||||
background-color: white;
|
||||
color: navy;
|
||||
}
|
||||
|
||||
A:link {
|
||||
background-color: white;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
A:visited {
|
||||
background-color: white;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
A:active {
|
||||
background-color: white;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.tiny {
|
||||
font-size: x-small;
|
||||
}
|
||||
|
||||
.update {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.ok-0 { background-color: white; color: #007700; }
|
||||
.ok-1 { background-color: white; color: #117B11; }
|
||||
.ok-2 { background-color: white; color: #227F22; }
|
||||
.ok-3 { background-color: white; color: #338333; }
|
||||
.ok-4 { background-color: white; color: #448744; }
|
||||
.ok-5 { background-color: white; color: #558B55; }
|
||||
.ok-6 { background-color: white; color: #668F66; }
|
||||
.ok-7 { background-color: white; color: #779377; }
|
||||
.ok-8 { background-color: white; color: #889788; }
|
||||
.ok-9 { background-color: white; color: #999B99; }
|
||||
|
||||
.fail-0 { background-color: white; color: #ff0000; }
|
||||
.fail-1 { background-color: white; color: #ff1111; }
|
||||
.fail-2 { background-color: white; color: #ff2222; }
|
||||
.fail-3 { background-color: white; color: #ff3333; }
|
||||
.fail-4 { background-color: white; color: #ff4444; }
|
||||
.fail-5 { background-color: white; color: #ff5555; }
|
||||
.fail-6 { background-color: white; color: #ff6666; }
|
||||
.fail-7 { background-color: white; color: #ff7777; }
|
||||
.fail-8 { background-color: white; color: #ff8888; }
|
||||
.fail-9 { background-color: white; color: #ff9999; }
|
||||
|
||||
TD, TH {
|
||||
width: 16ex;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
IMG {
|
||||
border: none;
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
begin 644 valid-css.png
|
||||
MB5!.1PT*&@H````-24A$4@```%@````?"`,```!4%OK2````]E!,5$5CI<9S
|
||||
ME,<,1YTV9*Y4?+K?YO+N[NY,3$RNKJZ=G9V^OKZQP^"AM]F2J],L+"P```!]
|
||||
M?7T<'!SN\O@A5:;!S^:-C8T,#`P73:)DB,$+1)V.I]+.SLY=75W0V^PF6:B#
|
||||
MG\U%<+0\/#QL>I%M;6W,S,S_S&;___\`9ID8>ZU*E+WG[_=*2DJ]O<:9F9FU
|
||||
MUN>$M=8S,S.$A(0C'`X/#`9:G+UF9F;OOU^);38\,!AM5RO?LEFOC$9,/![`
|
||||
MF4S/I5);2"0L(Q$,"02<?#XQC+4Y.3D<%@O#G$[KO%Z9``!F,P#TPV&5``#,
|
||||
MF3.YE$KAM%K>L5A[<V8H(!`(-YOM`````7123E,`0.;89@````%B2T=$`(@%
|
||||
M'4@```)@241!5'B<[95M<Y-`$,>;32!)\[`-DA)MGJJ]?5/?^"9W!`*!T8JQ
|
||||
M6OW^7\:]`QR(G4G&1%\X[@1F`W,_[O[WW[V+N_/'A8D[.B+$\?'QX?X_^%\`
|
||||
M-Z#)@UO0T@P+BB"RV^T.=2]_']P#L(CZFD4T*+A-LH>(>#6Z.D$*@#Z1`]`S
|
||||
M$W_AN@T`E\9XW1XA=D\`YRIX,-$?>?F*'$\_&%[?$$U'IVQ>'SRB&<#<R.+0
|
||||
MPFB#8WYE7Q;@E51*^6O.@E"I<,-)%',2/`/.2K"E56`:S&C"XO+?!3]%N^**
|
||||
MU1:1?\E:;/BN$#=BG9@DW0=_RK*LM%L3&GQY,*`Y7RV>N\M25.TF,8G$2F&L
|
||||
MLT!(E7*"4@1J'RRSS)`->`%SWCNVW4S/>JE=X=)M%1RB7XP,V"N8Q"L1Z03#
|
||||
MJ`[.N4PV8.8MH*DET#H3N1XL:5P%QP:\D:F(I*\^,%"L9:RT0#5N6G*+RO-8
|
||||
MAP6K`<89Q%*#<U,%IY@P<\MXI3\1HF(I0B%\3)[G%N")V3FVK_&RJ1:W7M*Q
|
||||
M6?AVE4N!&(@H,8E>B4Q_X19@=EGN.*`2_#K/[+*D`U_%9GS$QI/:;FL9*C_(
|
||||
M>>ENCUN`G5P#71B-N656T.V:-],W!PLDY^U*[N=:=VL9#29<VTMHNNSI)8W&
|
||||
MN@_AP5[Q6,RSG&^];0ZXX+0"%EF>:4(SZN#H%G%XN*1+8AY?ZF#+]$Q']\^>
|
||||
M+A`]_PZWH*E]1*^HDK_N-WJK<G=F5(\#X)]JL-)G/D%*\N[L1]-CP3W_F?>4
|
||||
M<__`8?HD-?>OG-)O#\?#\?'N6PF^/W.\_VZX/P">K(-C3;4/#@````!)14Y$
|
||||
$KD)@@@``
|
||||
`
|
||||
end
|
@ -1,57 +0,0 @@
|
||||
begin 644 valid-xhtml10.png
|
||||
MB5!.1PT*&@H````-24A$4@```%@````?"`,```$C$<I$```"B%!,5$4```#>
|
||||
MY^?.>SFMK:W>C$*EA$+OO6.]6EK>A$+.>WO>I:6<E'O>M5+&<W/>K5*<"`CW
|
||||
MO5J4C'.4>U)CE+TQ.4ICC+V4``"]UN>,K<[OK5*EO=;6WN^$I<;.WN?.UN<8
|
||||
M6I2,*0B]2B%[>WM:6DH0$`B,<SD02HQ:4DIS<W.UE$H("`"$:S$A&`@(``"$
|
||||
M8S%K:VNMC$+6<SG&G$K_[^]C8V/.:S'.8S&M:V-2A+5KE+TY.4J<M=:<"`#&
|
||||
M:VN<``#&I5J4M<ZU.1@Y.3FE4BD8&`B4>SE[8S$8$`B4<SDQ,3&]G$JM(1#>
|
||||
MWMX`,7N]E$H0"`",:S$`*7LI*2FEC%K6UM:UC$+.SL[G[_?&QL:]I5J$.2DI
|
||||
M8YQSG+V]M9Q:A+7.I5K_]]9K8U+_[]9C4BEC2BD`.83OQF,`,82<>SF<A%J4
|
||||
M<S&ME%I[<VNMC%J4E)2MQM[W___W]_]">ZU"2DJ]QL9SG,;6Y^]"<ZV,C(Q"
|
||||
M0DKO]_?O[_?.SL;GE$K6C(S_WFM".1AS:U(I(1!S6C'_UFM",1AS8U+_SFOG
|
||||
MO5I20B'.I5)K4BGGM5KWSF.$<U+WQF-:6EJUG%HY0DK&6BFUE%H(2I124E*U
|
||||
MSMXA6IP`2HS_______\Q:Z64:RD`0HQ*>ZU*2DI[G,;6M6/>Y^]C6E+W]_?W
|
||||
M]_?6K6-"0D+>K:WGO6/O[^\Y,1CGM6/>M5I[<U(Q*1"4E'M*.1A[:U(Q(1"4
|
||||
MC'M:2B'6K5(I(0AS6BGOO5I:0B'_UF/6I5*,>U+_SF/_QF-K4B&$K<X8&!C_
|
||||
M[W/&UN<06I3_YW.]G%H04I2U2B$0$!"]SMZ]O;TY<Z4(2HQ24DHY:Z4("`A2
|
||||
M2DHA4I2UM;7>M6,`0H24@#^D````V'123E/_________B/]L2?__=/______
|
||||
M__________________________________________\,____________>?__
|
||||
M____________________________________________________________
|
||||
M______________________]=____________________________________
|
||||
M`/______________"/__1/______________________________________
|
||||
M______________________]Q/IU@```%O4E$051XVI56BU\411P?R[OL84;:
|
||||
MBJ!1!%F("40&5*<9<D0>:1)04"+>R<,2?*&'TNHY-$+I(O&0&SHDO33`\Y5'
|
||||
M*3I;1H>)G/GH_IU^,[MWMQCVT>_-SN[.?O>[O_D]9@X5<^P10,6T>R+QU92`
|
||||
M->!#Q5FQ992P$48D&`>PFU>(!.,1OAOU4`^J\*7(5NQ&=">E%8PQ`GQ.KQ@;
|
||||
M8\3BUMX5`T0'8SXQW%G5"\.5+7O]?D*&26#H6_XE&Z5;=M!;E>L.L^,CF$FS
|
||||
M)*-()6%$?$03"6-/%*O<*$RFC+.U;\;P80=UA"BB#"EY*LK#"(EACX?2NO<I
|
||||
M?2I@)FROZ=S>9O^G,/QW=A;M]X((T[_)9EB$MFU-V1(8/D38LAP8FVXY:_SD
|
||||
M6C)P<R%AZ9(<8QQFJB:#28QA.A%4LJG@BW%S<CWEC=8#-$]NS`U8#_Y,AGS6
|
||||
MU*1J%[F8&\C%87+<?+IC.>V+`T?N&J0K0'EUTL=*TL%<%2.2ES%T!@70']AW
|
||||
M09#!(T<<-$A?MC7NBII!##V_>,1B$3FPP-$8'RJA=#RHVVP^W0'N-;=O>Y:[
|
||||
M>.D'F#5)TBQ-F?;SUATJH_0Z&N2!VP0)0;I.C.0`E[PH621)TFV>PAO`.4B8
|
||||
M8M9M:9+T"99FMF5.0MM+?K_=;O>+9H=K?K+[6[YP&_)CJD0QH-3M-L3*$+0I
|
||||
M0+Z_#YEH:2FR33\34ALFB\B%`TA9BREM?[.B-*=:K1FYPV2HVE3-=/+N(S1^
|
||||
M`B+C\531):CT+F7X5A)V[?_5)5_RR<BE6/.KD\-D7B[0JFCY;'J59E)*9(1D
|
||||
MUP%S*KMT64;G7,/)U?DX3)YH6!`ZUIU5[Z#>(LT,7^LW&Q1E`UOMP\W*A@-I
|
||||
MA<UGR$K+.YS<O;.LKJ^L<;9GIS<Z05%/>G+P&QF"^!.?8(^#-YY08==AX0_-
|
||||
M$_R&88CX3.&-G@0:O`9GSS3HO$`^D<,)^VX[N8>Q-`^X%LOCFNOZZVCL6Q/9
|
||||
MQVQ@\]T;8,8G3@R:[;CF"B$8TJ@)TO,%W<^-H%=/RSQSZ5W4QLW`.6"#<A1O
|
||||
M.L0M!K;%LK3V?A'$<[!R&SN_=`X(.T`W'=?>/]R,J`P/Z-/$;Z<;PGT/654U
|
||||
M[_%#!0A_"/(K;?<@TV[(9KL`3_!?W%-6RG]121X<OOPGW>X'%F8/#E_MA8<1
|
||||
M5B\J/$H7546!EZ%3!%3MGJF**@YPGE%XP9UR>+O[3BP7*>DM$^B#!-B<6$R+
|
||||
MIG%A?#DI)<WJVDA2/R0!;$T=,)G.H#S3P&L([<=R,D+Y@6J4C"%Z3QLM_MPQ
|
||||
M"OU6SS'HRVU9#0UQGN#S=/#61XDGKUXOTM8GW(Q:,%%=B,.E$.)'PUC.0XL6
|
||||
MMYK0HI1D79A,$B[IF>#"56!E?4*PA,9[KL%Z>E*LO;PB*Q@Q(=>P:W$KL:8H
|
||||
MF"59%8);T&4NW)J&4-HIE!Q8B8;R\O+!%6>?^"KBX_(UL;0_U.M83K-M=72^
|
||||
MK2>[D0YV>2.;+]]_B$K"64C"RY6X)+R@F"HN&?&]Q]?FQU[7A!N#":.>K;MY
|
||||
MW\>KM:[3%DM+O='@A9<";</0.WWS()&]DQ%YAH57GS3S1STKYCL\H3CZNR/D
|
||||
M&1?WXZ'.+<:L@%>QN>-46%/MN%*SCH2%88>=AP5EAL15866)IEMOU7/03U1E
|
||||
MT;C9(!E;U7NC5#S8_*CXDZ*NW^9TCHUHPC5S#I%37>UCNO!26-%F-6&9R\+O
|
||||
MS4EY/-X)"PR-#S;0T:`CX9KCST%:M&))8AOJXC[F&2IORM&%E9M'?V"XH_V\
|
||||
M9N\S[PH[>8/?7RLG%TB]-G/AUMUS1[5!;]&J:.7AM3F'0=@,%7$^9ZT\<GI.
|
||||
M#=9=C+^3N#8XX0W\D)7'A<<6+H.=]NOU`PPO.^X\NN^?:"2)/)U;FRZ3AROI
|
||||
MBO!F86@CQ/#/`I[)3>F8_R&*%$B1M_C&_V/[]L\*"PH+"@H+"_DA4!`Y%T2?
|
||||
=09^18?I-$_X7HLFJ[CL9`)L`````245.1*Y"8((`
|
||||
`
|
||||
end
|
Loading…
Reference in New Issue
Block a user