summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.PL4
-rw-r--r--docker/sysupdate.sh20
-rw-r--r--lib/LWP/Protocol/sbo.pm2
-rw-r--r--lib/Net/SBo.pm11
-rw-r--r--lib/SlackBuild/Archive.pm3
-rw-r--r--lib/SlackBuild/Archive/Extractor.pm2
-rw-r--r--lib/SlackBuild/Archive/Extractor/HTTP.pm6
-rw-r--r--lib/SlackBuild/Archive/Extractor/Tar.pm95
-rw-r--r--lib/SlackBuild/Archive/Tar.pm374
-rw-r--r--lib/SlackBuild/Base.pm53
-rw-r--r--lib/SlackBuild/Config.pm61
-rw-r--r--lib/SlackBuild/Counter.pm2
-rw-r--r--lib/SlackBuild/Download.pm4
-rw-r--r--lib/SlackBuild/Info.pm2
-rw-r--r--lib/SlackBuild/Pattern.pm4
-rw-r--r--lib/SlackBuild/Rc.pm4
-rw-r--r--lib/SlackBuild/Registry.pm41
-rw-r--r--lib/SlackBuild/Registry/Backend/FS.pm23
-rw-r--r--lib/SlackBuild/Registry/Backend/Packages.pm150
-rw-r--r--lib/SlackBuild/Registry/Pattern.pm2
-rw-r--r--lib/SlackBuild/Registry/Record.pm43
-rw-r--r--lib/SlackBuild/Registry/Version.pm2
-rw-r--r--lib/SlackBuild/Request.pm55
-rw-r--r--lib/SlackBuild/Request/Loader.pm28
-rw-r--r--lib/SlackBuild/Request/Loader/dir.pm26
-rw-r--r--lib/SlackBuild/Request/Loader/file.pm44
-rw-r--r--lib/SlackBuild/Request/Loader/sbo.pm3
-rw-r--r--lib/SlackBuild/Request/Loader/url.pm36
-rw-r--r--lib/SlackBuild/Runcap.pm88
-rw-r--r--lib/SlackBuild/URI.pm16
-rw-r--r--lib/SlackBuilder.pm189
-rw-r--r--lib/URI/sbo.pm2
-rwxr-xr-xslackbuilder3
33 files changed, 1163 insertions, 235 deletions
diff --git a/Makefile.PL b/Makefile.PL
index 05bbd84..64fcbec 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -46,7 +46,7 @@ WriteMakefile(NAME => 'slackbuilder',
'Log::Dispatch' => '2.44',
#Net::SBo
'POSIX' => 0,
- 'POSIX::Run::Capture' => 0,
+ 'POSIX::Run::Capture' => 1.01,
'Safe' => 0,
'Scalar::Util' => 0,
'Text::ParseWords' => 0,
diff --git a/docker/sysupdate.sh b/docker/sysupdate.sh
index 273adb6..5a8cdc9 100644
--- a/docker/sysupdate.sh
+++ b/docker/sysupdate.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Update a base Slackware installation so it can be used for building packages
-# Copyright (C) 2019 Sergey Poznyakoff
+# Copyright (C) 2019-2021 Sergey Poznyakoff
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,8 +17,21 @@
set -e
+. /etc/os-release
+
+if [ "$VERSION_CODENAME" = "current" ] || [ "$VERSION" = 15.0 ]; then
+ echo "Installing coreutils 8.25 to work around a docker bug"
+ cd /tmp
+ wget http://pirx.gnu.org.ua/slackware/slackware64-14.2/slackware64/a/coreutils-8.25-x86_64-2.txz
+ installpkg ./coreutils-8.25-x86_64-2.txz
+ removepkg $(find /var/log/packages/ -name 'coreutils*' -not -name coreutils-8.25-x86_64-2)
+ cd /usr/bin
+ ln -sf mktemp-gnu mktemp
+ cd /
+fi
+
# Update a list of available packages in /var/lib/slackpkg/pkglist
-slackpkg update
+yes | slackpkg update
# Create a list of installed packages. Each line in the output consists of
# three fields:
@@ -36,6 +49,7 @@ find /var/log/packages -type f -maxdepth 1 -printf '%f\n' | \
# d - development
# e - emacs
# l - libraries
+# n - network
# t - TeX
# tcl - Tcl/Tk and related
# x - X Window System
@@ -43,7 +57,7 @@ find /var/log/packages -type f -maxdepth 1 -printf '%f\n' | \
# above. The fourth contains base name of the package without the archive
# suffix (.t[gx]z).
awk '/^slackware64/ {
- if (match($7, /\/[adeltx]$/) || match($7, /\/ap/) || match($7, /\/tcl/))
+ if (match($7, /\/[adelntx]$/) || match($7, /\/ap/) || match($7, /\/tcl/))
print $2,$3,$5,$6}' \
/var/lib/slackpkg/pkglist | \
sort -k1 -k2V > /tmp/available
diff --git a/lib/LWP/Protocol/sbo.pm b/lib/LWP/Protocol/sbo.pm
index e01b3ea..ffc5ebd 100644
--- a/lib/LWP/Protocol/sbo.pm
+++ b/lib/LWP/Protocol/sbo.pm
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/lib/Net/SBo.pm b/lib/Net/SBo.pm
index b16cb80..6d3d31a 100644
--- a/lib/Net/SBo.pm
+++ b/lib/Net/SBo.pm
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -162,7 +162,7 @@ sub scan {
=head2 $sbo->commit()
-Returns the SHA-1 hash identified the scanned commit.
+Returns the SHA-1 hash which identifies the scanned commit.
=cut
@@ -266,16 +266,15 @@ sub get {
open(my $fd, '-|', @gitcmd) or croak "can't run git: $!";
$path .= '/' unless $path =~ m{/$};
- my $rx = qr($path);
my $tar = new Archive::Tar($fd);
my @result;
if ($extract) {
$dest .= '/' unless $dest =~ m{/$};
- foreach my $file (tar->get_files) {
+ foreach my $file ($tar->get_files) {
my $name = $file->full_path;
- if ($name =~ s{^$rx}{$dest}) {
+ if ($name =~ s{^\Q$path\E}{$dest}) {
if ($file->extract($name)) {
push @result, $name;
}
@@ -287,7 +286,7 @@ sub get {
}
foreach my $file ($tar->get_files) {
my $name = $file->full_path;
- if ($name =~ s{^$rx}{}) {
+ if ($name =~ s{^\Q$path\E}{}) {
$file->rename($name);
}
push @result, $name;
diff --git a/lib/SlackBuild/Archive.pm b/lib/SlackBuild/Archive.pm
index 3bcc21e..a9e92b3 100644
--- a/lib/SlackBuild/Archive.pm
+++ b/lib/SlackBuild/Archive.pm
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -81,6 +81,7 @@ sub download {
$self->_read_info($dst);
}
}
+ unlink $tmp;
return $result;
}
diff --git a/lib/SlackBuild/Archive/Extractor.pm b/lib/SlackBuild/Archive/Extractor.pm
index 38fb488..9590d08 100644
--- a/lib/SlackBuild/Archive/Extractor.pm
+++ b/lib/SlackBuild/Archive/Extractor.pm
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/lib/SlackBuild/Archive/Extractor/HTTP.pm b/lib/SlackBuild/Archive/Extractor/HTTP.pm
index 9d1f831..7f16168 100644
--- a/lib/SlackBuild/Archive/Extractor/HTTP.pm
+++ b/lib/SlackBuild/Archive/Extractor/HTTP.pm
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -47,9 +47,9 @@ sub extract {
for my $diag (@$err) {
my ($file, $message) = %$diag;
if ($file eq '') {
- $self->error("general error: $message");
+ $self->logger->error("general error: $message");
} else {
- $self->error("can't create $file: $message");
+ $self->logger->error("can't create $file: $message");
}
}
return $result;
diff --git a/lib/SlackBuild/Archive/Extractor/Tar.pm b/lib/SlackBuild/Archive/Extractor/Tar.pm
index 024c4bd..896bb1f 100644
--- a/lib/SlackBuild/Archive/Extractor/Tar.pm
+++ b/lib/SlackBuild/Archive/Extractor/Tar.pm
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -19,97 +19,16 @@ use strict;
use warnings;
use parent 'SlackBuild::Archive::Extractor';
use SlackBuild::Download;
-use POSIX::Run::Capture qw(:all);
-use POSIX qw(:sys_wait_h);
-
-sub _runcap_diag {
- my ($self, $obj) = @_;
- if (WIFEXITED($obj->status)) {
- return 1 if $obj->status == 0;
- while (my $s = $obj->next_line(SD_STDERR)) {
- chomp($s);
- $self->logger->error($s);
- }
- $self->logger->error("program "
- . $obj->program
- . " terminated with code "
- . WEXITSTATUS($obj->status));
- } elsif (WIFSIGNALED($obj->status)) {
- $self->logger->error("program "
- . $obj->program
- . " terminated on signal "
- . WTERMSIG($obj->status));
- } else {
- $self->logger->error("program "
- . $obj->program
- . " terminated with unrecogized code "
- . $obj->status);
- }
- return 0;
-}
-
-sub _run_tar {
- my $self = shift;
- my $obj = new POSIX::Run::Capture(argv => [ 'tar', @_ ],
- timeout => 10);
- if ($obj->run) {
- return $obj if $self->_runcap_diag($obj);
- } else {
- $self->logger->error("can't run tar: ".strerror($obj->errno));
- }
- return 0;
-}
-
-sub _check_build {
- my $self = shift;
- my $obj = $self->_run_tar('-t', '-f', $self->tempfile) or return 0;
- my $name = $self->archive->package_name;
- my $rx = qr($name);
- my $prefix;
- my $success = 1;
-
- while (my $s = $obj->next_line(SD_STDOUT)) {
- chomp($s);
- $s =~ s{^\./}{};
- if ($s =~ m{^\./}) {
- $self->logger->error($self->slackbuild_uri .": bad file: $s");
- $success = 0;
- }
- if ($s =~ s{^$rx/}{}) {
- if (defined($prefix)) {
- if (!$prefix) {
- $self->logger->error($self->slackbuild_uri .": bad file: $s");
- $success = 0;
- }
- } else {
- $prefix = 1;
- }
- } else {
- if (defined($prefix)) {
- if ($prefix) {
- $self->logger->error($self->slackbuild_uri .": bad file: $s");
- $success = 0;
- }
- } else {
- $prefix = 0;
- }
- }
- $self->archive->add_file($s);
- }
- $self->{_skip} = $prefix;
- return $success;
-}
+use SlackBuild::Archive::Tar;
sub extract {
my $self = shift;
my $result = new SlackBuild::Download($self->archive);
- if ($self->_check_build && $self->archive->verify) {
- $result->success($self->_run_tar('-C', $self->destdir,
- '--strip', $self->{_skip},
- '-x',
- '-f',
- $self->tempfile));
- }
+ my $tar = new SlackBuild::Archive::Tar($self->tempfile);
+ $tar->workdir($self->destdir);
+ $result->success($tar->strip($self->archive->package_name)
+ && $self->archive->add_file($tar->list)
+ && $self->archive->verify);
return $result;
}
diff --git a/lib/SlackBuild/Archive/Tar.pm b/lib/SlackBuild/Archive/Tar.pm
new file mode 100644
index 0000000..d69c0c5
--- /dev/null
+++ b/lib/SlackBuild/Archive/Tar.pm
@@ -0,0 +1,374 @@
+package SlackBuild::Archive::Tar;
+use strict;
+use warnings;
+use SlackBuild::Runcap;
+use POSIX::Run::Capture qw(:std);
+use File::Basename;
+use File::Temp qw(tempfile tempdir);
+use File::Spec;
+use Log::Log4perl;
+use Carp;
+
+=head1 NAME
+
+SlackBuild::Archive::Tar - domain-specific API for accessing tar archives
+
+=head1 DESCRIPTION
+
+This module provides API for accessing (reading or appending to)
+slackware package tar archives. It uses GNU tar as the underlying agent.
+
+=head1 CONSTRUCTOR
+
+ $tar = new SlackBuild::Archive::Tar($file);
+
+Creates an object for read-only access to tar archive B<$file>.
+The returned object can be used to get the listing of the archive,
+and extract files from it (see the B<extract> and B<strip> methods),
+but cannot be used to alter the archive content.
+
+ $tar = new SlackBuild::Archive::Tar($file, append => 1);
+
+Creates an object for reading and appending to tar archive B<$file>.
+The returned object cannot be used for extraction.
+
+=cut
+
+sub new {
+ my ($class, $filename, %opt) = @_;
+ bless { _filename => $filename, _append => $opt{append} }, $class;
+}
+
+=head1 METHODS
+
+=head2 filename
+
+Returns the archive filename.
+
+=cut
+
+sub filename { shift->{_filename} }
+
+=head2 is_mode_append
+
+Returns true if the archive was created for appending.
+
+=cut
+
+sub is_mode_append { shift->{_append} }
+
+my %compressor = (
+ gz => 'gzip',
+ tbz => 'bzip2',
+ bz2 => 'bzip2',
+ tlz => 'lzma',
+ lzma => 'lzma',
+ txz => 'xz',
+ xz => 'xz'
+);
+
+sub uncompress {
+ my ($self) = @_;
+ unless ($self->{_plaintar}) {
+ my ($name,undef,$suffix) =
+ fileparse($self->filename, keys(%compressor));
+ my $plaintar = File::Spec->catfile($self->workdir, $name);
+ my $rc = SlackBuild::Runcap->new(
+ argv => [ $compressor{$suffix}, '-d', '-c', $self->filename ],
+ stdout => $plaintar);
+ if ($rc->success) {
+ $self->{_plaintar} = $plaintar;
+ }
+ }
+ return $self->{_plaintar};
+}
+
+sub tarcmd {
+ my ($self, @argv) = @_;
+ local $ENV{TAR_OPTIONS};
+ unshift @argv, '-f', $self->filename;
+ my (undef,undef,$suffix) = fileparse($self->filename, keys(%compressor));
+ if ($suffix) {
+ unshift @argv, '-I', $compressor{$suffix};
+ }
+ my $rc = SlackBuild::Runcap->new(argv => [ 'tar', @argv ]);
+ if ($rc->success) {
+ [map { chomp; s{/$}{}; $_ } @{ $rc->get_lines(SD_STDOUT) }];
+ }
+}
+
+=head2 list
+
+ @a = $tar->list;
+
+Returns a list of member names in archive.
+
+=cut
+
+sub list {
+ my ($self) = @_;
+ if (!$self->{_list}) {
+ if (my $out = $self->tarcmd('-t')) {
+ $self->{_list} = $out;
+ } else {
+ $self->{_list} = [];
+ }
+ }
+ if ($self->{_sort}) {
+ $self->{_list} = [sort @{$self->{_list}}];
+ $self->{_sort} = 0;
+ }
+ return @{$self->{_list}};
+}
+
+=head2 has_file
+
+ if ($tar->has_file($file)) {
+ ...
+
+Returns true if B<$file> is a member of the archive B<$tar>. B<$file> must
+be given exactly as it should appear in the archive, but without trailing
+slash, if it is a directory,
+
+=cut
+
+sub has_file {
+ my ($self, $file) = @_;
+ grep { $_ eq $file } $self->list;
+}
+
+=head2 match_files
+
+ @files = $tar->match_files(@patterns);
+
+Returns a list of archive members whose names match at least on of the regexps
+from B<@patterns>.
+
+=cut
+
+sub match_files {
+ my $self = shift;
+ grep { my $file = $_;
+ grep { $file =~ m{$_} } @_ } $self->list;
+}
+
+=head2 workdir
+
+ $d = $tar->workdir;
+
+Returns the working directory for this archive. This is the directory where
+the archive will be extracted (or is already extracted) by B<extract> or
+B<strip> methods.
+
+ $tar->workdir($newdir);
+
+If called with an argument sets the working directory and creates it if
+it does not exist. Such invocation can happen only once, before any
+of the following methods were called: B<workdir>, B<extract>, B<strip>,
+B<add_file>, B<add_file_content>.
+If the directory has not been set, a call to any of these functions
+will create a temporary directory which will be removed when the object
+is destroyed.
+
+=cut
+
+sub workdir {
+ my $self = shift;
+ if (@_) {
+ if ($self->{_workdir}) {
+ croak "working directory already set ($self->{_workdir})";
+ }
+ $self->{_workdir} = shift;
+ if (! -d $self->{_workdir}) {
+ mkdir $self->{_workdir} or
+ croak "can't create directory $self->{_workdir}: $!";
+ }
+ }
+ if (!$self->{_workdir}) {
+ $self->{_workdir} = tempdir(CLEANUP => 1);
+ }
+ return $self->{_workdir};
+}
+
+=head2 extract
+
+ $tar->extract;
+
+Extracts the archive to the working directory. On success, returns the
+name of the working directory. On error, logs the reason using
+B<Log::Log4perl> and returns false.
+
+It is safe to call this method multiple times. Once the archive has
+been extracted, any subsequent call to B<extract> is a no-op.
+
+=cut
+
+sub extract {
+ my $self = shift;
+ croak "can't extract from ".$self->filename.": archive open for appending"
+ if $self->is_mode_append;
+ if ($self->extracted) {
+ return $self->workdir;
+ }
+ if ($self->tarcmd('-x', '-C', $self->workdir, @_)) {
+ $self->{_extracted} = 1;
+ return $self->workdir;
+ }
+}
+
+=head2 strip
+
+ $tar->strip($prefix)
+
+If all archive members are located under given directory B<$prefix>,
+extracts the archive stripping this prefix from each member name.
+Otherwise it is equivalent to B<extract>.
+
+=cut
+
+sub strip {
+ my ($self, $pfx) = @_;
+ my @list;
+ foreach my $member ($self->list) {
+ if ($member =~ m{\Q$pfx\E(?:/(.*))?$}) {
+ next unless $1;
+ push @list, $1;
+ } else {
+ @list = ();
+ }
+ }
+ my @args;
+ if (@list) {
+ $self->{_list} = \@list;
+ push @args, '--strip=1';
+ }
+ $self->extract(@args);
+}
+
+# sub strip {
+# my $self = shift;
+# my @list = grep { $_ ne '.' } $self->list;
+# return unless @list;
+# my $prefix = (File::Spec->splitdir(shift(@list)))[0];
+# while (my $member = shift @list) {
+# my @c = File::Spec->splitdir($member);
+# return unless $c[0] eq $prefix;
+# }
+# $self->extract or croak $self->filename . ": extraction failed";
+# $self->{_workdir} = File::Spec->catfile($self->{_workdir}, $prefix);
+# return $self->{_workdir};
+# }
+
+=head2 extracted
+
+Returns true if the archive has been extracted.
+
+=cut
+
+sub extracted { shift->{_extracted} }
+
+=head2 changed
+
+Returns true if the archive has been modified by a call to B<add_file> or
+B<add_file_content>.
+
+=cut
+
+sub changed { shift->{_changed} }
+
+sub logger { shift->{_logger} //= Log::Log4perl::get_logger(__PACKAGE__) }
+
+=head2 add_file
+
+ $tar->add_file($filename, $membername);
+
+Reads the file B<$filename> and adds its content to the archive as the
+member <$membername>. The B<$tar> object must have been created with
+the B<append =E<gt> 1> option.
+
+The appended member will be owner by root and will have the mode of
+0644.
+
+On success, returns true. On failure, returns false and logs the
+reason using B<Log::Log4perl>.
+
+=cut
+
+sub add_file {
+ my ($self, $filename, $membername) = @_;
+ croak "can't append to ".$self->filename.": archive open for extraction"
+ unless $self->is_mode_append;
+ my $tarfile = $self->uncompress or return;
+ (my $s_name = $filename) =~ s{^/}{};
+ $s_name =~ s{([\\/|()\[\]{}^\$\*+?.])}{\\$1}g;
+ (my $d_name = $membername) =~ s{/}{\\/}g;
+ my $rc = SlackBuild::Runcap->new(
+ argv => [ 'tar', '-r', '-f', $tarfile,
+ '--owner=root:0', '--group=root:0',
+ "--transform=s/$s_name/$d_name/",
+ '--mode=644',
+ $filename ]);
+ if ($rc->success) {
+ push @{$self->{_list}}, $membername;
+ $self->{_sort} = 1;
+ $self->{_changed} = 1;
+ }
+ return $rc->success;
+}
+
+=head2 add_file_content
+
+ $tar->add_file($membername, $content);
+
+Adds B<$content> to the archive under the name B<$membername>.
+
+The appended member will be owner by root and will have the mode of
+0644.
+
+On failure, returns false and logs the reason using B<Log::Log4perl>.
+
+=cut
+
+sub add_file_content {
+ my ($self, $membername, $text) = @_;
+ croak "can't append to ".$self->filename.": archive open for extraction"
+ unless $self->is_mode_append;
+ my ($fh, $filename) = tempfile(DIR => $self->workdir);
+ print $fh $text;
+ close $fh;
+ return $self->add_file($filename, $membername);
+}
+
+=head2 save
+
+ $tar->save;
+
+Saves the archive after modifications. Returns true on success, false on
+failure.
+
+This method is always called when destroying the B<SlackBuild::Archive::Tar>
+object.
+
+=cut
+
+sub save {
+ my $self = shift;
+ return 1 unless $self->changed;
+ unless (-w $self->filename) {
+ unlink $self->filename;
+ }
+
+ my ($name,undef,$suffix) =
+ fileparse($self->filename, keys(%compressor));
+ my $rc = SlackBuild::Runcap->new(
+ argv => [ $compressor{$suffix}, '-c', $self->uncompress ],
+ stdout => $self->filename);
+ if ($rc->success) {
+ $self->{_changed} = 0;
+ }
+ return $rc->success;
+}
+
+sub DESTROY { shift->save }
+
+1;
diff --git a/lib/SlackBuild/Base.pm b/lib/SlackBuild/Base.pm
index e580fa1..e4ec8ec 100644
--- a/lib/SlackBuild/Base.pm
+++ b/lib/SlackBuild/Base.pm
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -28,24 +28,43 @@ sub import {
if ($dfn =~ m/^(?<attr>[a-zA-Z_][a-zA-Z_0-9]*)
(?::(?<flag>.*))?$/x) {
my $attribute = $+{attr};
- my $flag = $+{flag} || 'rw';
- if ($flag eq 'ro') {
- *{ $package . '::' . $attribute } = sub {
- my $self = shift;
- croak "too many arguments for ${package}::$attribute"
- if @_;
- return $self->{$attribute};
- }
- } else {
- *{ $package . '::' . $attribute } = sub {
- my $self = shift;
- if (@_) {
+ my @kw = split ',', $+{flag} || 'rw';
+ my %flags;
+ @flags{@kw} = (1) x @kw;
+ if ($flags{ro}) {
+ *{ $package . '::' . $attribute } =
+ $flags{array}
+ ? sub {
+ my $self = shift;
+ croak "too many arguments for ${package}::$attribute"
+ if @_;
+ return @{$self->{$attribute}};
+ }
+ : sub {
+ my $self = shift;
croak "too many arguments for ${package}::$attribute"
- if @_ > 1;
- $self->{$attribute} = shift;
+ if @_;
+ return $self->{$attribute};
+ }
+ } else {
+ *{ $package . '::' . $attribute } =
+ $flags{array}
+ ? sub {
+ my $self = shift;
+ if (@_) {
+ @{$self->{$attribute}} = @_;
+ }
+ return @{$self->{$attribute}};
+ }
+ : sub {
+ my $self = shift;
+ if (@_) {
+ croak "too many arguments for ${package}::$attribute"
+ if @_ > 1;
+ $self->{$attribute} = shift;
+ }
+ return $self->{$attribute};
}
- return $self->{$attribute};
- }
}
} else {
croak "$filename:$line: bad attribute spec: $dfn"
diff --git a/lib/SlackBuild/Config.pm b/lib/SlackBuild/Config.pm
index b96a457..a0fb49e 100644
--- a/lib/SlackBuild/Config.pm
+++ b/lib/SlackBuild/Config.pm
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -30,6 +30,36 @@ sub mangle {
$self->set('dir', $kw, File::Spec->catfile($rootdir, $subdir));
}
}
+
+ if ($self->is_set('lookup')) {
+ if (my $v = $self->get(qw(lookup order))) {
+ my @mods = split /\s+/, $v;
+ for (my $i = 0; $i <= $#mods; $i++) {
+ $self->set('lookup', $mods[$i], 'priority', $i);
+ }
+ }
+
+ foreach my $name ($self->names_of('lookup')) {
+ if ($self->is_section('lookup', $name)) {
+# print "MOD $name\n";
+ my $node = $self->getnode('lookup', $name);
+ my $mod = "SlackBuild::Request::Loader::$name";
+ (my $file = $mod) =~ s{::}{/}g;
+ unless (eval { require "$file.pm" }) {
+ $self->error("can't load module $name: $@",
+ locus => $node->locus);
+ next;
+ }
+ eval {
+ $mod->Configure(%{$node->as_hash});
+ };
+ if ($@) {
+ $self->error("can't initialize module $name: $@",
+ locus => $node->locus);
+ }
+ }
+ }
+ }
}
sub check_dir {
@@ -42,6 +72,21 @@ sub check_dir {
return 1;
}
+sub check_slaptget_versions {
+ my ($self, $valref, $prev_value, $locus) = @_;
+ my $val = $$valref;
+ my %valid = (
+ never => 1,
+ always => 1,
+ 'when-available' => 1
+ );
+ unless ($valid{$$valref}) {
+ $self->error("$val: unrecognozed keyword", locus => $locus);
+ return 0;
+ }
+ return 1;
+}
+
1;
__DATA__
[core]
@@ -55,5 +100,17 @@ __DATA__
log = STRING :mandatory log
pkg = STRING :mandatory pkg
spool = STRING :mandatory spool
+[docker]
+ unconfined = BOOL
+[lookup]
+ order = STRING
+[lookup file]
+ path = STRING
+ suffixes = STRING
+[lookup dir]
+ path = STRING
+[slapt-get]
+ enable = BOOL
+ versions = STRING :check=check_slaptget_versions :mandatory when-available
+ force = BOOL
-
diff --git a/lib/SlackBuild/Counter.pm b/lib/SlackBuild/Counter.pm
index a827acb..e0ed6b3 100644
--- a/lib/SlackBuild/Counter.pm
+++ b/lib/SlackBuild/Counter.pm
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/lib/SlackBuild/Download.pm b/lib/SlackBuild/Download.pm
index b301a58..9e09b2e 100644
--- a/lib/SlackBuild/Download.pm
+++ b/lib/SlackBuild/Download.pm
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -30,7 +30,7 @@ SlackBuild::Download - download result class
Objects of this class represent the return type of download operations.
Each object has two mandatory associated attributes: archive that performed
the download (a SlackBuild::Archive object) and the success marker (true or
-false. When used in scalar context, B<SlackBuild::Download> behaves as a
+false). When used in scalar context, B<SlackBuild::Download> behaves as a
boolean value (true if the download succeeded and false otherwise),
=head1 CONSTRUCTOR
diff --git a/lib/SlackBuild/Info.pm b/lib/SlackBuild/Info.pm
index 21487bc..2e56a18 100644
--- a/lib/SlackBuild/Info.pm
+++ b/lib/SlackBuild/Info.pm
@@ -1,5 +1,5 @@
# This file is part of slackbuilder
-# Copyright (C) 2017-2019 Sergey Poznyakoff
+# Copyright (C) 2017-2021 Sergey Poznyakoff
#
# Slackbuilder is free software; you can redis