summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2019-03-20 12:50:47 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2019-03-20 13:57:30 (GMT)
commita297c865dd4611c4fd862e59c70ba1b72a142035 (patch) (side-by-side diff)
tree1751891a3b93a8ce8a2260e0be9ddf8d9e90f6a0
parenta6040f631367a33f4e96759ce6ceefb759303f25 (diff)
downloadslackbuilder-a297c865dd4611c4fd862e59c70ba1b72a142035.tar.gz
slackbuilder-a297c865dd4611c4fd862e59c70ba1b72a142035.tar.bz2
Rewrite request loader.v1.0-
* lib/SlackBuild/Request.pm (load): New method. (new): Fall back to load() if given one argument. * lib/SlackBuild/Request/Auto.pm: Remove. * lib/SlackBuild/Request/Loader/dir.pm: New file. * lib/SlackBuild/Request/Loader/file.pm: New file. * lib/SlackBuild/Request/Loader/sbo.pm: New file. * lib/SlackBuild/Request/Loader/url.pm: New file. * slackbuilder: Use SlackBuild::Request->new instead of SlackBuild::Request::Auto->new * t/request.t: More tests.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--lib/SlackBuild/Request.pm108
-rw-r--r--lib/SlackBuild/Request/Auto.pm106
-rw-r--r--lib/SlackBuild/Request/Loader/dir.pm21
-rw-r--r--lib/SlackBuild/Request/Loader/file.pm25
-rw-r--r--lib/SlackBuild/Request/Loader/sbo.pm15
-rw-r--r--lib/SlackBuild/Request/Loader/url.pm22
-rwxr-xr-xslackbuilder13
-rw-r--r--t/request.t37
8 files changed, 207 insertions, 140 deletions
diff --git a/lib/SlackBuild/Request.pm b/lib/SlackBuild/Request.pm
index 6b8e132..4ae81d3 100644
--- a/lib/SlackBuild/Request.pm
+++ b/lib/SlackBuild/Request.pm
@@ -7,6 +7,7 @@ use Text::ParseWords;
use JSON;
use File::Basename;
use Safe;
+use feature 'state';
=head1 NAME
@@ -199,15 +200,6 @@ my %generics = (
}
);
-sub _readfile {
- my ($self,$file) = @_;
- local $/ = undef;
- open(my $fd, $file) or croak "can't open file $file: $!";
- my $string = <$fd>;
- close $fd;
- decode_json($string);
-}
-
sub strategy {
my ($self, $attr) = @_;
if ($attr) {
@@ -240,22 +232,25 @@ Build the request from the supplied attribute/value pairs. Allowed attributes
are discussed in detail in the B<ATTRIBUTES> section. Empty argument list
is OK.
- new SlackBuild::Request($file)
+ new SlackBuild::Request($URL)
-Read the request from the disk file B<$file>. The file must contain a single
-request formatted as JSON. No empty lines or comments are allowed.
+Loads request from the $URL. This is equivalent to
+ load SlackBuild::Request($URL)
+
+See the description of B<load>, below.
+
=cut
sub new {
- my $self = bless {}, shift;
+ my $class = shift;
my %a;
if (@_ == 1) {
my $file = shift;
if (ref($file) eq 'HASH') {
%a = %$file;
} else {
- %a = %{$self->_readfile($file)}
+ %a = return $class->load($file);
}
} elsif (@_ % 2) {
croak "bad number of arguments";
@@ -263,12 +258,97 @@ sub new {
%a = @_;
}
+ my $self = bless {}, $class;
while (my ($k,$v) = each %a) {
$self->${\ "set_$k"}($v);
}
return $self;
}
+=head2 load
+
+ $req = load SlackBuild::Request($URL)
+
+Loads request from the supplied $URL. Allowed arguments are:
+
+=over 4
+
+=item Local file name
+
+If $URL is the name of an existing local file, the file is loaded to the
+memory and parsed as JSON object (if it begins with a curly brace), or as
+YAML document.
+
+=item Local directory name
+
+If $URL is the name of an existing local directory, it is searched for
+any files matching the shell globbing pattern C<*.SlackBuild>. If any
+such file is found, its base name is taken as the name of the package,
+and the full pathname of the directory itself as the B<slackbuild_uri>.
+
+=item URL of the remote tarball
+
+If $URL begins with any of C<http://>, C<https://>, C<ftp://>, C<ftps://>,
+and its path name component ends in C<.tar> with optional compression
+suffix (C<.gz>, C<.xz>, C<.lz>, or C<.bz2>), the file name part of the
+URL is taken as the package name and the $URL itself as B<slackbuild_uri>.
+
+=item SBo URL
+
+ sbo:///COMMIT/CATEGORY/PACKAGE
+
+This URL refers the definition of C<PACKAGE> in B<slackbuild.org> repository.
+For example:
+
+ sbo://HEAD/system/cronie
+
+=item Package name
+
+Unqualified package name is looked up in the B<slackbuild.org> repository.
+If it is found, the retrieved data are used to build the request.
+
+=back
+
+=cut
+
+sub load {
+ my ($class, $reqname) = @_;
+
+ my $ldpack = __PACKAGE__ . '::Loader';
+ my @comp = split /::/, $ldpack;
+
+ # Current (as of perl 5.28.0) implementation of "state" only permits
+ # the initialization of scalar variables in scalar context. Therefore
+ # this variable is an array ref.
+ state $loaders //=
+ [map { $_->[1] }
+ sort { $a->[0] <=> $b->[0] }
+ map {
+ my ($modname) = $ldpack . '::' . fileparse($_, '.pm');
+ eval {
+ no strict 'refs';
+ if (scalar %{ $modname.'::' }) {
+ die "INCLUDED $modname";
+ };
+ require $_;
+ my $prio = ${$modname.'::PRIORITY'};
+ die unless $prio && $modname->can('Load');
+ [ $prio, $modname ]
+ }
+ }
+ map { glob File::Spec->catfile($_, '*.pm') }
+ grep { -d $_ }
+ map { File::Spec->catfile($_, @comp) } @INC];
+
+ foreach my $ld (@$loaders) {
+ if (my $req = $ld->Load($reqname)) {
+ return $class->new($req);
+ }
+ }
+
+ croak "unrecognized request type";
+}
+
=head1 STRING REPRESENTATION
When used is string context, objects of this class are represented as
diff --git a/lib/SlackBuild/Request/Auto.pm b/lib/SlackBuild/Request/Auto.pm
deleted file mode 100644
index 576d39d..0000000
--- a/lib/SlackBuild/Request/Auto.pm
+++ b/dev/null
@@ -1,106 +0,0 @@
-package SlackBuild::Request::Auto;
-use strict;
-use warnings;
-use parent 'SlackBuild::Request';
-use File::Basename;
-use File::Spec;
-use Net::SBo;
-use JSON;
-use YAML;
-use Carp;
-
-sub req {
- my ($class, $reqname) = @_;
- my $req;
-
- if (-f $reqname) {
- local $/ = undef;
- open(my $fd, $reqname) or croak "can't open file $reqname: $!";
- my $string = <$fd>;
- close $fd;
- if ($string =~ /^\{/) {
- return decode_json($string);
- }
- return YAML::Load($string);
- }
-
- if (-d $reqname) {
- if (my $file =
- (glob File::Spec->catfile($reqname, '*.SlackBuild'))[0]) {
- my ($package,$path,$suffix) = fileparse($file, '.SlackBuild');
- return { package => $package, slackbuild_uri => $path };
- }
- }
-
- if ($reqname =~ m{^\w+://}) {
- my $uri = new URI($reqname);
- if ($uri->scheme =~ m{^(?:http|ftp)s?}
- && $uri->path =~ m{.*/(.+?)\.tar(?:\.(?:[xgl]z|bz2))?}x) {
- return { package => $1, slackbuild_uri => $reqname };
- }
- if ($uri->scheme eq 'sbo') {
- return { package => $uri->package, slackbuild_uri => $reqname }
- }
- }
-
- if (my ($dir,$commit) = Net::SBo->new->find($reqname)) {
- return { package => $reqname, slackbuild_uri => "sbo://$commit/$dir"};
- }
-
- croak "unrecognized request type";
-}
-
-sub new {
- my ($class, $arg) = @_;
- return $class->SUPER::new(__PACKAGE__->req($arg));
-}
-
-1;
-__END__
-
-=head1 NAME
-
-SlackBuild::Request::Auto - automatic request convertor for SlackBuilder
-
-=head1 SYNOPSIS
-
- $req = new SlackBuild::Request::Auto($arg)
-
-=head1 DESCRIPTION
-
-Attempts to recognize the format of I<$arg> and convert it to the SlackBuilder
-build request.
-
-Argument can be any of:
-
-=over 4
-
-=item Name of an existing file
-
-The file is read and parsed as a JSON request file.
-
-=item Name of an existing directory
-
-If it contains a file B<*.SlackBuild>, a request referring to files
-in this directory is returned.
-
-=item A http, https, ftp, or ftps URL to a tar file
-
-The file component of the URL must end with B<.tar>, followed with a
-compression suffix (B<.gz>, B<.xz>, or B<.bz2>). The archive must contain
-at least the B<*.SlackBuild> file.
-
-Example:
-
- https://slackbuilds.org/slackbuilds/14.2/system/mailutils.tar.gz
-
-=item An SBo URL
-
-Example:
-
- sbo://HEAD/system/mailutils
-
-=back
-
-=cut
-
diff --git a/lib/SlackBuild/Request/Loader/dir.pm b/lib/SlackBuild/Request/Loader/dir.pm
new file mode 100644
index 0000000..5e2af9d
--- a/dev/null
+++ b/lib/SlackBuild/Request/Loader/dir.pm
@@ -0,0 +1,21 @@
+package SlackBuild::Request::Loader::dir;
+use strict;
+use warnings;
+use File::Basename;
+use File::Spec;
+
+our $PRIORITY = 20;
+
+sub Load {
+ my ($class, $reqname) = @_;
+ if (-d $reqname) {
+ if (my $file =
+ (glob File::Spec->catfile($reqname, '*.SlackBuild'))[0]) {
+ my ($package,$path) = fileparse($file, '.SlackBuild');
+ return { package => $package, slackbuild_uri => $path };
+ }
+ }
+}
+
+1;
+
diff --git a/lib/SlackBuild/Request/Loader/file.pm b/lib/SlackBuild/Request/Loader/file.pm
new file mode 100644
index 0000000..2a8cae6
--- a/dev/null
+++ b/lib/SlackBuild/Request/Loader/file.pm
@@ -0,0 +1,25 @@
+package SlackBuild::Request::Loader::file;
+use strict;
+use warnings;
+use JSON;
+use YAML ();
+use Carp;
+
+our $PRIORITY = 10;
+
+sub Load {
+ my ($class, $reqname) = @_;
+ if (-f $reqname) {
+ local $/ = undef;
+ open(my $fd, $reqname) or croak "can't open file $reqname: $!";
+ my $string = <$fd>;
+ close $fd;
+ if ($string =~ /^\{/) {
+ return decode_json($string);
+ }
+ return YAML::Load($string);
+ }
+}
+
+1;
+
diff --git a/lib/SlackBuild/Request/Loader/sbo.pm b/lib/SlackBuild/Request/Loader/sbo.pm
new file mode 100644
index 0000000..bb0ec77
--- a/dev/null
+++ b/lib/SlackBuild/Request/Loader/sbo.pm
@@ -0,0 +1,15 @@
+package SlackBuild::Request::Loader::sbo;
+use strict;
+use warnings;
+use Net::SBo;
+
+our $PRIORITY = 40;
+
+sub Load {
+ my ($class, $reqname) = @_;
+ if (my ($dir,$commit) = Net::SBo->new->find($reqname)) {
+ return { package => $reqname, slackbuild_uri => "sbo://$commit/$dir"};
+ }
+}
+
+1;
diff --git a/lib/SlackBuild/Request/Loader/url.pm b/lib/SlackBuild/Request/Loader/url.pm
new file mode 100644
index 0000000..f8ff68f
--- a/dev/null
+++ b/lib/SlackBuild/Request/Loader/url.pm
@@ -0,0 +1,22 @@
+package SlackBuild::Request::Loader::url;
+use strict;
+use warnings;
+use URI;
+
+our $PRIORITY = 30;
+
+sub Load {
+ my ($class, $reqname) = @_;
+ if ($reqname =~ m{^\w+://}) {
+ my $uri = new URI($reqname);
+ if ($uri->scheme =~ m{^(?:http|ftp)s?}
+ && $uri->path =~ m{.*/(.+?)\.tar(?:\.(?:[xgl]z|bz2))?}x) {
+ return { package => $1, slackbuild_uri => $reqname };
+ }
+ if ($uri->scheme eq 'sbo') {
+ return { package => $uri->package, slackbuild_uri => $reqname }
+ }
+ }
+}
+
+1;
diff --git a/slackbuilder b/slackbuilder
index 6e3ac47..9ad2722 100755
--- a/slackbuilder
+++ b/slackbuilder
@@ -9,7 +9,7 @@ use File::Basename;
use File::Spec;
use Unix::Sysexits;
use SlackBuilder;
-use SlackBuild::Request::Auto;
+use SlackBuild::Request;
use Net::SBo;
use JSON;
use Try::Tiny;
@@ -35,15 +35,6 @@ sub error {
print STDERR "$_{prefix}: " if defined($_{prefix});
print STDERR "$msg\n"
}
-
-sub readfile {
- my $file = shift;
- local $/ = undef;
- open(my $fd, $file) or abend(EX_NOINPUT, "can't open file $file: $!");
- my $string = <$fd>;
- close $fd;
- return decode_json($string);
-}
my %sbargs;
GetOptions("h" => sub {
@@ -64,7 +55,7 @@ GetOptions("h" => sub {
abend(EX_USAGE, "bad number of arguments") unless @ARGV == 1;
my $reqname = shift @ARGV;
my $req = try {
- new SlackBuild::Request::Auto($reqname)
+ new SlackBuild::Request($reqname)
} catch {
my $err = (split /\n/)[0];
$err =~ s{\s+at .* line \d+\.$}{};
diff --git a/t/request.t b/t/request.t
index 3880229..9a7eeb7 100644
--- a/t/request.t
+++ b/t/request.t
@@ -7,7 +7,7 @@ use SlackBuild::Info;
use File::Temp;
use Test;
-plan tests => 6;
+plan tests => 7;
#1
my $req = new SlackBuild::Request(
@@ -88,8 +88,9 @@ ok("$req",
q{{"package":"foo","prereq":["bar","baz"],"slackbuild_uri":"foo.tar.gz","source_uri":["foo-1.0.tar.gz"],"strategy":{"prereq":"keep"},"version":"1.0"}});
#6
-my $fh = new File::Temp(UNLINK => 1);
-print $fh <<'EOT'
+{
+ my $fh = new File::Temp(UNLINK => 1);
+ print $fh <<'EOT'
{
"package": "foo",
"version": "1.0",
@@ -98,10 +99,28 @@ print $fh <<'EOT'
"prereq": "quux"
}
EOT
+ ;
+ $fh->flush;
+ $req = load SlackBuild::Request($fh->filename);
+ ok("$req",
+ q{{"build":"2","package":"foo","prereq":["quux"],"source_uri":["foo-1.1.tar.gz","bar-1.0.tar.gz"],"version":"1.0"}});
+}
+#7
+{
+ my $fh = new File::Temp(UNLINK => 1);
+ print $fh <<'EOT'
+---
+package: foo
+version: 1.0
+source_uri:
+ - foo-1.1.tar.gz
+ - bar-1.0.tar.gz
+build: 2
+prereq: quux
+EOT
;
-$fh->flush;
-$req = new SlackBuild::Request($fh->filename);
-ok("$req",
- q{{"build":"2","package":"foo","prereq":["quux"],"source_uri":["foo-1.1.tar.gz","bar-1.0.tar.gz"],"version":"1.0"}});
-
-
+ $fh->flush;
+ $req = load SlackBuild::Request($fh->filename);
+ ok("$req",
+ q{{"build":"2","package":"foo","prereq":["quux"],"source_uri":["foo-1.1.tar.gz","bar-1.0.tar.gz"],"version":"1.0"}});
+}

Return to:

Send suggestions and report system problems to the System administrator.