pkgsrc/mk/bulk/post-build

502 lines
12 KiB
Text
Raw Normal View History

2000-09-16 00:05:46 +02:00
#!/usr/pkg/bin/perl
# $NetBSD: post-build,v 1.31 2004/02/05 23:53:16 grant Exp $
2000-09-16 00:05:46 +02:00
#
# Collect stuff after a pkg bulk build
#
# (c) 2000 Hubert Feyrer, All Rights Reserved.
#
use File::Basename;
# Where config vars are stored (/bin/sh syntax)
if (-f $ENV{"BULK_BUILD_CONF"}) {
$BULK_BUILD_CONF=$ENV{"BULK_BUILD_CONF"};
2000-09-16 00:05:46 +02:00
} else {
$BULK_BUILD_CONF=dirname("$0")."/build.conf";
2000-09-16 00:05:46 +02:00
}
# Dig given variable out of config file, and set it
sub getconf {
local($var)=@_;
local($val);
2000-09-16 00:05:46 +02:00
chomp($val=`. ./$BULK_BUILD_CONF ; echo \$$var`);
eval "\$$var=\"$val\";";
2000-09-16 00:05:46 +02:00
}
getconf("ADMINSIG"); # "-Your Name"
2000-09-16 00:05:46 +02:00
getconf("FTPURL"); # "pub/NetBSD/pkgstat/`date +%Y%m%d.%H%M`"
getconf("FTP"); # "/disk1/ftp/${FTPURL}"
2000-09-17 23:51:09 +02:00
getconf("FTPHOST"); # ftp://ftp.machi.ne/
2000-09-16 00:05:46 +02:00
getconf("REPORT"); # "broken.html"
getconf("USR_PKGSRC"); # "/usr/pkgsrc"
getconf("osrev"); # `uname -r`
getconf("arch"); # `uname -m`
$enddate=localtime(time());
This commit incorporates several speed improvements which have been tested over several bulk builds on an alpha: - At the start of a bulk build, 4 files are created to allow fast lookup of various dependency tree things. These files are .index == maps package name (foo-2.3) to directory (bar/foo) .dependstree == contains the complete pkgsrc dependency tree in a tsort(1) compatible format. .depends == contains 1 line per package and lists all the build depends for the package. .supports == contains 1 line per package and lists all packages which depend on this package. - When a package fails to build, the list of all packages which depend upon it is read from .supports. Each of those packages is immediately marked as broken. This prevents us from trying to build those packages which can have significant overhead if lots of other depends are installed before the system notices the broken one. In addition, the post-build postprocessing will now indicate that a package is 'truely broken' (ie, bad PLIST, failed compilation) vs. a package which is broken because it depends on a failed package. This assists in determining where to focus our efforts in fixing broken packages. - In the old approach, all packages are removed after each one is built. The purpose was to a) conserve disk space, b) verify that all required dependencies are in fact listed, and c) prevent conflicts. The problem was that often times several packages in a row have similar depends. For example we might want to build several perl packages in a row. In the old approach, we would install perl, build the pkg, deinstall perl and continue with the next one. In the new approach, when it is decided that a pkg is out of date and should be rebuilt, the .depends file is used to obtain a list of pkgs we require. Then and pkgs which are no longer needed are removed. This helps to minimize the total number of pkg_add/pkg_delete's in a bulk build. - Since the order of the build is controlled by the depends tree, all depends for a given package will have been built by the time the pkg in question needs them. If any of the depends failed to build, then the pkg which needs the failed one will have been marked as broken. Given this, the complete depends list for a pkg is read from .depends and the depends installed via pkg_add rather than relying on recursive make calls to install the depends. - while here, fix a few minor bugs x - don't leave .make log files around when the build succeeds x - make sure we refer to the correct report file in the email x - use '.order' for the build order file instead of '.l' x - use 'grep -c' instead of 'grep | wc -l'
2001-02-01 09:47:29 +01:00
$reportf=basename($REPORT);
2000-09-16 00:05:46 +02:00
chomp($os=`uname -s`);
# extract the name of the files used for the build log and broken build log.
# these have defaults set by bsd.bulk-pkg.mk and may be overridden in /etc/mk.conf
chomp($BROKENFILE=`( cd $USR_PKGSRC/pkgtools/pkglint ; $ENV{"BMAKE"} show-var VARNAME=BROKENFILE )`);
2000-09-16 00:05:46 +02:00
# also extract the names of the cache files used during the bulk build. We'll save a copy of
# those to help debug if the build messed up.
chomp($DEPENDSTREEFILE=`( cd $USR_PKGSRC/pkgtools/pkglint ; $ENV{"BMAKE"} show-var VARNAME=DEPENDSTREEFILE )`);
chomp($DEPENDSFILE=`( cd $USR_PKGSRC/pkgtools/pkglint ; $ENV{"BMAKE"} show-var VARNAME=DEPENDSFILE )`);
chomp($SUPPORTSFILE=`( cd $USR_PKGSRC/pkgtools/pkglint ; $ENV{"BMAKE"} show-var VARNAME=SUPPORTSFILE )`);
chomp($INDEXFILE=`( cd $USR_PKGSRC/pkgtools/pkglint ; $ENV{"BMAKE"} show-var VARNAME=INDEXFILE )`);
chomp($ORDERFILE=`( cd $USR_PKGSRC/pkgtools/pkglint ; $ENV{"BMAKE"} show-var VARNAME=ORDERFILE )`);
chomp($STARTFILE=`( cd $USR_PKGSRC/pkgtools/pkglint ; $ENV{"BMAKE"} show-var VARNAME=STARTFILE )`);
chomp($LOCALBASE=`( cd $USR_PKGSRC/pkgtools/pkglint ; $ENV{"BMAKE"} show-var VARNAME=LOCALBASE )`);
chomp($X11BASE=`( cd $USR_PKGSRC/pkgtools/pkglint ; $ENV{"BMAKE"} show-var VARNAME=X11BASE )`);
chomp($FIND=`( cd $USR_PKGSRC/pkgtools/pkglint ; $ENV{"BMAKE"} show-var VARNAME=FIND )`);
$dtfile=basename($DEPENDSTREEFILE);
$depfile=basename($DEPENDSFILE);
$supfile=basename($SUPPORTSFILE);
$indfile=basename($INDEXFILE);
$ordfile=basename($ORDERFILE);
$startfile=basename($STARTFILE);
$startdate = (stat($STARTFILE))[9];
if ($startdate == 0) {
$startdate = "unknown";
} else {
$startdate = localtime($startdate)."";
}
$verbose=1;
2000-09-16 00:05:46 +02:00
$report_head = <<EOF;
Package Breaks Last commit Maintainer
-------------------------------------------------------------------------
EOF
$report_form = <<EOF;
@<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<< @<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<
$pkg $nbrokenby $who $maintainer
EOF
2000-09-16 00:05:46 +02:00
system("mkdir -p ${FTP}");
# Copy over the output from the build process
chdir($USR_PKGSRC);
system("tar plcf - $BROKENFILE */*/$BROKENFILE | ( cd ${FTP} ; tar plxf - )");
2000-09-16 00:05:46 +02:00
# Copy over the cache files used during the build
foreach my $f ($DEPENDSTREEFILE, $DEPENDSFILE, $SUPPORTSFILE, $INDEXFILE, $ORDERFILE) {
system("cp ${f} ${FTP}") if -f ${f};
2000-09-16 00:05:46 +02:00
}
chdir($FTP);
writeReport();
2000-09-16 00:05:46 +02:00
#
# Adjust "last" symlink
#
{
local($base, $dir) = $FTP=~m|^(.*)/([^/]*)$|;
unlink("$base/last");
symlink($dir, "$base/last");
}
#
# Generate leftovers-${arch}.html: files not deleted
# Leftover files are copied to leftovers-${arch} dir, and linked from
# leftovers-${arch}.html
#
{
chdir($FTP);
2000-09-16 00:05:46 +02:00
system("mkdir -p leftovers-${arch}");
# Find files since last build:
$leftovers_txt = "leftovers-${arch}.txt";
$leftovers_html = "leftovers-${arch}.html";
system("${FIND} ${LOCALBASE} -newer ${USR_PKGSRC}/${startfile} -type f -print >>$leftovers_txt");
system("${FIND} ${X11BASE} -newer ${USR_PKGSRC}/${startfile} -type f -print >>$leftovers_txt");
2000-09-16 00:05:46 +02:00
# Strip perl-files:
{
local $/;
undef $/;
$perlfiles = `pkg_info -qL perl`;
}
($perlfiles_pattern = $perlfiles) =~ s/\n/|/g;
$perlfiles_pattern =~ s/|$//;
open (LEFT, $leftovers_txt) or die "can't read $leftovers_txt: $!";
@left = <LEFT>;
close (LEFT);
@leftovers = grep(!/^(${perlfiles_pattern})$/, @left);
2000-09-16 00:05:46 +02:00
open (LEFT, ">$leftovers_txt") or die "can't write $leftovers_txt: $!";
print LEFT @leftovers;
close (LEFT);
if (scalar(@leftovers)) {
# Store leftovers, for easier identification:
system("tar plcf - `cat $leftovers_txt` | ( cd leftovers-${arch} ; tar plxf - )");
}
2000-09-16 00:05:46 +02:00
# Add links to leftover list:
open (OUT, "> $leftovers_html")
or die "can't write $leftovers_html";
print OUT <<EOOUT;
<html>
<body>
<pre>
2000-09-16 00:05:46 +02:00
EOOUT
foreach (@leftovers) {
chomp;
print OUT "<a href=\"${FTPHOST}/${FTPURL}/leftovers-${arch}$_\">$_</a>\n";
2000-09-16 00:05:46 +02:00
}
print OUT <<EOOUT2;
</pre>
</body>
</html>
2000-09-16 00:05:46 +02:00
EOOUT2
close(OUT);
}
# print the result of a single broken package
sub pkgResult {
my ($pinfo, $state) = @_;
my $pkg = $pinfo->{pkg};
my $nbrokenby = $pinfo->{nbrokenby};
my $nerrors = $pinfo->{nerrors};
@idents = `${FIND} ${USR_PKGSRC}/${pkg} -type f -print | xargs grep \\\$NetBSD`;
$datetime = "";
$who = "nobody";
$file = "";
$ver = "";
foreach $ident (@idents) {
$ident =~ /\$[N]etBSD: ([^ ]*),v ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) Exp \$/;
if ("$3 $4" gt $datetime) {
$datetime = "$3 $4";
$who = $5;
$file = $1;
$ver = $1;
}
}
$maintainer = `grep ^MAINTAINER $USR_PKGSRC/$pkg/Makefile`;
$maintainer =~ s/MAINTAINER=[ \t]*//;
$maintainer =~ s/</&lt;/g;
$maintainer =~ s/>/&gt;/g;
chomp($maintainer);
(my $state_style = $state) =~ s/ //g;
$nbrokenby_html = '<td>&nbsp;</td>';
$nbrokenby_html =
'<td align="right" class="pkg-'.$state_style.'">'.$nbrokenby.'</td>'
if $nbrokenby > 0;
if ($pinfo->{nerrors} != 0 && $verbose) {
print swrite($report_form, $pkg, $nbrokenby > 0 ? $nbrokenby : "", $who, $maintainer);
}
return <<EOHTML;
<tr>
<td><a class="pkg-$state_style" href="$pinfo->{bf}" title="build log for $pkg">$pkg</a></td>
$nbrokenby_html
<td>$who</td>
<td>$file</td>
<td>$maintainer</td>
</tr>
EOHTML
}
# write the build report
sub writeReport {
my $broken = getBroken();
$nbroken = scalar(@{$broken->{"broken"}});
$nbrokendep = scalar(@{$broken->{"broken depends"}});
$nunpackaged = scalar(@{$broken->{"not packaged"}});
$nbrokentot = $nbroken + $nbrokendep;
$ntotal = $nunpackaged + $nbroken + $nbrokendep;
if ($verbose) {
print <<EOF;
pkgsrc bulk build results
$os $osrev/$arch
Summary:
EOF
my $summary_form = <<EOF;
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
EOF
print swrite($summary_form, "Build started:", $startdate);
print swrite($summary_form, "Build ended:", $enddate);
print swrite($summary_form);
print swrite($summary_form, "Packages really broken:", $nbroken);
print swrite($summary_form, "Pkgs broken due to them:", $nbrokendep);
print swrite($summary_form, "Total broken:", $nbrokentot);
print swrite($summary_form, "Not packaged:", $nunpackaged);
print swrite($summary_form, "Total:", $ntotal);
print <<EOF;
Packages not listed here resulted in a binary package. The build
report, including logs of failed/not-packaged is available from:
$FTPHOST/$FTPURL/$reportf
EOF
}
open(HTML,">$REPORT") or die "Can't write $REPORT: $!\n";
print HTML <<EOHTML;
<html>
<head>
<title>$os $osrev/$arch bulk package build</title>
<style type="text/css">
<!--
body {
Font-Family: Tahoma, Verdana, sans-serif;
Line-Height: 1.3em;
Text-Decoration: None;
Color: black;
Background-Color: white;
Border-Width: 0;
}
table {
Border-Width: 0;
}
table td {
Font-Family: Tahoma, Verdana, sans-serif;
line-height: 1em;
}
a:link {
Color: #3535c5;
}
a:visited {
Color: #700080;
}
a:hover {
Color: #6565e5;
Text-Decoration: underline;
}
tr {
Vertical-Align: top;
}
td {
Vertical-Align: top;
}
h1 {
Font-Size: 3.5ex;
Line-Height: 1em;
Color: #000066;
}
h2 {
Font-Size: 2.5ex;
Line-Height: 1em;
Color: #660000;
}
h3 {
Font-Size: 2ex;
Color: #660066;
}
h4 {
Font-Size: 1.8ex;
Color: #006600;
}
tt.filename {
Line-Height: 1.3em;
Color: #AA0000;
}
.pkgname {
Font-Family: Arial, Helvetica, Courier, fixed;
Font-Style: Italic;
Text-Decoration: none;
Line-Height: 1.3em;
}
.pkg-broken {
Color: red;
}
.pkg-brokendepends {
Color: orange;
}
.pkg-notpackaged {
Color: blue;
}
-->
</style>
</head>
<body bgcolor="white" text="black" link="#3535c5" vlink="#700080"
alink="#3535c5">
<h1>pkgsrc bulk build results</h1>
<h2>$os $osrev/$arch</h2>
<h3>Summary</h3>
<table>
<tr>
<td>Build started: <td align="right">$startdate</td>
</tr>
<tr>
<td>Build ended: <td align="right">$enddate</td>
</tr>
<tr>
<td>&nbsp;</td> <td>&nbsp;</td>
</tr>
<tr class="pkg-broken">
<td>Packages really broken: <td align="right">$nbroken</td>
</tr>
<tr class="pkg-brokendepends">
<td>Packages broken due to them: <td align="right">$nbrokendep</td>
</tr>
<tr>
<td>Total broken: <td align="right">$nbrokentot</td>
</tr>
<tr class="pkg-notpackaged">
<td>Not packaged: <td align="right">$nunpackaged</td>
</tr>
<tr>
<td>Total: <td align="right">$ntotal</td>
</tr>
</table>
<p>
Packages not listed here resulted in a <a
href="../../packages/" title="binary packages for $os $osrev/$arch">binary
package</a>. Results of failed packages are available below.
</p>
<p>
Files leftover from the build (because of broken PLISTs, etc.) can be
found in <a href="leftovers-${arch}.html" title="leftover files">this
list</a>.
</p>
EOHTML
my %state_head = (
"broken" => "Broken packages",
"broken depends" => "Broken dependencies",
"not packaged" => "Not packaged"
);
foreach my $state ("broken", "broken depends", "not packaged") {
next unless scalar(@{$broken->{$state}});
print HTML <<EOHTML;
<h2>$state_head{$state}</h2>
<table width="100%">
<tr align="left">
<th width="30%">Package</th>
<th>Breaks</th>
<th>Last commit by</th>
<th>File touched last</th>
<th>Maintainer</th>
</tr>
EOHTML
if ($verbose && $state ne "not packaged") {
print "\n\n$state_head{$state}\n\n";
print $report_head;
}
foreach my $pinfo (@{$broken->{$state}}) {
print HTML pkgResult($pinfo, $state);
}
print HTML "</table>\n";
}
print HTML <<EOHTML;
<hr>
<p>
The following cache files were used during the build:
</p>
<ul>
<li>The <a href="$dtfile">depends tree file</a>.</li>
<li>The <a href="$depfile">depends file</a>.</li>
<li>The <a href="$supfile">supports file</a>.</li>
<li>The <a href="$indfile">index file</a>.</li>
<li>The <a href="$ordfile">build order file</a>.</li>
</ul>
<hr>
<p>
<ul>
<!-- <li>View the <a href="$prog">progress</a> of the build. -->
<!-- <li>See the list of <a href="../index.html">all log files</a>. -->
<li>Visit the <a href="http://www.NetBSD.org">NetBSD web site</a>.
<li>Learn more about
<a href="http://www.NetBSD.org/Documentation/software/packages.html">
The NetBSD Packages Collection</a>.
</ul>
</p>
</body>
</html>
EOHTML
close(HTML);
if ($verbose) {
print "\n\n$ADMINSIG\n\n";
print "[* This message was created automatically! *]\n";
}
}
# get and sort the broken packages
sub getBroken {
open (BF, $BROKENFILE) or die "can't open $BROKENFILE: $!";
my @in = <BF>;
close (BF);
my $res = {};
foreach (@in) {
chomp;
my ($nerrors, $bf, $nbrokenby) = split;
(my $pkg = $bf) =~ s,/$BROKENFILE,,;
my %tmp = (
bf => $bf,
pkg => $pkg,
nbrokenby => $nbrokenby,
nerrors => $nerrors,
);
if ($nerrors > 0) {
push(@{$res->{"broken"}}, \%tmp);
} elsif ($nerrors == -1) {
push(@{$res->{"broken depends"}}, \%tmp);
} else {
push(@{$res->{"not packaged"}}, \%tmp);
}
}
# sort pkgs in each state
foreach my $state ("broken", "broken depends", "not packaged") {
$res->{$state} = [ sort { $a->{pkg} cmp $b->{pkg} } @{$res->{$state}} ];
}
return $res;
}
sub swrite {
my $format = shift;
$^A = "";
formline($format, @_);
$^A =~ s/\n\n/\n/;
return $^A;
2000-09-16 00:05:46 +02:00
}