123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983 |
- #!/usr/bin/env perl
- # This chunk of stuff was generated by App::FatPacker. To find the original
- # file's code, look for the end of this BEGIN block or the string 'FATPACK'
- BEGIN {
- my %fatpacked;
- $fatpacked{"MetaCPAN/API/Tiny.pm"} = <<'METACPAN_API_TINY';
- package MetaCPAN::API::Tiny;
- {
- $MetaCPAN::API::Tiny::VERSION = '1.131730';
- }
- use strict;
- use warnings;
- # ABSTRACT: A Tiny API client for MetaCPAN
- use Carp;
- use JSON::PP 'encode_json', 'decode_json';
- use HTTP::Tiny;
- sub new {
- my ($class, @args) = @_;
- $#_ % 2 == 0
- or croak 'Arguments must be provided as name/value pairs';
- my %params = @args;
- die 'ua_args must be an array reference'
- if $params{ua_args} && ref($params{ua_args}) ne 'ARRAY';
- my $self = +{
- base_url => $params{base_url} || 'http://api.metacpan.org/v0',
- ua => $params{ua} || HTTP::Tiny->new(
- $params{ua_args}
- ? @{$params{ua_args}}
- : (agent => 'MetaCPAN::API::Tiny/'
- . ($MetaCPAN::API::VERSION || 'xx'))),
- };
- return bless($self, $class);
- }
- sub _build_extra_params {
- my $self = shift;
- @_ % 2 == 0
- or croak 'Incorrect number of params, must be key/value';
- my %extra = @_;
- my $ua = $self->{ua};
- foreach my $key (keys %extra)
- {
- # The implementation in HTTP::Tiny uses + instead of %20, fix that
- $extra{$key} = $ua->_uri_escape($extra{$key});
- $extra{$key} =~ s/\+/%20/g;
- }
- my $params = join '&', map { "$_=" . $extra{$_} } sort keys %extra;
- return $params;
- }
- # /source/{author}/{release}/{path}
- sub source {
- my $self = shift;
- my %opts = @_ ? @_ : ();
- my $url = '';
- my $error = "Provide 'author' and 'release' and 'path'";
- %opts or croak $error;
- if (
- defined ( my $author = $opts{'author'} ) &&
- defined ( my $release = $opts{'release'} ) &&
- defined ( my $path = $opts{'path'} )
- ) {
- $url = "source/$author/$release/$path";
- } else {
- croak $error;
- }
- $url = $self->{base_url} . "/$url";
- my $result = $self->{ua}->get($url);
- $result->{'success'}
- or croak "Failed to fetch '$url': " . $result->{'reason'};
- return $result->{'content'};
- }
- # /release/{distribution}
- # /release/{author}/{release}
- sub release {
- my $self = shift;
- my %opts = @_ ? @_ : ();
- my $url = '';
- my $error = "Either provide 'distribution', or 'author' and 'release', " .
- "or 'search'";
- %opts or croak $error;
- my %extra_opts = ();
- if ( defined ( my $dist = $opts{'distribution'} ) ) {
- $url = "release/$dist";
- } elsif (
- defined ( my $author = $opts{'author'} ) &&
- defined ( my $release = $opts{'release'} )
- ) {
- $url = "release/$author/$release";
- } elsif ( defined ( my $search_opts = $opts{'search'} ) ) {
- ref $search_opts && ref $search_opts eq 'HASH'
- or croak $error;
- %extra_opts = %{$search_opts};
- $url = 'release/_search';
- } else {
- croak $error;
- }
- return $self->fetch( $url, %extra_opts );
- }
- # /pod/{module}
- # /pod/{author}/{release}/{path}
- sub pod {
- my $self = shift;
- my %opts = @_ ? @_ : ();
- my $url = '';
- my $error = "Either provide 'module' or 'author and 'release' and 'path'";
- %opts or croak $error;
- if ( defined ( my $module = $opts{'module'} ) ) {
- $url = "pod/$module";
- } elsif (
- defined ( my $author = $opts{'author'} ) &&
- defined ( my $release = $opts{'release'} ) &&
- defined ( my $path = $opts{'path'} )
- ) {
- $url = "pod/$author/$release/$path";
- } else {
- croak $error;
- }
- # check content-type
- my %extra = ();
- if ( defined ( my $type = $opts{'content-type'} ) ) {
- $type =~ m{^ text/ (?: html|plain|x-pod|x-markdown ) $}x
- or croak 'Incorrect content-type provided';
- $extra{headers}{'content-type'} = $type;
- }
- $url = $self->{base_url}. "/$url";
- my $result = $self->{ua}->get( $url, \%extra );
- $result->{'success'}
- or croak "Failed to fetch '$url': " . $result->{'reason'};
- return $result->{'content'};
- }
- # /module/{module}
- sub module {
- my $self = shift;
- my $name = shift;
- $name or croak 'Please provide a module name';
- return $self->fetch("module/$name");
- }
- # file() is a synonym of module
- sub file { goto &module }
- # /author/{author}
- sub author {
- my $self = shift;
- my ( $pause_id, $url, %extra_opts );
- if ( @_ == 1 ) {
- $url = 'author/' . shift;
- } elsif ( @_ == 2 ) {
- my %opts = @_;
- if ( defined $opts{'pauseid'} ) {
- $url = "author/" . $opts{'pauseid'};
- } elsif ( defined $opts{'search'} ) {
- my $search_opts = $opts{'search'};
- ref $search_opts && ref $search_opts eq 'HASH'
- or croak "'search' key must be hashref";
- %extra_opts = %{$search_opts};
- $url = 'author/_search';
- } else {
- croak 'Unknown option given';
- }
- } else {
- croak 'Please provide an author PAUSEID or a "search"';
- }
- return $self->fetch( $url, %extra_opts );
- }
- sub fetch {
- my $self = shift;
- my $url = shift;
- my $extra = $self->_build_extra_params(@_);
- my $base = $self->{base_url};
- my $req_url = $extra ? "$base/$url?$extra" : "$base/$url";
- my $result = $self->{ua}->get($req_url);
- return $self->_decode_result( $result, $req_url );
- }
- sub post {
- my $self = shift;
- my $url = shift;
- my $query = shift;
- my $base = $self->{base_url};
- defined $url
- or croak 'First argument of URL must be provided';
- ref $query and ref $query eq 'HASH'
- or croak 'Second argument of query hashref must be provided';
- my $query_json = encode_json( $query );
- my $result = $self->{ua}->request(
- 'POST',
- "$base/$url",
- {
- headers => { 'Content-Type' => 'application/json' },
- content => $query_json,
- }
- );
- return $self->_decode_result( $result, $url, $query_json );
- }
- sub _decode_result {
- my $self = shift;
- my ( $result, $url, $original ) = @_;
- my $decoded_result;
- ref $result and ref $result eq 'HASH'
- or croak 'First argument must be hashref';
- defined $url
- or croak 'Second argument of a URL must be provided';
- if ( defined ( my $success = $result->{'success'} ) ) {
- my $reason = $result->{'reason'} || '';
- $reason .= ( defined $original ? " (request: $original)" : '' );
- $success or croak "Failed to fetch '$url': $reason";
- } else {
- croak 'Missing success in return value';
- }
- defined ( my $content = $result->{'content'} )
- or croak 'Missing content in return value';
- eval { $decoded_result = decode_json $content; 1 }
- or do { croak "Couldn't decode '$content': $@" };
- return $decoded_result;
- }
- 1;
- __END__
- =pod
- =head1 NAME
- MetaCPAN::API::Tiny - A Tiny API client for MetaCPAN
- =head1 VERSION
- version 1.131730
- =head1 DESCRIPTION
- This is the Tiny version of L<MetaCPAN::API>. It implements a compatible API
- with a few notable exceptions:
- =over 4
- =item Attributes are direct hash access
- The attributes defined using Mo(o|u)se are now accessed via the blessed hash
- directly. There are no accessors defined to access this elements.
- =item Exception handling
- Instead of using Try::Tiny, raw evals are used. This could potentially cause
- issues, so just be aware.
- =item Testing
- Test::Fatal was replaced with an eval implementation of exception().
- Test::TinyMocker usage is retained, but may be absorbed since it is pure perl
- =back
- =head1 CLASS_METHODS
- =head2 new
- new is the constructor for MetaCPAN::API::Tiny. In the non-tiny version of this
- module, this is provided via Any::Moose built from the attributes defined. In
- the tiny version, we define our own constructor. It takes the same arguments
- and provides similar checks to MetaCPAN::API with regards to arguments passed.
- =head1 PUBLIC_METHODS
- =head2 source
- my $source = $mcpan->source(
- author => 'DOY',
- release => 'Moose-2.0201',
- path => 'lib/Moose.pm',
- );
- Searches MetaCPAN for a module or a specific release and returns the plain source.
- =head2 release
- my $result = $mcpan->release( distribution => 'Moose' );
- # or
- my $result = $mcpan->release( author => 'DOY', release => 'Moose-2.0001' );
- Searches MetaCPAN for a dist.
- You can do complex searches using 'search' parameter:
- # example lifted from MetaCPAN docs
- my $result = $mcpan->release(
- search => {
- author => "OALDERS AND ",
- filter => "status:latest",
- fields => "name",
- size => 1,
- },
- );
- =head2 pod
- my $result = $mcpan->pod( module => 'Moose' );
- # or
- my $result = $mcpan->pod(
- author => 'DOY',
- release => 'Moose-2.0201',
- path => 'lib/Moose.pm',
- );
- Searches MetaCPAN for a module or a specific release and returns the POD.
- =head2 module
- my $result = $mcpan->module('MetaCPAN::API');
- Searches MetaCPAN and returns a module's ".pm" file.
- =head2 file
- A synonym of L</module>
- =head2 author
- my $result1 = $mcpan->author('XSAWYERX');
- my $result2 = $mcpan->author( pauseid => 'XSAWYERX' );
- Searches MetaCPAN for a specific author.
- You can do complex searches using 'search' parameter:
- # example lifted from MetaCPAN docs
- my $result = $mcpan->author(
- search => {
- q => 'profile.name:twitter',
- size => 1,
- },
- );
- =head2 fetch
- my $result = $mcpan->fetch('/release/distribution/Moose');
- # with parameters
- my $more = $mcpan->fetch(
- '/release/distribution/Moose',
- param => 'value',
- );
- This is a helper method for API implementations. It fetches a path from MetaCPAN, decodes the JSON from the content variable and returns it.
- You don't really need to use it, but you can in case you want to write your own extension implementation to MetaCPAN::API.
- It accepts an additional hash as "GET" parameters.
- =head2 post
- # /release&content={"query":{"match_all":{}},"filter":{"prefix":{"archive":"Cache-Cache-1.06"}}}
- my $result = $mcpan->post(
- 'release',
- {
- query => { match_all => {} },
- filter => { prefix => { archive => 'Cache-Cache-1.06' } },
- },
- );
- The POST equivalent of the "fetch()" method. It gets the path and JSON request.
- =head1 THANKS
- Overall the tests and code were ripped directly from MetaCPAN::API and
- tiny-fied. A big thanks to Sawyer X for writing the original module.
- =head1 AUTHOR
- Nicholas R. Perez <nperez@cpan.org>
- =head1 COPYRIGHT AND LICENSE
- This software is copyright (c) 2013 by Nicholas R. Perez <nperez@cpan.org>.
- This is free software; you can redistribute it and/or modify it under
- the same terms as the Perl 5 programming language system itself.
- =cut
- METACPAN_API_TINY
- s/^ //mg for values %fatpacked;
- unshift @INC, sub {
- if (my $fat = $fatpacked{$_[1]}) {
- if ($] < 5.008) {
- return sub {
- return 0 unless length $fat;
- $fat =~ s/^([^\n]*\n?)//;
- $_ = $1;
- return 1;
- };
- }
- open my $fh, '<', \$fat
- or die "FatPacker error loading $_[1] (could be a perl installation issue?)";
- return $fh;
- }
- return
- };
- } # END OF FATPACK CODE
- use 5.010;
- use strict;
- use warnings;
- use Fatal qw(open close);
- use Getopt::Long;
- use Pod::Usage;
- use File::Basename;
- use Module::CoreList;
- use HTTP::Tiny;
- use Safe;
- use MetaCPAN::API::Tiny;
- use Digest::SHA qw(sha256_hex);
- use Text::Wrap;
- $Text::Wrap::columns = 62;
- # Below, 5.028 should be aligned with the version of perl actually
- # bundled in Buildroot:
- die <<"MSG" if $] < 5.028;
- This script needs a host perl with the same major version as Buildroot target perl.
- Your current host perl is:
- $^X
- version $]
- You may install a local one by running:
- perlbrew install perl-5.28.0
- MSG
- my ($help, $man, $quiet, $force, $recommend, $test, $host);
- my $target = 1;
- GetOptions( 'help|?' => \$help,
- 'man' => \$man,
- 'quiet|q' => \$quiet,
- 'force|f' => \$force,
- 'host!' => \$host,
- 'target!' => \$target,
- 'recommend' => \$recommend,
- 'test' => \$test
- ) or pod2usage(-exitval => 1);
- pod2usage(-exitval => 0) if $help;
- pod2usage(-exitval => 0, -verbose => 2) if $man;
- pod2usage(-exitval => 1) if scalar @ARGV == 0;
- my %dist; # name -> metacpan data
- my %need_target; # name -> 1 if target package is needed
- my %need_host; # name -> 1 if host package is needed
- my %need_dlopen; # name -> 1 if requires dynamic library
- my %is_xs; # name -> 1 if XS module
- my %deps_build; # name -> list of host dependencies
- my %deps_runtime; # name -> list of target dependencies
- my %license_files; # name -> hash of license files
- my %checksum; # author -> list of checksum
- my $mirror = 'http://cpan.metacpan.org'; # a CPAN mirror
- my $mcpan = MetaCPAN::API::Tiny->new(base_url => 'http://fastapi.metacpan.org/v1');
- my $ua = HTTP::Tiny->new();
- my $new_pkgs;
- my %white_list = (
- 'ExtUtils-Config' => 1,
- 'ExtUtils-InstallPaths' => 1,
- 'ExtUtils-Helpers' => 1,
- 'File-ShareDir-Install' => 1,
- 'Module-Build' => 1,
- 'Module-Build-Tiny' => 1,
- );
- my @info = ();
- sub get_checksum {
- my ($url) = @_;
- my ($path) = $url =~ m|^[^:/?#]+://[^/?#]*([^?#]*)|;
- my ($basename, $dirname) = fileparse( $path );
- unless ($checksum{$dirname}) {
- my $url = $mirror . $dirname . q{CHECKSUMS};
- my $response = $ua->get($url);
- $checksum{$dirname} = $response->{content};
- }
- my $chksum = Safe->new->reval($checksum{$dirname});
- return $chksum->{$basename}, $basename;
- }
- sub is_xs {
- my ($manifest) = @_;
- # This heuristic determines if a module is a native extension, by searching
- # some file extension types in the MANIFEST of the distribution.
- # It was inspired by http://deps.cpantesters.org/static/purity.html
- return $manifest =~ m/\.(swg|xs|c|h|i)[\n\s]/;
- }
- sub find_license_files {
- my ($manifest) = @_;
- my @license_files;
- foreach (split /\n/, $manifest) {
- next if m|/|;
- push @license_files, $_ if m/(ARTISTIC|COPYING|COPYRIGHT|LICENSE)/i;
- }
- if (scalar @license_files == 0 && $manifest =~ m/(README)[\n\s]/i) {
- @license_files = ($1);
- }
- if (scalar @license_files == 0 && $manifest =~ m/(README\.md)[\n\s]/i) {
- @license_files = ($1);
- }
- return @license_files;
- }
- sub want_test {
- my ($distname) = @_;
- return 1 if $need_dlopen{$distname} && scalar @{$deps_runtime{$distname}} > 0;
- }
- sub get_dependencies {
- my ($distname) = @_;
- my %dep = map { $_ => 1 } @{$deps_runtime{$distname}};
- for my $direct (@{$deps_runtime{$distname}}) {
- for (get_dependencies( $direct )) {
- $dep{$_} = 1;
- }
- }
- return keys %dep;
- }
- sub get_indirect_dependencies {
- my ($distname) = @_;
- my %indirect;
- my %direct = map { $_ => 1 } @{$deps_runtime{$distname}};
- for my $dep (get_dependencies( $distname )) {
- $indirect{$dep} = 1 unless exists $direct{$dep};
- }
- return keys %indirect;
- }
- sub fetch {
- my ($name, $need_target, $need_host, $top) = @_;
- $need_target{$name} = $need_target if $need_target;
- $need_host{$name} = $need_host if $need_host;
- unless ($dist{$name} && !$top) {
- say qq{fetch ${name}} unless $quiet;
- my $result = $mcpan->release( distribution => $name );
- $dist{$name} = $result;
- $license_files{$name} = {};
- eval {
- my $author = $result->{author};
- my $release = $name . q{-} . $result->{version};
- my $manifest = $mcpan->source( author => $author, release => $release, path => 'MANIFEST' );
- $need_dlopen{$name} = $is_xs{$name} = is_xs( $manifest );
- foreach my $fname (find_license_files( $manifest )) {
- my $license = $mcpan->source( author => $author, release => $release, path => $fname );
- $license_files{$name}->{$fname} = sha256_hex( $license );
- }
- };
- if ($@) {
- warn $@;
- }
- my %build = ();
- my %runtime = ();
- my %optional = ();
- foreach my $dep (@{$result->{dependency}}) {
- my $modname = ${$dep}{module};
- next if $modname eq q{perl};
- next if $modname =~ m|^Alien|;
- next if $modname =~ m|^Win32|;
- next if !($test && $top) && $modname =~ m|^Test|;
- next if Module::CoreList::is_core( $modname, undef, $] );
- # we could use the host Module::CoreList data, because host perl and
- # target perl have the same major version
- next if ${$dep}{phase} eq q{develop};
- next if ${$dep}{phase} eq q{x_Dist_Zilla};
- next if !($test && $top) && ${$dep}{phase} eq q{test};
- my $distname = $mcpan->module( $modname )->{distribution};
- if (${$dep}{phase} eq q{runtime}) {
- if (${$dep}{relationship} eq q{requires}) {
- $runtime{$distname} = 1;
- }
- else {
- $optional{$distname} = 1 if $recommend && $top;
- }
- }
- else { # configure, build
- $build{$distname} = 1;
- push @info, qq{[$name] suspicious dependency on $distname}
- unless exists $white_list{$distname};
- }
- }
- $deps_build{$name} = [keys %build];
- $deps_runtime{$name} = [keys %runtime];
- foreach my $distname (@{$deps_build{$name}}) {
- fetch( $distname, 0, 1 );
- }
- foreach my $distname (@{$deps_runtime{$name}}) {
- fetch( $distname, $need_target, $need_host );
- $need_dlopen{$name} ||= $need_dlopen{$distname};
- }
- foreach my $distname (keys %optional) {
- fetch( $distname, $need_target, $need_host );
- }
- }
- return;
- }
- foreach my $distname (@ARGV) {
- # Command-line's distributions
- fetch( $distname, !!$target, !!$host, 1 );
- }
- say scalar keys %dist, q{ packages fetched.} unless $quiet;
- # Buildroot package name: lowercase
- sub fsname {
- my $name = shift;
- $name =~ s|_|-|g;
- return q{perl-} . lc $name;
- }
- # Buildroot variable name: uppercase
- sub brname {
- my $name = shift;
- $name =~ s|-|_|g;
- return uc $name;
- }
- # Buildroot requires license name as in http://spdx.org/licenses/
- sub brlicense {
- my $license = shift;
- $license =~ s|apache_1_1|Apache-1.1|;
- $license =~ s|apache_2_0|Apache-2.0|;
- $license =~ s|artistic_2|Artistic-2.0|;
- $license =~ s|artistic|Artistic-1.0|;
- $license =~ s|lgpl_2_1|LGPL-2.1|;
- $license =~ s|lgpl_3_0|LGPL-3.0|;
- $license =~ s|gpl_2|GPL-2.0|;
- $license =~ s|gpl_3|GPL-3.0|;
- $license =~ s|mit|MIT|;
- $license =~ s|mozilla_1_1|Mozilla-1.1|;
- $license =~ s|openssl|OpenSSL|;
- $license =~ s|perl_5|Artistic or GPL-1.0+|;
- return $license;
- }
- while (my ($distname, $dist) = each %dist) {
- my $fsname = fsname( $distname );
- my $dirname = q{package/} . $fsname;
- my $cfgname = $dirname . q{/Config.in};
- my $mkname = $dirname . q{/} . $fsname . q{.mk};
- my $hashname = $dirname . q{/} . $fsname . q{.hash};
- my $brname = brname( $fsname );
- my $testname = q{support/testing/tests/package/test_} . lc $brname . q{.py};
- unless (-d $dirname) {
- mkdir $dirname;
- $new_pkgs = 1;
- }
- if ($need_target{$distname} && ($force || !-f $cfgname)) {
- $dist->{abstract} =~ s|\s+$||;
- $dist->{abstract} .= q{.} unless $dist->{abstract} =~ m|\.$|;
- my $abstract = wrap( q{}, qq{\t }, $dist->{abstract} );
- my $homepage = $dist->{resources}->{homepage} || qq{https://metacpan.org/release/${distname}};
- say qq{write ${cfgname}} unless $quiet;
- open my $fh, q{>}, $cfgname;
- say {$fh} qq{config BR2_PACKAGE_${brname}};
- say {$fh} qq{\tbool "${fsname}"};
- say {$fh} qq{\tdepends on !BR2_STATIC_LIBS} if $need_dlopen{$distname};
- foreach my $dep (sort @{$deps_runtime{$distname}}) {
- my $brdep = brname( fsname( $dep ) );
- say {$fh} qq{\tselect BR2_PACKAGE_${brdep} # runtime};
- }
- say {$fh} qq{\thelp};
- say {$fh} qq{\t ${abstract}\n} if $abstract;
- say {$fh} qq{\t ${homepage}};
- if ($need_dlopen{$distname}) {
- say {$fh} qq{\ncomment "${fsname} needs a toolchain w/ dynamic library"};
- say {$fh} qq{\tdepends on BR2_STATIC_LIBS};
- }
- close $fh;
- }
- if ($force || !-f $mkname) {
- my $version = $dist->{version};
- my ($path) = $dist->{download_url} =~ m|^[^:/?#]+://[^/?#]*([^?#]*)|;
- # this URL contains only the scheme, auth and path parts (but no query and fragment parts)
- # the scheme is not used, because the job is done by the BR download infrastructure
- # the auth part is not used, because we use $(BR2_CPAN_MIRROR)
- my ($filename, $directories, $suffix) = fileparse( $path, q{tar.gz}, q{tgz} );
- $directories =~ s|/$||;
- my @dependencies = map( { q{host-} . fsname( $_ ); } sort @{$deps_build{$distname}} );
- my $dependencies = join qq{ \\\n\t}, @dependencies;
- $dependencies = qq{\\\n\t} . $dependencies if scalar @dependencies > 1;
- my @host_dependencies = map { q{host-} . fsname( $_ ); } sort( @{$deps_build{$distname}},
- @{$deps_runtime{$distname}} );
- my $host_dependencies = join qq{ \\\n\t}, @host_dependencies;
- $host_dependencies = qq{\\\n\t} . $host_dependencies if scalar @host_dependencies > 1;
- my $license = brlicense( ref $dist->{license} eq 'ARRAY'
- ? join q{ or }, @{$dist->{license}}
- : $dist->{license} );
- my $license_files = join q{ }, sort keys %{$license_files{$distname}};
- if ($license_files && (!$license || $license eq q{unknown})) {
- push @info, qq{[$distname] undefined LICENSE, see $license_files};
- $license = q{???};
- }
- say qq{write ${mkname}} unless $quiet;
- open my $fh, q{>}, $mkname;
- say {$fh} qq{################################################################################};
- say {$fh} qq{#};
- say {$fh} qq{# ${fsname}};
- say {$fh} qq{#};
- say {$fh} qq{################################################################################};
- say {$fh} qq{};
- say {$fh} qq{${brname}_VERSION = ${version}};
- say {$fh} qq{${brname}_SOURCE = ${distname}-\$(${brname}_VERSION).${suffix}};
- say {$fh} qq{${brname}_SITE = \$(BR2_CPAN_MIRROR)${directories}};
- say {$fh} qq{${brname}_DEPENDENCIES = ${dependencies}} if $need_target{$distname} && $dependencies;
- say {$fh} qq{HOST_${brname}_DEPENDENCIES = ${host_dependencies}} if $need_host{$distname} && $host_dependencies;
- say {$fh} qq{${brname}_LICENSE = ${license}} if $license;
- say {$fh} qq{${brname}_LICENSE_FILES = ${license_files}} if $license_files;
- say {$fh} qq{${brname}_DISTNAME = ${distname}};
- say {$fh} qq{};
- say {$fh} qq{\$(eval \$(perl-package))} if $need_target{$distname};
- say {$fh} qq{\$(eval \$(host-perl-package))} if $need_host{$distname};
- close $fh;
- }
- if ($force || !-f $hashname) {
- my ($checksum, $filename) = get_checksum($dist->{download_url});
- my $md5 = $checksum->{md5};
- my $sha256 = $checksum->{sha256};
- say qq{write ${hashname}} unless $quiet;
- open my $fh, q{>}, $hashname;
- say {$fh} qq{# retrieved by scancpan from ${mirror}/};
- say {$fh} qq{md5 ${md5} ${filename}};
- say {$fh} qq{sha256 ${sha256} ${filename}};
- my %license_files = %{$license_files{$distname}};
- if (scalar keys %license_files) {
- say {$fh} q{};
- say {$fh} qq{# computed by scancpan};
- foreach my $license (sort keys %license_files) {
- my $digest = $license_files{$license};
- say {$fh} qq{sha256 ${digest} ${license}};
- }
- }
- close $fh;
- }
- if (want_test( $distname ) && ($force || !-f $testname)) {
- my $classname = $distname;
- $classname =~ s|-||g;
- my $modname = $distname;
- $modname =~ s|-|::|g;
- my $mark = $is_xs{$distname} ? q{ XS} : q{};
- my @indirect = (get_indirect_dependencies( $distname ));
- say qq{write ${testname}} unless $quiet;
- open my $fh, q{>}, $testname;
- say {$fh} qq{from tests.package.test_perl import TestPerlBase};
- say {$fh} qq{};
- say {$fh} qq{};
- say {$fh} qq{class TestPerl${classname}(TestPerlBase):};
- say {$fh} qq{ """};
- say {$fh} qq{ package:};
- say {$fh} qq{ ${distname}${mark}};
- say {$fh} qq{ direct dependencies:};
- foreach my $dep (sort @{$deps_runtime{$distname}}) {
- $mark = $is_xs{$dep} ? q{ XS} : q{};
- say {$fh} qq{ ${dep}${mark}};
- }
- if (scalar @indirect > 0) {
- say {$fh} qq{ indirect dependencies:};
- foreach my $dep (sort @indirect) {
- $mark = $is_xs{$dep} ? q{ XS} : q{};
- say {$fh} qq{ ${dep}${mark}};
- }
- }
- say {$fh} qq{ """};
- say {$fh} qq{};
- say {$fh} qq{ config = TestPerlBase.config + \\};
- say {$fh} qq{ """};
- say {$fh} qq{ BR2_PACKAGE_PERL=y};
- say {$fh} qq{ BR2_PACKAGE_${brname}=y};
- say {$fh} qq{ """};
- say {$fh} qq{};
- say {$fh} qq{ def test_run(self):};
- say {$fh} qq{ self.login()};
- say {$fh} qq{ self.module_test("${modname}")};
- close $fh;
- }
- }
- if ($new_pkgs) {
- my %pkg;
- my $cfgname = q{package/Config.in};
- if (-f $cfgname) {
- open my $fh, q{<}, $cfgname;
- while (<$fh>) {
- chomp;
- $pkg{$_} = 1 if m|package/perl-|;
- }
- close $fh;
- }
- foreach my $distname (keys %need_target) {
- my $fsname = fsname( $distname );
- $pkg{qq{\tsource "package/${fsname}/Config.in"}} = 1;
- }
- say qq{${cfgname} must contain the following lines:};
- say join qq{\n}, sort keys %pkg;
- }
- say join qq{\n}, @info;
- __END__
- =head1 NAME
- utils/scancpan Try-Tiny Moo
- =head1 SYNOPSIS
- utils/scancpan [options] [distname ...]
- Options:
- -help
- -man
- -quiet
- -force
- -target/-notarget
- -host/-nohost
- -recommend
- -test
- =head1 OPTIONS
- =over 8
- =item B<-help>
- Prints a brief help message and exits.
- =item B<-man>
- Prints the manual page and exits.
- =item B<-quiet>
- Executes without output
- =item B<-force>
- Forces the overwriting of existing files.
- =item B<-target/-notarget>
- Switches package generation for the target variant (the default is C<-target>).
- =item B<-host/-nohost>
- Switches package generation for the host variant (the default is C<-nohost>).
- =item B<-recommend>
- Adds I<recommended> dependencies.
- =item B<-test>
- Adds dependencies for test.
- =back
- =head1 DESCRIPTION
- This script creates templates of the Buildroot package files for all the
- Perl/CPAN distributions required by the specified distnames. The
- dependencies and metadata are fetched from https://metacpan.org/.
- After running this script, it is necessary to check the generated files.
- For distributions that link against a target library, you have to add the
- buildroot package name for that library to the DEPENDENCIES variable.
- See the Buildroot documentation for details on the usage of the Perl
- infrastructure.
- The major version of the host perl must be aligned on the target one,
- in order to work with the right CoreList data.
- =head1 LICENSE
- Copyright (C) 2013-2018 by Francois Perrad <francois.perrad@gadz.org>
- 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- This script is a part of Buildroot.
- This script requires the module C<MetaCPAN::API::Tiny> (version 1.131730)
- which was included at the beginning of this file by the tool C<fatpack>.
- See L<https://metacpan.org/release/NPEREZ/MetaCPAN-API-Tiny-1.131730>.
- See L<https://metacpan.org/release/App-FatPacker>.
- These both libraries are free software and may be distributed under the same
- terms as perl itself.
- And perl may be distributed under the terms of Artistic v1 or GPL v1 license.
- =cut
|