diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2019-03-20 13:50:47 +0100 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2019-03-20 14:57:30 +0100 |
commit | a297c865dd4611c4fd862e59c70ba1b72a142035 (patch) | |
tree | 1751891a3b93a8ce8a2260e0be9ddf8d9e90f6a0 | |
parent | a6040f631367a33f4e96759ce6ceefb759303f25 (diff) | |
download | slackbuilder-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.
-rw-r--r-- | lib/SlackBuild/Request.pm | 108 | ||||
-rw-r--r-- | lib/SlackBuild/Request/Auto.pm | 106 | ||||
-rw-r--r-- | lib/SlackBuild/Request/Loader/dir.pm | 21 | ||||
-rw-r--r-- | lib/SlackBuild/Request/Loader/file.pm | 25 | ||||
-rw-r--r-- | lib/SlackBuild/Request/Loader/sbo.pm | 15 | ||||
-rw-r--r-- | lib/SlackBuild/Request/Loader/url.pm | 22 | ||||
-rwxr-xr-x | slackbuilder | 13 | ||||
-rw-r--r-- | t/request.t | 37 |
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 +++ /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 --- /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 --- /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 --- /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 --- /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"}}); +} |