Commit 9097e59c authored by Michael Pyne's avatar Michael Pyne

Add persistent data store for kdesvn-build. Initially the only things tracked are the last

successful build revision, last successful install revision, and the number of consecutive
module failures.

In addition the user is warned at program end of all modules that have failed to build for more
than 3 consecutive build attempts for the module to take a closer look at the issue.

If there's other cool things that would be useful for the script to track I'm all ears.  The
last-successful-rev stuff was initially for tracking if a module should be rebuilt or not.  But
if required library dependencies have changed in the interim (i.e. qt-copy or kdelibs) then we
should allow CMake to do its things no matter what so I will not actually implement that feature
after all.  But it's still useful to track IMO.


svn path=/trunk/KDE/kdesdk/scripts/kdesvn-build; revision=841748
parent 70f77a24
......@@ -266,9 +266,13 @@ use Fcntl; # For sysopen constants
use POSIX qw(strftime :sys_wait_h);
use File::Find; # For our lndir reimplementation.
use File::Basename;
use File::Spec;
use Sys::Hostname;
use IO::Handle;
use IO::File;
use Errno qw(:POSIX);
use Data::Dumper;
use 5.008_000; # Require Perl 5.8.0
# Debugging level constants.
use constant {
......@@ -2852,7 +2856,10 @@ sub read_options
if (open CONFIG, "<$file")
$success = 1;
$rcfile = $file;
# rel2abs used since path for rcfile is used later in execution
# when the cwd may have changed so we need to expand path here.
$rcfile = File::Spec->rel2abs($file);
......@@ -3108,6 +3115,24 @@ sub output_failed_module_lists()
my @failures = @{$fail_lists{$type}};
output_failed_module_list("failed to $type", @failures);
# See if any modules fail continuously and warn specifically for them.
my $persistent_opt = sub {
my $mod = shift;
return ((exists $package_opts{$mod}{'persistent-options'}{'failure-count'}) and
(int $package_opts{$mod}{'persistent-options'}{'failure-count'} > 3));
my @super_fail = grep { &{$persistent_opt}($_) }(keys %package_opts);
if (@super_fail)
warning "\nThe following modules have failed to build 3 or more times in a row:";
warning "\tr[b[$_]" foreach @super_fail;
warning "\nThere is probably a local error causing this kind of consistent failure, it";
warning "is recommended to verify no issues on the system.\n";
# This subroutine extract the value from options of the form --option=value,
......@@ -3179,6 +3204,144 @@ sub set_option
$package_opts{$module}{$option} = $value;
# Sets a "persistent" option which will be read in for a module when kdesvn-build starts
# up and written back out at (normal) program exit.
# First parameter is the module to set the option for, or 'global'.
# Second parameter is the name of the value to set (i.e. key)
# Third parameter is the value to store, which must be a scalar.
sub set_persistent_option
my ($module, $key, $value) = @_;
# A reference to a hash is used in the normal package_opts hash table with the
# special key persistent-options.
if (not exists $package_opts{$module}{'persistent-options'})
$package_opts{$module}{'persistent-options'} = { };
$package_opts{$module}{'persistent-options'}{$key} = $value;
# Returns the value of a "persistent" option (normally read in as part of startup), or
# undef if there is no value stored.
# First parameter is the module to get the option for, or 'global' if not for a module.
# Note that unlike set_option/get_option, no inheritance is done at this point so if
# an option is present globally but not for a module you must check both if that's what
# you want.
# Second paramter is the name of the value to retrieve (i.e. the key)
# A scalar is always the return value.
sub get_persistent_option
my ($module, $key) = @_;
# Don't auto-vivify the value if it's not there.
return undef unless exists $package_opts{$module}{'persistent-options'};
return undef unless exists $package_opts{$module}{'persistent-options'}{$key};
return $package_opts{$module}{'persistent-options'}{$key};
# Writes out the persistent options to the file .kdesvn-build-data. Note: If
# the file already exists, it is only overwritten if the file contains
# "AUTOGENERATED BY kdesvn-build" in the first line in case someone actually
# used this file name before this feature was added.
# The directory used is the same directory that contains the rc file in use.
sub write_persistent_options
my $dir = dirname($rcfile);
my $fh = IO::File->new("> $dir/.kdesvn-build-data");
if (not defined $fh)
error "Unable to save persistent module data: b[r[$!]";
print $fh "# AUTOGENERATED BY kdesvn-build $versionNum\n";
# Modules with persistent options
my @names = grep { exists $package_opts{$_}{'persistent-options'} } keys %package_opts;
# References to the persistent hash tables.
my @refs = map { $package_opts{$_}{'persistent-options'} } @names;
my %output;
# This is a hash slice, it basically does $output{$names[i]} = $refs[i] for
# all entries in the lists.
@output{@names} = @refs;
$Data::Dumper::Indent = 1;
print $fh Data::Dumper->Dump([\%output], ["persistent_options"]);
# Reads in all persistent options from the file where they are kept
# (.kdesvn-build-data) for use in the program.
# The directory used is the same directory that contains the rc file in use.
sub read_persistent_options
my $dir = dirname($rcfile);
my $fh = IO::File->new("<$dir/.kdesvn-build-data");
return unless defined $fh;
my $persistent_data;
local $/ = undef; # Read in whole file with <> operator.
$persistent_data = <$fh>;
# $persistent_data should be Perl code which, when evaluated will give us
# a hash called persistent-options which we can then merge into our
# package_opts.
my $persistent_options = eval "my $persistent_data";
if ($@)
# Failed.
error "Failed to read persistent module data: r[b[$@]";
for my $key (keys %{$persistent_options})
$package_opts{$key}{'persistent-options'} = ${$persistent_options}{$key};
# Returns a string containing the current on-disk revision number of the
# given Subversion repository, or undef if there was an error.
# First parameter is the name of the module to examine.
sub current_module_revision
my $module = shift;
my $srcdir = get_fullpath($module, 'source');
open SVN_INFO, "-|", "svn", "info", "--non-interactive", $srcdir or do {
warning "\tUnable to determine $module revision, is svn installed?";
return undef;
while (<SVN_INFO>)
next unless /^Revision:/;
my ($rev) = /^Revision:\s*(\d+)/;
close SVN_INFO;
return $rev;
close SVN_INFO;
return undef;
# Subroutine to recursively deep copy (form a completely independent clone)
# of the modules given for module A (first parameter) to module B (second
# parameter).
......@@ -5471,6 +5634,14 @@ EOF
$svn_status{$buffer} = 'failed';
push @{$fail_lists{'update'}}, $buffer;
error "\tUnable to update r[$buffer], build canceled.";
# Increment failed count to track when to start bugging the
# user to fix stuff.
my $fail_count = get_persistent_option($buffer, 'failure-count');
$fail_count = 0 unless defined $fail_count;
set_persistent_option($buffer, 'failure-count', $fail_count);
......@@ -5480,6 +5651,8 @@ EOF
my $elapsed = prettify_seconds(time - $start_time);
print STATUS_FILE "$module: Succeeded after $elapsed.\n" if $outfile;
set_persistent_option($module, 'last-build-rev', current_module_revision($module));
set_persistent_option($module, 'failure-count', 0);
info "\tOverall time for g[$module] was g[$elapsed].";
push @build_done, $module;
......@@ -5492,6 +5665,14 @@ EOF
info "\tOverall time for r[$module] was g[$elapsed].";
push @{$fail_lists{'build'}}, $module;
# Increment failed count to track when to start bugging the
# user to fix stuff.
my $fail_count = get_persistent_option($module, 'failure-count');
$fail_count = 0 unless defined $fail_count;
set_persistent_option($module, 'failure-count', $fail_count);
if (get_option($module, 'stop-on-failure'))
note "\n$module didn't build, stopping here.";
......@@ -5572,6 +5753,8 @@ sub finish
my $logdir = get_log_dir('global');
$exitcode = 0 unless $exitcode;
exit $exitcode if pretending; # Abort early when pretending.
......@@ -5737,6 +5920,8 @@ sub handle_install
next if $result != 0; # Don't delete anything if the build failed.
set_persistent_option($module, 'last-install-rev', current_module_revision($module));
my $remove_setting = get_option($module, 'remove-after-install');
# Possibly remove the srcdir and builddir after install for users with
......@@ -6283,6 +6468,10 @@ eval
my $time = localtime;
info "Script started processing at g[$time]" unless pretending;
# Read in persistent data for i.e. tracking the revision of the last
# successful svn update or build.
# Coverity doesn't respond to email as often as we'd like, but we can
# usually work around that here.
if (exists $ENV{'COVERITY_RUN'} )
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment