summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2019-03-21 06:55:38 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2019-03-21 09:07:28 (GMT)
commita9845d6973ca7271437a6fbc659f48cd1100add3 (patch) (side-by-side diff)
tree2a69fe5d036115192002c719f9397cac5a5ecef5
parenta297c865dd4611c4fd862e59c70ba1b72a142035 (diff)
downloadslackbuilder-a9845d6973ca7271437a6fbc659f48cd1100add3.tar.gz
slackbuilder-a9845d6973ca7271437a6fbc659f48cd1100add3.tar.bz2
Switch to Log::Log4perl for logging
* Makefile.PL: Add Log::Log4perl and Log::Dispatch to the list of prerequisites. * lib/SlackBuild/Config.pm (core.logging): New statement. * lib/SlackBuild/Archive.pm (logger): New method. Use it for diagnostics. * lib/SlackBuild/Rc.pm: Likewise. * lib/SlackBuild/URI.pm: Likewise, * lib/SlackBuilder.pm: Use Log::Log4perl. Rewrite the real-time parser for the stdout and stderr obtained from the builder. * slackbuilder: Remove unused functions.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--Makefile.PL2
-rw-r--r--lib/SlackBuild/Archive.pm10
-rw-r--r--lib/SlackBuild/Config.pm3
-rw-r--r--lib/SlackBuild/Rc.pm5
-rw-r--r--lib/SlackBuild/URI.pm15
-rw-r--r--lib/SlackBuilder.pm241
-rwxr-xr-xslackbuilder11
7 files changed, 214 insertions, 73 deletions
diff --git a/Makefile.PL b/Makefile.PL
index 776890c..e92a8b5 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -26,6 +26,8 @@ WriteMakefile(NAME => 'slackbuilder',
'YAML' => '1.20',
'LWP::UserAgent' => '6.29',
'List::Regexp' => '1.03',
+ 'Log::Log4perl' => '1.48',
+ 'Log::Dispatch' => '2.67',
#Net::SBo
'POSIX' => 0,
'POSIX::Run::Capture' => 0,
diff --git a/lib/SlackBuild/Archive.pm b/lib/SlackBuild/Archive.pm
index 2f3663e..03fd17b 100644
--- a/lib/SlackBuild/Archive.pm
+++ b/lib/SlackBuild/Archive.pm
@@ -7,6 +7,7 @@ use SlackBuild::Info;
use File::Temp qw/ tempfile tempdir /;
use File::Basename;
use File::Spec;
+use Log::Log4perl;
use Carp;
*AUTOLOAD = \&SlackBuild::URI::AUTOLOAD;
@@ -86,21 +87,18 @@ sub info {
return $self->{_info} ||= new SlackBuild::Info;
}
-sub download_success {
- my $self = shift;
- return $self->{_last_success};
-}
-
sub download_status {
my $self = shift;
return $self->SUPER::download_status unless exists $self->{_last_status};
return $self->{_last_status};
}
+sub logger { shift->{_logger} //= Log::Log4perl::get_logger(__PACKAGE__) }
+
sub error {
my $self = shift;
- $self->{_last_success} = 0;
$self->{_last_status} = shift;
+ $self->logger->error($self->{_last_status});
return 0;
}
diff --git a/lib/SlackBuild/Config.pm b/lib/SlackBuild/Config.pm
index 0790c7d..2d9fbb2 100644
--- a/lib/SlackBuild/Config.pm
+++ b/lib/SlackBuild/Config.pm
@@ -40,8 +40,9 @@ sub check_dir {
1;
__DATA__
[core]
- image = STRING :mandatory
+ image = STRING :mandatory
verbose = NUMBER :mandatory 0
+ logging = STRING :mandatory /etc/slackbuilder/logging.conf
[dir]
root = STRING :check=check_dir :mandatory /srv/slackbuild
tmp = STRING :mandatory tmp
diff --git a/lib/SlackBuild/Rc.pm b/lib/SlackBuild/Rc.pm
index 022386a..c40ccc1 100644
--- a/lib/SlackBuild/Rc.pm
+++ b/lib/SlackBuild/Rc.pm
@@ -4,12 +4,15 @@ use warnings;
use Carp;
use SlackBuild::Registry::Record;
use SlackBuild::Registry::Pattern;
+use Log::Log4perl;
sub new {
my ($class, $builder) = @_;
return bless { _builder => $builder }, $class;
}
+sub logger { shift->{_logger} //= Log::Log4perl::get_logger(__PACKAGE__) }
+
sub builder { shift->{_builder} }
sub resolve {
@@ -39,7 +42,7 @@ sub code {
my ($self, $reg) = @_;
my ($pkglist, $unresolved) = $self->resolve($reg);
if (@$unresolved) {
- $self->builder->error("$_: package not resolved") for (@$unresolved);
+ $self->logger->error("$_: package not resolved") for (@$unresolved);
return;
}
my @code = ('#! /bin/sh',
diff --git a/lib/SlackBuild/URI.pm b/lib/SlackBuild/URI.pm
index 410a9ca..21d19f9 100644
--- a/lib/SlackBuild/URI.pm
+++ b/lib/SlackBuild/URI.pm
@@ -6,6 +6,7 @@ use Carp;
use LWP::UserAgent;
use File::Basename;
use File::Spec;
+use Log::Log4perl;
# use LWP::Protocol::https;
# use LWP::Protocol::file;
# use LWP::Protocol::ftp;
@@ -43,6 +44,11 @@ sub new {
return $self;
}
+sub logger {
+ my $self = shift;
+ return $self->{_logger} //= Log::Log4perl::get_logger(__PACKAGE__);
+}
+
sub clone {
my $self = shift;
return new SlackBuild::URI($self);
@@ -62,9 +68,9 @@ sub download {
my $dst = shift || basename($self->path);
my $scheme = $self->scheme;
require "LWP/Protocol/$scheme.pm";
- print "downloading $self\n";
+ $self->logger->info("downloading $self");
my $ua = LWP::UserAgent->new();
- $ua->agent('Slackbuilder/0.90');
+ $ua->agent('Slackbuilder/$SlackBuilder::VERSION');
my $response = $ua->get($self->as_string, ':content_file' => $dst);
$self->download_response($response);
return $response->is_success;
@@ -79,11 +85,6 @@ sub download_response {
return $self->{_response};
}
-sub download_success {
- my $self = shift;
- return $self->download_response->is_success;
-}
-
sub download_status {
my $self = shift;
return $self->download_response->status_line;
diff --git a/lib/SlackBuilder.pm b/lib/SlackBuilder.pm
index 2544b5f..924a847 100644
--- a/lib/SlackBuilder.pm
+++ b/lib/SlackBuilder.pm
@@ -13,6 +13,8 @@ use File::Temp qw/ tempfile tempdir /;
use File::Copy;
use POSIX::Run::Capture qw(:all);
use POSIX qw(:sys_wait_h strerror uname);
+use Log::Log4perl qw(:levels);
+use Carp;
use constant {
E_OK => 0,
@@ -35,15 +37,44 @@ sub new {
$self->{conf} = new SlackBuild::Config(
filename => $ENV{SLACKBUILDER_CONFIG} || '/etc/slackbuilder.conf');
+
+ Log::Log4perl::Layout::PatternLayout::add_global_cspec('N',
+ sub {
+ my ($layout, $message, $category, $priority, $caller_level) = @_;
+ my $pfx = "$0: $priority";
+ if ($priority eq 'DEBUG') {
+ $pfx .= ": $category";
+ if ($self->conf->tree->Core->Verbose->value > 1) {
+ my $caller_offset = Log::Log4perl::caller_depth_offset($caller_level);
+ my ($package,$filename,$line) = caller($caller_offset);
+ $pfx .= ": $filename:$line";
+ }
+ }
+ return $pfx;
+ });
+ $self->logger->level($INFO);
+ my $layout = new Log::Log4perl::Layout::PatternLayout("%N: %m%n");
+ my $appender = new Log::Log4perl::Appender('Log::Dispatch::Screen',
+ stderr => 1);
+ $appender->layout($layout);
+ $self->logger->add_appender($appender);
my $v;
- if ($v = delete $args{image}) {
- $self->conf->set(qw(core image), $v);
+ if (defined($v = $self->conf->tree->Core->Logging->value) && -f $v) {
+ Log::Log4perl::init($v);
}
+
if ($v = delete $args{verbose}) {
$self->conf->set(qw(core verbose), $v);
}
+ if ($self->conf->tree->Core->Verbose->value) {
+ $self->logger->level($DEBUG);
+ }
- croak "bad number of arguments" if keys(%args);
+ if ($v = delete $args{image}) {
+ $self->conf->set(qw(core image), $v);
+ }
+
+# croak "bad number of arguments" if keys(%args);
$self->clear;
@@ -62,21 +93,17 @@ sub ospkgdir {
File::Spec->catfile($self->pkgdir, $self->osversion, @_);
}
sub image { shift->conf->tree->Core->Image->value };
-sub verbose { shift->conf->tree->Core->Verbose->value };
sub arch { shift->{_arch} };
+sub logger { shift->{_logger} //= Log::Log4perl::get_logger('SlackBuild') }
+
sub error {
my ($self, $diag) = @_;
- push @{$self->{_error}}, $diag;
+ $self->logger->error($diag);
}
-sub errors {
- my $self = shift;
- if (wantarray) {
- ( @{$self->{_error}} );
- } else {
- @{$self->{_error}};
- }
+sub errors { # FIXME
+ shift->{_error_count};
}
sub errno {
@@ -95,7 +122,7 @@ sub is_success {
sub clear {
my $self = shift;
$self->{_errno} = E_OK;
- $self->{_error} = [];
+ $self->{_error_count} = 0;
delete $self->{_request};
delete $self->{_result};
}
@@ -318,7 +345,131 @@ sub _prepare {
return unless SlackBuild::Rc->new($self)->write($reg, $filename);
return 'rc';
}
-
+
+# Regex created using the following command:
+# (find / -type d -not -name '/' -mindepth 1 -maxdepth 1 -printf '%f\n';
+# echo '.';
+# echo 'install') | xargs regexp-opt --pcre
+my $file_name_rx = q{(?:b(?:in|oot)|dev|etc|home|install|l(?:ib(?:64)?|ost\+found)|m(?:edia|nt)|opt|proc|r(?:oot|un)|s(?:bin|rv|ys)|tmp|(?:us|va)r|\.)(?:/\w+)*};
+
+# Parser states:
+use constant {
+ ST_INIT => 0, # Initial state
+ # [expect OUT] "Creating Slackware package: foobar"
+ # goto ST_CREATING
+ ST_CREATING => 1, # [expect OUT] Empty line
+ # goto ST_LISTING
+ # [else] goto ST_INIT
+ ST_LISTING => 2, # [expect ERR] File name (matching $file_name_rx)
+ # remain in this state
+ # [else] goto ST_INIT
+ # [expect OUT] Empty line
+ # goto ST_CREATED
+ # [else] goto ST_INIT
+ ST_CREATED => 3 # [expect OUT] "Slackware package foo created"
+ # goto ST_INIT
+};
+
+# state([$newstate])
+# With argument - switch to that state.
+# Return current state.
+sub state {
+ my ($self, $newstate) = @_;
+ if (defined($newstate)) {
+ $self->logger->debug("going to $newstate");
+ $self->{_state} = $newstate;
+ }
+ return $self->{_state};
+}
+
+# Parsers for each particular state.
+# Each parser is named by the corresponding state, converted to lower case,
+# prefixed with underscore and suffixed by the channel name ('_err' or '_out').
+# Argument is the line of text obtained from that channel, without trailing
+# linefeed character.
+
+sub _st_init_out {
+ my ($self, $input) = @_;
+ if ($input =~ m{^Creating Slackware package:}) {
+ $self->logger->info($input);
+ $self->state(ST_CREATING);
+ }
+}
+
+sub _st_default_err {
+ my ($self, $input) = @_;
+ $self->logger->error($input);
+}
+
+sub _st_created_out {
+ my ($self, $input) = @_;
+ if ($input =~ m{^Slackware package /tmp/(.+?) created}) {
+ $self->file($1);
+ $self->logger->info($input);
+ } else {
+ $self->logger->error("unexpected output: $input");
+ }
+ $self->state(ST_INIT);
+}
+
+sub _st_creating_out {
+ my ($self, $input) = @_;
+ if ($input eq '') {
+ $self->state(ST_LISTING);
+ } else {
+ $self->state(ST_INIT);
+ }
+}
+
+sub _st_listing_err {
+ my ($self, $input) = @_;
+ if ($input =~ m{$file_name_rx}) {
+ $self->logger->debug("adding file $input");
+ } else {
+ $self->logger->error($input);
+ $self->state(ST_INIT);
+ }
+}
+
+sub _st_listing_out {
+ my ($self, $input) = @_;
+ if ($input eq '') {
+ $self->state(ST_CREATED);
+ } else {
+ $self->state(ST_INIT);
+ }
+}
+
+# Parser tables bring together parsers for each channel:
+
+my @parser_out = (
+ \&_st_init_out,
+ \&_st_creating_out,
+ \&_st_listing_out,
+ \&_st_created_out
+);
+
+my @parser_err = (
+ \&_st_default_err,
+ \&_st_default_err,
+ \&_st_listing_err,
+ \&_st_default_err
+);
+
+# Finally, parser functions to be called for each channel:
+
+sub parser_out {
+ my ($self, $line) = @_;
+ $self->logger->debug("OUT: $line");
+ $self->${\$parser_out[$self->state]}($line);
+}
+
+sub parser_err {
+ my ($self, $line) = @_;
+ $self->logger->debug("ERR: $line");
+ $self->${\$parser_err[$self->state]}($line);
+}
+
sub _build {
my $self = shift;
@@ -337,51 +488,47 @@ sub _build {
$rcfile,
$self->slackbuild_name);
- printf("building %s on %s version %s (%s)\n",
- $self->package_name,
- $self->os_release('NAME'),
- $self->os_release('VERSION'),
- $self->arch);
+ $self->logger->info(
+ sprintf("building %s on %s version %s (%s)\n",
+ $self->package_name,
+ $self->os_release('NAME'),
+ $self->os_release('VERSION'),
+ $self->arch));
open(my $logfd, '>', $self->_logfilename)
or do {
- $self->error("can't create log file " .
- $self->_logfilename .
- ": $!");
+ $self->logger->fatal("can't create log file " .
+ $self->_logfilename .
+ ": $!");
return $self->errno(E_FAIL);
};
-
- my $obj = new POSIX::Run::Capture(argv => \@args,
- stdout => sub {
- print $logfd 'OUT: ' . shift
- },
- stderr => sub {
- my $line = shift;
- chomp($line);
- $self->error($line);
- if ($self->verbose) {
- print STDERR "$line\n";
- }
- print $logfd "ERR: $line\n";
- });
+
+ $self->state(ST_INIT);
+ my $obj = new POSIX::Run::Capture(
+ argv => \@args,
+ stdout => sub {
+ my $line = shift;
+ print $logfd "OUT: $line";
+ chomp($line);
+ $self->parser_out($line);
+ },
+ stderr => sub {
+ my $line = shift;
+ print $logfd "ERR: $line";
+ chomp($line);
+ $self->parser_err($line);
+ });
+ if ($self->state != ST_INIT) {
+ $self->logger->error("parser left in inconsistent state");
+ }
$self->{_result}{docker} = $obj;
if ($obj->run) {
$self->_runcap_diag($obj);
} else {
- $self->error("can't run docker: ".strerror($obj->errno));
+ $self->logger->fatal("can't run docker: ".strerror($obj->errno));
return $self->errno(E_EXEC);
}
-# $self->errno(E_FAIL) if $self->errors;
-
- $obj->rewind(SD_STDOUT);
- while (my $s = $obj->next_line(SD_STDOUT)) {
- chomp($s);
- if ($s =~ m{^Slackware package /tmp/(.+?) created}) {
- $self->file($1);
- }
- }
return $self->errno(E_OK);
}
-
1;
diff --git a/slackbuilder b/slackbuilder
index 9ad2722..36f7bdb 100755
--- a/slackbuilder
+++ b/slackbuilder
@@ -27,14 +27,6 @@ sub abend {
print STDERR "@_\n";
exit $code;
}
-
-sub error {
- my $msg = shift;
- local %_ = @_;
- print STDERR "$progname: " if defined($progname);
- print STDERR "$_{prefix}: " if defined($_{prefix});
- print STDERR "$msg\n"
-}
my %sbargs;
GetOptions("h" => sub {
@@ -75,7 +67,4 @@ if ($builder->is_success) {
}
} else {
print STDERR "ERROR: " . $builder->errno . "\n";
- foreach my $e ($builder->errors) {
- print STDERR "$e\n";
- }
}

Return to:

Send suggestions and report system problems to the System administrator.