diff --git a/bin/generate_sitemap.pl b/bin/generate_sitemap.pl
index 0905f1df89..2decbb6af4 100755
--- a/bin/generate_sitemap.pl
+++ b/bin/generate_sitemap.pl
@@ -5,37 +5,41 @@
use strict;
use warnings;
-use FindBin qw ($Bin);
-use lib "$Bin/../lib";
-
+use File::Basename;
+use File::Spec;
+use Cwd;
+use Config::ZOMG;
+my $root_dir;
+
+BEGIN {
+ my $bin_dir = File::Basename::dirname(__FILE__);
+ $root_dir
+ = Cwd::abs_path( File::Spec->catdir( $bin_dir, File::Spec->updir ) );
+}
+use lib "$root_dir/lib";
use MetaCPAN::Sitemap;
-my $out_dir = "$Bin/../root/static/sitemaps/";
-mkdir $out_dir;
-
-my @parts = (
-
- # For authors, we're looking for the pauseid, and want to build a URL
- # with 'author' in the path.
-
- {
- object_type => 'author',
- field_name => 'pauseid',
- xml_file => "$out_dir/authors.xml.gz",
- cpan_directory => 'author',
- },
-
- # For releases, we're looking for a download URL; since we're not
- # building a URL, the cpan_directory is missing, but we also want to
- # filter on only the 'latest' entries.
-
- {
- object_type => 'release',
- field_name => 'distribution',
- xml_file => "$out_dir/releases.xml.gz",
- cpan_directory => 'release',
- filter => { status => 'latest' },
- }
+my $config = Config::ZOMG->open(
+ name => 'MetaCPAN::Web',
+ path => $root_dir,
);
-MetaCPAN::Sitemap->new($_)->process for @parts;
+my $out_dir = "$root_dir/root/static/sitemaps/";
+mkdir $out_dir;
+
+my $web_host = $config->{web_host};
+$web_host =~ s{/\z}{};
+my $sitemaps = $config->{sitemap};
+
+for my $file ( sort keys %$sitemaps ) {
+ my %sm_config = %{ $sitemaps->{$file} };
+ my $full_file = $out_dir . $file;
+ $sm_config{url_prefix} ||= do {
+ my $metacpan_url = $sm_config{metacpan_url};
+ s{/\z}{}, s{\A/}{} for $metacpan_url;
+ "$web_host/$metacpan_url/";
+ };
+ $sm_config{api_secure} = $config->{api_secure};
+ my $sitemap = MetaCPAN::Sitemap->new(%sm_config);
+ $sitemap->write($full_file);
+}
diff --git a/cpanfile b/cpanfile
index 08c846c458..687ba237fe 100644
--- a/cpanfile
+++ b/cpanfile
@@ -1,4 +1,3 @@
-requires 'AnyEvent::Curl::Multi';
requires 'CHI';
requires 'CPAN::Changes', '0.21';
requires 'CPAN::Meta', '2.141520'; # Avoid issues with List::Util dep under carton install.
@@ -32,6 +31,7 @@ requires 'Encode', '2.51';
requires 'Exporter';
requires 'File::Path';
requires 'Format::Human::Bytes';
+requires 'Future';
requires 'Getopt::Long::Descriptive';
requires 'Gravatar::URL';
requires 'HTML::Escape';
@@ -43,6 +43,9 @@ requires 'HTTP::Request';
requires 'HTTP::Request::Common';
requires 'Hash::AsObject';
requires 'Hash::Merge';
+requires 'IO::Async::Loop';
+requires 'IO::Async::SSL';
+requires 'IO::Socket::SSL';
requires 'Importer';
requires 'JavaScript::Minifier::XS';
requires 'List::Util', '1.45';
@@ -54,18 +57,16 @@ requires 'Module::Build::Tiny', '0.037';
requires 'Module::Runtime';
requires 'Moo', '2.000002';
requires 'Moose', '2.1605';
-requires 'MooseX::ClassAttribute';
requires 'MooseX::Fastly::Role', '0.03';
requires 'MooseX::Role::Parameterized', '1.02';
-requires 'MooseX::StrictConstructor';
requires 'MooseX::Types::Common::Numeric';
requires 'MooseX::Types::Common::String';
requires 'MooseX::Types::Moose';
requires 'MooseX::Types::URI', '0.08';
+requires 'Net::Async::HTTP';
requires 'Net::Fastly', '1.05';
requires 'Params::ValidationCompiler';
requires 'Path::Tiny', '0.076';
-requires 'PerlIO::gzip';
requires 'Plack', '1.0039';
requires 'Plack::Middleware::ReverseProxy';
requires 'Plack::Middleware::Runtime';
@@ -92,7 +93,6 @@ requires 'Try::Tiny', '0.24';
requires 'URI', '1.71';
requires 'URI::Escape';
requires 'XML::Feed';
-requires 'XML::Simple';
requires 'YAML', '1.15'; # fix dep chain issue
test_requires 'App::Prove';
diff --git a/cpanfile.snapshot b/cpanfile.snapshot
index f87bf631f5..a5a242fa8e 100644
--- a/cpanfile.snapshot
+++ b/cpanfile.snapshot
@@ -7,86 +7,6 @@ DISTRIBUTIONS
Algorithm::Diff::_impl 1.1903
requirements:
ExtUtils::MakeMaker 0
- Any-Moose-0.27
- pathname: E/ET/ETHER/Any-Moose-0.27.tar.gz
- provides:
- Any::Moose 0.27
- requirements:
- Carp 0
- ExtUtils::MakeMaker 0
- Moose 0
- perl 5.006002
- strict 0
- warnings 0
- Any-URI-Escape-0.01
- pathname: P/PH/PHRED/Any-URI-Escape-0.01.tar.gz
- provides:
- Any::URI::Escape 0.01
- requirements:
- ExtUtils::MakeMaker 0
- URI::Escape 0
- AnyEvent-7.13
- pathname: M/ML/MLEHMANN/AnyEvent-7.13.tar.gz
- provides:
- AE undef
- AE::Log::COLLECT undef
- AE::Log::FILTER undef
- AE::Log::LOG undef
- AnyEvent 7.13
- AnyEvent::Base 7.13
- AnyEvent::CondVar 7.13
- AnyEvent::CondVar::Base 7.13
- AnyEvent::DNS undef
- AnyEvent::Debug undef
- AnyEvent::Debug::Backtrace undef
- AnyEvent::Debug::Wrap undef
- AnyEvent::Debug::Wrapped undef
- AnyEvent::Debug::shell undef
- AnyEvent::Handle undef
- AnyEvent::IO undef
- AnyEvent::IO::IOAIO undef
- AnyEvent::IO::Perl undef
- AnyEvent::Impl::Cocoa undef
- AnyEvent::Impl::EV undef
- AnyEvent::Impl::Event undef
- AnyEvent::Impl::EventLib undef
- AnyEvent::Impl::FLTK undef
- AnyEvent::Impl::Glib undef
- AnyEvent::Impl::IOAsync undef
- AnyEvent::Impl::Irssi undef
- AnyEvent::Impl::POE undef
- AnyEvent::Impl::Perl undef
- AnyEvent::Impl::Qt undef
- AnyEvent::Impl::Qt::Io undef
- AnyEvent::Impl::Qt::Timer undef
- AnyEvent::Impl::Tk undef
- AnyEvent::Impl::UV undef
- AnyEvent::Log undef
- AnyEvent::Log::COLLECT undef
- AnyEvent::Log::Ctx undef
- AnyEvent::Log::FILTER undef
- AnyEvent::Log::LOG undef
- AnyEvent::Loop undef
- AnyEvent::Socket undef
- AnyEvent::Strict undef
- AnyEvent::TLS undef
- AnyEvent::Util undef
- requirements:
- Canary::Stability 0
- ExtUtils::MakeMaker 6.52
- AnyEvent-Curl-Multi-1.1
- pathname: O/OT/OTTERLEY/AnyEvent-Curl-Multi-1.1.tar.gz
- provides:
- AnyEvent::Curl::Multi 1.1
- AnyEvent::Curl::Multi::Handle 1.1
- requirements:
- AnyEvent 5
- ExtUtils::MakeMaker 0
- HTTP::Request 0
- HTTP::Response 0
- Object::Event 1
- Test::More 0
- WWW::Curl 4.14
Apache-LogFormat-Compiler-0.35
pathname: K/KA/KAZEBURO/Apache-LogFormat-Compiler-0.35.tar.gz
provides:
@@ -294,14 +214,6 @@ DISTRIBUTIONS
requirements:
ExtUtils::MakeMaker 0
Test::Exception 0
- Carp-Clan-Share-0.013
- pathname: R/RK/RKRIMEN/Carp-Clan-Share-0.013.tar.gz
- provides:
- Carp::Clan::Share 0.013
- requirements:
- Carp::Clan 0
- ExtUtils::MakeMaker 6.42
- Test::More 0
Catalyst-Action-REST-1.20
pathname: J/JJ/JJNAPIORK/Catalyst-Action-REST-1.20.tar.gz
provides:
@@ -745,17 +657,6 @@ DISTRIBUTIONS
requirements:
ExtUtils::MakeMaker 0
Test::More 0
- Clone-PP-1.07
- pathname: N/NE/NEILB/Clone-PP-1.07.tar.gz
- provides:
- Clone::PP 1.07
- requirements:
- Exporter 0
- ExtUtils::MakeMaker 0
- perl 5.006
- strict 0
- vars 0
- warnings 0
Code-TidyAll-0.59
pathname: D/DR/DROLSKY/Code-TidyAll-0.59.tar.gz
provides:
@@ -860,6 +761,7 @@ DISTRIBUTIONS
Config::Any::XML undef
Config::Any::YAML undef
requirements:
+ Config::General 2.47
Module::Pluggable::Object 3.6
Config-General-2.63
pathname: T/TL/TLINDEN/Config-General-2.63.tar.gz
@@ -886,26 +788,6 @@ DISTRIBUTIONS
Mixin::Linewise::Writers 0
strict 0
warnings 0
- Config-JFDI-0.065
- pathname: R/RO/ROKR/Config-JFDI-0.065.tar.gz
- provides:
- Config::JFDI 0.065
- Config::JFDI::Carp undef
- Config::JFDI::Source::Loader undef
- requirements:
- Any::Moose 0
- Carp::Clan::Share 0
- Clone 0
- Config::Any 0
- Config::General 0
- Data::Visitor 0.24
- ExtUtils::MakeMaker 6.31
- Getopt::Usaginator 0
- Hash::Merge::Simple 0
- List::MoreUtils 0
- Path::Class 0
- Sub::Install 0
- Test::Most 0
Config-Tiny-2.23
pathname: R/RS/RSAVAGE/Config-Tiny-2.23.tgz
provides:
@@ -988,29 +870,6 @@ DISTRIBUTIONS
Data::Page 2
ExtUtils::MakeMaker 0
Test::More 0.1
- Data-Printer-0.39
- pathname: G/GA/GARU/Data-Printer-0.39.tar.gz
- provides:
- DDP undef
- Data::Printer 0.39
- Data::Printer::Filter undef
- Data::Printer::Filter::DB undef
- Data::Printer::Filter::DateTime undef
- Data::Printer::Filter::Digest undef
- requirements:
- Carp 0
- Clone::PP 0
- ExtUtils::MakeMaker 0
- Fcntl 0
- File::HomeDir 0.91
- File::Spec 0
- File::Temp 0
- Package::Stash 0.3
- Scalar::Util 0
- Sort::Naturally 0
- Term::ANSIColor 3
- Test::More 0.88
- version 0.77
Data-UUID-1.221
pathname: R/RJ/RJBS/Data-UUID-1.221.tar.gz
provides:
@@ -1571,19 +1430,6 @@ DISTRIBUTIONS
perl 5.008004
strict 0
warnings 0
- Devel-CheckCompiler-0.07
- pathname: S/SY/SYOHEX/Devel-CheckCompiler-0.07.tar.gz
- provides:
- Devel::AssertC99 undef
- Devel::CheckCompiler 0.07
- requirements:
- Exporter 0
- ExtUtils::CBuilder 0
- File::Temp 0
- Module::Build::Tiny 0.035
- Test::More 0.98
- parent 0
- perl 5.008001
Devel-Confess-0.009004
pathname: H/HA/HAARG/Devel-Confess-0.009004.tar.gz
provides:
@@ -1917,6 +1763,18 @@ DISTRIBUTIONS
requirements:
ExtUtils::MakeMaker 6.42
Test::More 0
+ Future-0.34
+ pathname: P/PE/PEVANS/Future-0.34.tar.gz
+ provides:
+ Future 0.34
+ Future::Mutex 0.34
+ Future::Utils 0.34
+ Test::Future 0.34
+ requirements:
+ Carp 1.25
+ Test::Builder::Module 0
+ Time::HiRes 0
+ perl 5.008
Getopt-Long-Descriptive-0.100
pathname: R/RJ/RJBS/Getopt-Long-Descriptive-0.100.tar.gz
provides:
@@ -1936,16 +1794,6 @@ DISTRIBUTIONS
overload 0
strict 0
warnings 0
- Getopt-Usaginator-0.0012
- pathname: R/RO/ROKR/Getopt-Usaginator-0.0012.tar.gz
- provides:
- Getopt::Usaginator 0.0012
- requirements:
- ExtUtils::MakeMaker 6.31
- File::Spec 0
- IPC::Open3 0
- Package::Pkg 0.0014
- Test::Most 0
Gravatar-URL-1.07
pathname: M/MS/MSCHWERN/Gravatar-URL-1.07.tar.gz
provides:
@@ -2300,6 +2148,69 @@ DISTRIBUTIONS
perl 5.006
strict 0
warnings 0
+ IO-Async-0.71
+ pathname: P/PE/PEVANS/IO-Async-0.71.tar.gz
+ provides:
+ IO::Async 0.71
+ IO::Async::Channel 0.71
+ IO::Async::ChildManager 0.71
+ IO::Async::Debug 0.71
+ IO::Async::File 0.71
+ IO::Async::FileStream 0.71
+ IO::Async::Function 0.71
+ IO::Async::Future 0.71
+ IO::Async::Handle 0.71
+ IO::Async::Listener 0.71
+ IO::Async::Loop 0.71
+ IO::Async::Loop::Poll 0.71
+ IO::Async::Loop::Select 0.71
+ IO::Async::LoopTests 0.71
+ IO::Async::Notifier 0.71
+ IO::Async::OS 0.71
+ IO::Async::OS::MSWin32 0.71
+ IO::Async::OS::cygwin 0.71
+ IO::Async::OS::linux 0.71
+ IO::Async::PID 0.71
+ IO::Async::Process 0.71
+ IO::Async::Protocol 0.71
+ IO::Async::Protocol::LineStream 0.71
+ IO::Async::Protocol::Stream 0.71
+ IO::Async::Resolver 0.71
+ IO::Async::Routine 0.71
+ IO::Async::Signal 0.71
+ IO::Async::Socket 0.71
+ IO::Async::Stream 0.71
+ IO::Async::Test 0.71
+ IO::Async::Timer 0.71
+ IO::Async::Timer::Absolute 0.71
+ IO::Async::Timer::Countdown 0.71
+ IO::Async::Timer::Periodic 0.71
+ requirements:
+ Exporter 5.57
+ File::stat 0
+ Future 0.33
+ Future::Utils 0.18
+ IO::Poll 0
+ Module::Build 0.4004
+ Socket 2.007
+ Storable 0
+ Struct::Dumb 0
+ Time::HiRes 0
+ perl 5.008004
+ IO-Async-SSL-0.19
+ pathname: P/PE/PEVANS/IO-Async-SSL-0.19.tar.gz
+ provides:
+ IO::Async::SSL 0.19
+ IO::Async::SSLStream 0.19
+ requirements:
+ Future 0.33
+ IO::Async::Handle 0.29
+ IO::Async::Loop 0.66
+ IO::Async::OS 0
+ IO::Async::Protocol::Stream 0
+ IO::Async::Stream 0.59
+ IO::Socket::SSL 1.968
+ Test::More 0.88
IO-HTML-1.001
pathname: C/CJ/CJM/IO-HTML-1.001.tar.gz
provides:
@@ -2402,7 +2313,6 @@ DISTRIBUTIONS
JSON::MaybeXS 1.003009
requirements:
Carp 0
- Cpanel::JSON::XS 2.3310
ExtUtils::CBuilder 0.27
ExtUtils::MakeMaker 0
File::Spec 0
@@ -2453,19 +2363,6 @@ DISTRIBUTIONS
requirements:
ExtUtils::MakeMaker 0
Test::More 0
- List-AllUtils-0.14
- pathname: D/DR/DROLSKY/List-AllUtils-0.14.tar.gz
- provides:
- List::AllUtils 0.14
- requirements:
- Exporter 0
- ExtUtils::MakeMaker 0
- List::SomeUtils 0.50
- List::Util 1.45
- List::UtilsBy 0.10
- base 0
- strict 0
- warnings 0
List-Compare-0.53
pathname: J/JK/JKEENAN/List-Compare-0.53.tar.gz
provides:
@@ -2512,13 +2409,6 @@ DISTRIBUTIONS
perl 5.006
strict 0
warnings 0
- List-UtilsBy-0.10
- pathname: P/PE/PEVANS/List-UtilsBy-0.10.tar.gz
- provides:
- List::UtilsBy 0.10
- requirements:
- Exporter 5.57
- Module::Build 0.4004
Log-Any-1.049
pathname: P/PR/PREACTION/Log-Any-1.049.tar.gz
provides:
@@ -2825,21 +2715,6 @@ DISTRIBUTIONS
perl 5.006
strict 0
warnings 0
- Module-Build-XSUtil-0.16
- pathname: H/HI/HIDEAKIO/Module-Build-XSUtil-0.16.tar.gz
- provides:
- Module::Build::XSUtil 0.16
- requirements:
- Devel::CheckCompiler 0
- Devel::PPPort 0
- Exporter 0
- ExtUtils::CBuilder 0
- File::Basename 0
- File::Path 0
- Module::Build 0.4005
- XSLoader 0
- parent 0
- perl 5.008005
Module-Implementation-0.09
pathname: D/DR/DROLSKY/Module-Implementation-0.09.tar.gz
provides:
@@ -3314,33 +3189,6 @@ DISTRIBUTIONS
parent 0.223
strict 1.03
warnings 1.03
- MooseX-ClassAttribute-0.29
- pathname: D/DR/DROLSKY/MooseX-ClassAttribute-0.29.tar.gz
- provides:
- MooseX::ClassAttribute 0.29
- MooseX::ClassAttribute::Meta::Role::Attribute 0.29
- MooseX::ClassAttribute::Trait::Application 0.29
- MooseX::ClassAttribute::Trait::Application::ToClass 0.29
- MooseX::ClassAttribute::Trait::Application::ToRole 0.29
- MooseX::ClassAttribute::Trait::Attribute 0.29
- MooseX::ClassAttribute::Trait::Class 0.29
- MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes 0.29
- MooseX::ClassAttribute::Trait::Role 0.29
- MooseX::ClassAttribute::Trait::Role::Composite 0.29
- requirements:
- ExtUtils::MakeMaker 0
- List::Util 1.45
- Moose 2.00
- Moose::Exporter 0
- Moose::Meta::Role::Attribute 0
- Moose::Role 0
- Moose::Util 0
- Moose::Util::MetaRole 0
- Scalar::Util 0
- namespace::autoclean 0.11
- namespace::clean 0.20
- strict 0
- warnings 0
MooseX-Emulate-Class-Accessor-Fast-0.00903
pathname: F/FL/FLORA/MooseX-Emulate-Class-Accessor-Fast-0.00903.tar.gz
provides:
@@ -3551,45 +3399,6 @@ DISTRIBUTIONS
perl 5.006
strict 0
warnings 0
- Mouse-v2.4.9
- pathname: S/SY/SYOHEX/Mouse-v2.4.9.tar.gz
- provides:
- Mouse v2.4.9
- Mouse::Exporter undef
- Mouse::Meta::Attribute undef
- Mouse::Meta::Class undef
- Mouse::Meta::Method undef
- Mouse::Meta::Method::Accessor undef
- Mouse::Meta::Method::Constructor undef
- Mouse::Meta::Method::Delegation undef
- Mouse::Meta::Method::Destructor undef
- Mouse::Meta::Module undef
- Mouse::Meta::Role undef
- Mouse::Meta::Role::Application undef
- Mouse::Meta::Role::Application::RoleSummation undef
- Mouse::Meta::Role::Composite undef
- Mouse::Meta::Role::Method undef
- Mouse::Meta::TypeConstraint undef
- Mouse::Object undef
- Mouse::PurePerl undef
- Mouse::Role v2.4.9
- Mouse::Spec v2.4.9
- Mouse::Tiny v2.4.8
- Mouse::TypeRegistry undef
- Mouse::Util v2.4.9
- Mouse::Util::MetaRole undef
- Mouse::Util::TypeConstraints undef
- Squirrel undef
- Squirrel::Role undef
- Test::Mouse undef
- ouse undef
- requirements:
- ExtUtils::CBuilder 0
- Module::Build 0.4005
- Module::Build::XSUtil 0.16
- Scalar::Util 1.14
- XSLoader 0.02
- perl 5.008005
Mozilla-CA-20160104
pathname: A/AB/ABH/Mozilla-CA-20160104.tar.gz
provides:
@@ -3598,6 +3407,29 @@ DISTRIBUTIONS
ExtUtils::MakeMaker 0
Test 0
perl 5.006
+ Net-Async-HTTP-0.41
+ pathname: P/PE/PEVANS/Net-Async-HTTP-0.41.tar.gz
+ provides:
+ Net::Async::HTTP 0.41
+ Net::Async::HTTP::Connection 0.41
+ Net::Async::HTTP::StallTimer 0.41
+ requirements:
+ Future 0.28
+ Future::Utils 0.16
+ HTTP::Cookies 0
+ HTTP::Request 0
+ HTTP::Request::Common 0
+ HTTP::Response 0
+ IO::Async::Loop 0.59
+ IO::Async::Stream 0.59
+ IO::Async::Test 0
+ IO::Async::Timer::Countdown 0
+ List::Util 1.29
+ Struct::Dumb 0.07
+ Test::Identity 0
+ Test::More 0.88
+ Test::Refcount 0
+ URI 0
Net-CIDR-Lite-0.21
pathname: D/DO/DOUGW/Net-CIDR-Lite-0.21.tar.gz
provides:
@@ -3833,15 +3665,6 @@ DISTRIBUTIONS
Carp 0
ExtUtils::MakeMaker 0
POSIX 0
- Object-Event-1.23
- pathname: E/EL/ELMEX/Object-Event-1.23.tar.gz
- provides:
- Object::Event 1.23
- requirements:
- AnyEvent 3.5
- ExtUtils::MakeMaker 0
- Test::More 0
- common::sense 0
Object-Signature-1.07
pathname: A/AD/ADAMK/Object-Signature-1.07.tar.gz
provides:
@@ -4095,20 +3918,6 @@ DISTRIBUTIONS
Sub::Name 0
strict 0
warnings 0
- Package-Pkg-0.0020
- pathname: R/RO/ROKR/Package-Pkg-0.0020.tar.gz
- provides:
- Package::Pkg 0.0020
- Package::Pkg::Lexicon undef
- Package::Pkg::Loader undef
- requirements:
- Class::Load 0
- Clone 0
- ExtUtils::MakeMaker 6.30
- Mouse 0
- Sub::Install 0
- Test::Most 0
- Try::Tiny 0
Package-Stash-0.37
pathname: D/DO/DOY/Package-Stash-0.37.tar.gz
provides:
@@ -4271,204 +4080,204 @@ DISTRIBUTIONS
perl 5.008001
strict 0
warnings 0
- Perl-Critic-1.126
- pathname: T/TH/THALJEF/Perl-Critic-1.126.tar.gz
- provides:
- Perl::Critic 1.126
- Perl::Critic::Annotation 1.126
- Perl::Critic::Command 1.126
- Perl::Critic::Config 1.126
- Perl::Critic::Document 1.126
- Perl::Critic::Exception 1.126
- Perl::Critic::Exception::AggregateConfiguration 1.126
- Perl::Critic::Exception::Configuration 1.126
- Perl::Critic::Exception::Configuration::Generic 1.126
- Perl::Critic::Exception::Configuration::NonExistentPolicy 1.126
- Perl::Critic::Exception::Configuration::Option 1.126
- Perl::Critic::Exception::Configuration::Option::Global 1.126
- Perl::Critic::Exception::Configuration::Option::Global::ExtraParameter 1.126
- Perl::Critic::Exception::Configuration::Option::Global::ParameterValue 1.126
- Perl::Critic::Exception::Configuration::Option::Policy 1.126
- Perl::Critic::Exception::Configuration::Option::Policy::ExtraParameter 1.126
- Perl::Critic::Exception::Configuration::Option::Policy::ParameterValue 1.126
- Perl::Critic::Exception::Fatal 1.126
- Perl::Critic::Exception::Fatal::Generic 1.126
- Perl::Critic::Exception::Fatal::Internal 1.126
- Perl::Critic::Exception::Fatal::PolicyDefinition 1.126
- Perl::Critic::Exception::IO 1.126
- Perl::Critic::Exception::Parse 1.126
- Perl::Critic::OptionsProcessor 1.126
- Perl::Critic::Policy 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitBooleanGrep 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitComplexMappings 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitLvalueSubstr 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitReverseSortBlock 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitSleepViaSelect 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitStringyEval 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitStringySplit 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitUniversalCan 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitUniversalIsa 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitUselessTopic 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitVoidGrep 1.126
- Perl::Critic::Policy::BuiltinFunctions::ProhibitVoidMap 1.126
- Perl::Critic::Policy::BuiltinFunctions::RequireBlockGrep 1.126
- Perl::Critic::Policy::BuiltinFunctions::RequireBlockMap 1.126
- Perl::Critic::Policy::BuiltinFunctions::RequireGlobFunction 1.126
- Perl::Critic::Policy::BuiltinFunctions::RequireSimpleSortBlock 1.126
- Perl::Critic::Policy::ClassHierarchies::ProhibitAutoloading 1.126
- Perl::Critic::Policy::ClassHierarchies::ProhibitExplicitISA 1.126
- Perl::Critic::Policy::ClassHierarchies::ProhibitOneArgBless 1.126
- Perl::Critic::Policy::CodeLayout::ProhibitHardTabs 1.126
- Perl::Critic::Policy::CodeLayout::ProhibitParensWithBuiltins 1.126
- Perl::Critic::Policy::CodeLayout::ProhibitQuotedWordLists 1.126
- Perl::Critic::Policy::CodeLayout::ProhibitTrailingWhitespace 1.126
- Perl::Critic::Policy::CodeLayout::RequireConsistentNewlines 1.126
- Perl::Critic::Policy::CodeLayout::RequireTidyCode 1.126
- Perl::Critic::Policy::CodeLayout::RequireTrailingCommas 1.126
- Perl::Critic::Policy::ControlStructures::ProhibitCStyleForLoops 1.126
- Perl::Critic::Policy::ControlStructures::ProhibitCascadingIfElse 1.126
- Perl::Critic::Policy::ControlStructures::ProhibitDeepNests 1.126
- Perl::Critic::Policy::ControlStructures::ProhibitLabelsWithSpecialBlockNames 1.126
- Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions 1.126
- Perl::Critic::Policy::ControlStructures::ProhibitNegativeExpressionsInUnlessAndUntilConditions 1.126
- Perl::Critic::Policy::ControlStructures::ProhibitPostfixControls 1.126
- Perl::Critic::Policy::ControlStructures::ProhibitUnlessBlocks 1.126
- Perl::Critic::Policy::ControlStructures::ProhibitUnreachableCode 1.126
- Perl::Critic::Policy::ControlStructures::ProhibitUntilBlocks 1.126
- Perl::Critic::Policy::ControlStructures::ProhibitYadaOperator 1.126
- Perl::Critic::Policy::Documentation::PodSpelling 1.126
- Perl::Critic::Policy::Documentation::RequirePackageMatchesPodName 1.126
- Perl::Critic::Policy::Documentation::RequirePodAtEnd 1.126
- Perl::Critic::Policy::Documentation::RequirePodLinksIncludeText 1.126
- Perl::Critic::Policy::Documentation::RequirePodSections 1.126
- Perl::Critic::Policy::ErrorHandling::RequireCarping 1.126
- Perl::Critic::Policy::ErrorHandling::RequireCheckingReturnValueOfEval 1.126
- Perl::Critic::Policy::InputOutput::ProhibitBacktickOperators 1.126
- Perl::Critic::Policy::InputOutput::ProhibitBarewordFileHandles 1.126
- Perl::Critic::Policy::InputOutput::ProhibitExplicitStdin 1.126
- Perl::Critic::Policy::InputOutput::ProhibitInteractiveTest 1.126
- Perl::Critic::Policy::InputOutput::ProhibitJoinedReadline 1.126
- Perl::Critic::Policy::InputOutput::ProhibitOneArgSelect 1.126
- Perl::Critic::Policy::InputOutput::ProhibitReadlineInForLoop 1.126
- Perl::Critic::Policy::InputOutput::ProhibitTwoArgOpen 1.126
- Perl::Critic::Policy::InputOutput::RequireBracedFileHandleWithPrint 1.126
- Perl::Critic::Policy::InputOutput::RequireBriefOpen 1.126
- Perl::Critic::Policy::InputOutput::RequireCheckedClose 1.126
- Perl::Critic::Policy::InputOutput::RequireCheckedOpen 1.126
- Perl::Critic::Policy::InputOutput::RequireCheckedSyscalls 1.126
- Perl::Critic::Policy::InputOutput::RequireEncodingWithUTF8Layer 1.126
- Perl::Critic::Policy::Miscellanea::ProhibitFormats 1.126
- Perl::Critic::Policy::Miscellanea::ProhibitTies 1.126
- Perl::Critic::Policy::Miscellanea::ProhibitUnrestrictedNoCritic 1.126
- Perl::Critic::Policy::Miscellanea::ProhibitUselessNoCritic 1.126
- Perl::Critic::Policy::Modules::ProhibitAutomaticExportation 1.126
- Perl::Critic::Policy::Modules::ProhibitConditionalUseStatements 1.126
- Perl::Critic::Policy::Modules::ProhibitEvilModules 1.126
- Perl::Critic::Policy::Modules::ProhibitExcessMainComplexity 1.126
- Perl::Critic::Policy::Modules::ProhibitMultiplePackages 1.126
- Perl::Critic::Policy::Modules::RequireBarewordIncludes 1.126
- Perl::Critic::Policy::Modules::RequireEndWithOne 1.126
- Perl::Critic::Policy::Modules::RequireExplicitPackage 1.126
- Perl::Critic::Policy::Modules::RequireFilenameMatchesPackage 1.126
- Perl::Critic::Policy::Modules::RequireNoMatchVarsWithUseEnglish 1.126
- Perl::Critic::Policy::Modules::RequireVersionVar 1.126
- Perl::Critic::Policy::NamingConventions::Capitalization 1.126
- Perl::Critic::Policy::NamingConventions::ProhibitAmbiguousNames 1.126
- Perl::Critic::Policy::Objects::ProhibitIndirectSyntax 1.126
- Perl::Critic::Policy::References::ProhibitDoubleSigils 1.126
- Perl::Critic::Policy::RegularExpressions::ProhibitCaptureWithoutTest 1.126
- Perl::Critic::Policy::RegularExpressions::ProhibitComplexRegexes 1.126
- Perl::Critic::Policy::RegularExpressions::ProhibitEnumeratedClasses 1.126
- Perl::Critic::Policy::RegularExpressions::ProhibitEscapedMetacharacters 1.126
- Perl::Critic::Policy::RegularExpressions::ProhibitFixedStringMatches 1.126
- Perl::Critic::Policy::RegularExpressions::ProhibitSingleCharAlternation 1.126
- Perl::Critic::Policy::RegularExpressions::ProhibitUnusedCapture 1.126
- Perl::Critic::Policy::RegularExpressions::ProhibitUnusualDelimiters 1.126
- Perl::Critic::Policy::RegularExpressions::ProhibitUselessTopic 1.126
- Perl::Critic::Policy::RegularExpressions::RequireBracesForMultiline 1.126
- Perl::Critic::Policy::RegularExpressions::RequireDotMatchAnything 1.126
- Perl::Critic::Policy::RegularExpressions::RequireExtendedFormatting 1.126
- Perl::Critic::Policy::RegularExpressions::RequireLineBoundaryMatching 1.126
- Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils 1.126
- Perl::Critic::Policy::Subroutines::ProhibitBuiltinHomonyms 1.126
- Perl::Critic::Policy::Subroutines::ProhibitExcessComplexity 1.126
- Perl::Critic::Policy::Subroutines::ProhibitExplicitReturnUndef 1.126
- Perl::Critic::Policy::Subroutines::ProhibitManyArgs 1.126
- Perl::Critic::Policy::Subroutines::ProhibitNestedSubs 1.126
- Perl::Critic::Policy::Subroutines::ProhibitReturnSort 1.126
- Perl::Critic::Policy::Subroutines::ProhibitSubroutinePrototypes 1.126
- Perl::Critic::Policy::Subroutines::ProhibitUnusedPrivateSubroutines 1.126
- Perl::Critic::Policy::Subroutines::ProtectPrivateSubs 1.126
- Perl::Critic::Policy::Subroutines::RequireArgUnpacking 1.126
- Perl::Critic::Policy::Subroutines::RequireFinalReturn 1.126
- Perl::Critic::Policy::TestingAndDebugging::ProhibitNoStrict 1.126
- Perl::Critic::Policy::TestingAndDebugging::ProhibitNoWarnings 1.126
- Perl::Critic::Policy::TestingAndDebugging::ProhibitProlongedStrictureOverride 1.126
- Perl::Critic::Policy::TestingAndDebugging::RequireTestLabels 1.126
- Perl::Critic::Policy::TestingAndDebugging::RequireUseStrict 1.126
- Perl::Critic::Policy::TestingAndDebugging::RequireUseWarnings 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitCommaSeparatedStatements 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitComplexVersion 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitConstantPragma 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitEmptyQuotes 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitEscapedCharacters 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitImplicitNewlines 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitInterpolationOfLiterals 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitLeadingZeros 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitLongChainsOfMethodCalls 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitMagicNumbers 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitMismatchedOperators 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitNoisyQuotes 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitQuotesAsQuotelikeOperatorDelimiters 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitSpecialLiteralHeredocTerminator 1.126
- Perl::Critic::Policy::ValuesAndExpressions::ProhibitVersionStrings 1.126
- Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion 1.126
- Perl::Critic::Policy::ValuesAndExpressions::RequireInterpolationOfMetachars 1.126
- Perl::Critic::Policy::ValuesAndExpressions::RequireNumberSeparators 1.126
- Perl::Critic::Policy::ValuesAndExpressions::RequireQuotedHeredocTerminator 1.126
- Perl::Critic::Policy::ValuesAndExpressions::RequireUpperCaseHeredocTerminator 1.126
- Perl::Critic::Policy::Variables::ProhibitAugmentedAssignmentInDeclaration 1.126
- Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations 1.126
- Perl::Critic::Policy::Variables::ProhibitEvilVariables 1.126
- Perl::Critic::Policy::Variables::ProhibitLocalVars 1.126
- Perl::Critic::Policy::Variables::ProhibitMatchVars 1.126
- Perl::Critic::Policy::Variables::ProhibitPackageVars 1.126
- Perl::Critic::Policy::Variables::ProhibitPerl4PackageNames 1.126
- Perl::Critic::Policy::Variables::ProhibitPunctuationVars 1.126
- Perl::Critic::Policy::Variables::ProhibitReusedNames 1.126
- Perl::Critic::Policy::Variables::ProhibitUnusedVariables 1.126
- Perl::Critic::Policy::Variables::ProtectPrivateVars 1.126
- Perl::Critic::Policy::Variables::RequireInitializationForLocalVars 1.126
- Perl::Critic::Policy::Variables::RequireLexicalLoopIterators 1.126
- Perl::Critic::Policy::Variables::RequireLocalizedPunctuationVars 1.126
- Perl::Critic::Policy::Variables::RequireNegativeIndices 1.126
- Perl::Critic::PolicyConfig 1.126
- Perl::Critic::PolicyFactory 1.126
- Perl::Critic::PolicyListing 1.126
- Perl::Critic::PolicyParameter 1.126
- Perl::Critic::PolicyParameter::Behavior 1.126
- Perl::Critic::PolicyParameter::Behavior::Boolean 1.126
- Perl::Critic::PolicyParameter::Behavior::Enumeration 1.126
- Perl::Critic::PolicyParameter::Behavior::Integer 1.126
- Perl::Critic::PolicyParameter::Behavior::String 1.126
- Perl::Critic::PolicyParameter::Behavior::StringList 1.126
- Perl::Critic::ProfilePrototype 1.126
- Perl::Critic::Statistics 1.126
- Perl::Critic::TestUtils 1.126
- Perl::Critic::Theme 1.126
- Perl::Critic::ThemeListing 1.126
- Perl::Critic::UserProfile 1.126
- Perl::Critic::Utils 1.126
- Perl::Critic::Utils::Constants 1.126
- Perl::Critic::Utils::DataConversion 1.126
- Perl::Critic::Utils::McCabe 1.126
- Perl::Critic::Utils::POD 1.126
- Perl::Critic::Utils::POD::ParseInteriorSequence 1.126
- Perl::Critic::Utils::PPI 1.126
- Perl::Critic::Utils::Perl 1.126
- Perl::Critic::Violation 1.126
- Test::Perl::Critic::Policy 1.126
+ Perl-Critic-1.128
+ pathname: P/PE/PETDANCE/Perl-Critic-1.128.tar.gz
+ provides:
+ Perl::Critic 1.128
+ Perl::Critic::Annotation 1.128
+ Perl::Critic::Command 1.128
+ Perl::Critic::Config 1.128
+ Perl::Critic::Document 1.128
+ Perl::Critic::Exception 1.128
+ Perl::Critic::Exception::AggregateConfiguration 1.128
+ Perl::Critic::Exception::Configuration 1.128
+ Perl::Critic::Exception::Configuration::Generic 1.128
+ Perl::Critic::Exception::Configuration::NonExistentPolicy 1.128
+ Perl::Critic::Exception::Configuration::Option 1.128
+ Perl::Critic::Exception::Configuration::Option::Global 1.128
+ Perl::Critic::Exception::Configuration::Option::Global::ExtraParameter 1.128
+ Perl::Critic::Exception::Configuration::Option::Global::ParameterValue 1.128
+ Perl::Critic::Exception::Configuration::Option::Policy 1.128
+ Perl::Critic::Exception::Configuration::Option::Policy::ExtraParameter 1.128
+ Perl::Critic::Exception::Configuration::Option::Policy::ParameterValue 1.128
+ Perl::Critic::Exception::Fatal 1.128
+ Perl::Critic::Exception::Fatal::Generic 1.128
+ Perl::Critic::Exception::Fatal::Internal 1.128
+ Perl::Critic::Exception::Fatal::PolicyDefinition 1.128
+ Perl::Critic::Exception::IO 1.128
+ Perl::Critic::Exception::Parse 1.128
+ Perl::Critic::OptionsProcessor 1.128
+ Perl::Critic::Policy 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitBooleanGrep 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitComplexMappings 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitLvalueSubstr 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitReverseSortBlock 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitSleepViaSelect 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitStringyEval 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitStringySplit 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitUniversalCan 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitUniversalIsa 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitUselessTopic 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitVoidGrep 1.128
+ Perl::Critic::Policy::BuiltinFunctions::ProhibitVoidMap 1.128
+ Perl::Critic::Policy::BuiltinFunctions::RequireBlockGrep 1.128
+ Perl::Critic::Policy::BuiltinFunctions::RequireBlockMap 1.128
+ Perl::Critic::Policy::BuiltinFunctions::RequireGlobFunction 1.128
+ Perl::Critic::Policy::BuiltinFunctions::RequireSimpleSortBlock 1.128
+ Perl::Critic::Policy::ClassHierarchies::ProhibitAutoloading 1.128
+ Perl::Critic::Policy::ClassHierarchies::ProhibitExplicitISA 1.128
+ Perl::Critic::Policy::ClassHierarchies::ProhibitOneArgBless 1.128
+ Perl::Critic::Policy::CodeLayout::ProhibitHardTabs 1.128
+ Perl::Critic::Policy::CodeLayout::ProhibitParensWithBuiltins 1.128
+ Perl::Critic::Policy::CodeLayout::ProhibitQuotedWordLists 1.128
+ Perl::Critic::Policy::CodeLayout::ProhibitTrailingWhitespace 1.128
+ Perl::Critic::Policy::CodeLayout::RequireConsistentNewlines 1.128
+ Perl::Critic::Policy::CodeLayout::RequireTidyCode 1.128
+ Perl::Critic::Policy::CodeLayout::RequireTrailingCommas 1.128
+ Perl::Critic::Policy::ControlStructures::ProhibitCStyleForLoops 1.128
+ Perl::Critic::Policy::ControlStructures::ProhibitCascadingIfElse 1.128
+ Perl::Critic::Policy::ControlStructures::ProhibitDeepNests 1.128
+ Perl::Critic::Policy::ControlStructures::ProhibitLabelsWithSpecialBlockNames 1.128
+ Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions 1.128
+ Perl::Critic::Policy::ControlStructures::ProhibitNegativeExpressionsInUnlessAndUntilConditions 1.128
+ Perl::Critic::Policy::ControlStructures::ProhibitPostfixControls 1.128
+ Perl::Critic::Policy::ControlStructures::ProhibitUnlessBlocks 1.128
+ Perl::Critic::Policy::ControlStructures::ProhibitUnreachableCode 1.128
+ Perl::Critic::Policy::ControlStructures::ProhibitUntilBlocks 1.128
+ Perl::Critic::Policy::ControlStructures::ProhibitYadaOperator 1.128
+ Perl::Critic::Policy::Documentation::PodSpelling 1.128
+ Perl::Critic::Policy::Documentation::RequirePackageMatchesPodName 1.128
+ Perl::Critic::Policy::Documentation::RequirePodAtEnd 1.128
+ Perl::Critic::Policy::Documentation::RequirePodLinksIncludeText 1.128
+ Perl::Critic::Policy::Documentation::RequirePodSections 1.128
+ Perl::Critic::Policy::ErrorHandling::RequireCarping 1.128
+ Perl::Critic::Policy::ErrorHandling::RequireCheckingReturnValueOfEval 1.128
+ Perl::Critic::Policy::InputOutput::ProhibitBacktickOperators 1.128
+ Perl::Critic::Policy::InputOutput::ProhibitBarewordFileHandles 1.128
+ Perl::Critic::Policy::InputOutput::ProhibitExplicitStdin 1.128
+ Perl::Critic::Policy::InputOutput::ProhibitInteractiveTest 1.128
+ Perl::Critic::Policy::InputOutput::ProhibitJoinedReadline 1.128
+ Perl::Critic::Policy::InputOutput::ProhibitOneArgSelect 1.128
+ Perl::Critic::Policy::InputOutput::ProhibitReadlineInForLoop 1.128
+ Perl::Critic::Policy::InputOutput::ProhibitTwoArgOpen 1.128
+ Perl::Critic::Policy::InputOutput::RequireBracedFileHandleWithPrint 1.128
+ Perl::Critic::Policy::InputOutput::RequireBriefOpen 1.128
+ Perl::Critic::Policy::InputOutput::RequireCheckedClose 1.128
+ Perl::Critic::Policy::InputOutput::RequireCheckedOpen 1.128
+ Perl::Critic::Policy::InputOutput::RequireCheckedSyscalls 1.128
+ Perl::Critic::Policy::InputOutput::RequireEncodingWithUTF8Layer 1.128
+ Perl::Critic::Policy::Miscellanea::ProhibitFormats 1.128
+ Perl::Critic::Policy::Miscellanea::ProhibitTies 1.128
+ Perl::Critic::Policy::Miscellanea::ProhibitUnrestrictedNoCritic 1.128
+ Perl::Critic::Policy::Miscellanea::ProhibitUselessNoCritic 1.128
+ Perl::Critic::Policy::Modules::ProhibitAutomaticExportation 1.128
+ Perl::Critic::Policy::Modules::ProhibitConditionalUseStatements 1.128
+ Perl::Critic::Policy::Modules::ProhibitEvilModules 1.128
+ Perl::Critic::Policy::Modules::ProhibitExcessMainComplexity 1.128
+ Perl::Critic::Policy::Modules::ProhibitMultiplePackages 1.128
+ Perl::Critic::Policy::Modules::RequireBarewordIncludes 1.128
+ Perl::Critic::Policy::Modules::RequireEndWithOne 1.128
+ Perl::Critic::Policy::Modules::RequireExplicitPackage 1.128
+ Perl::Critic::Policy::Modules::RequireFilenameMatchesPackage 1.128
+ Perl::Critic::Policy::Modules::RequireNoMatchVarsWithUseEnglish 1.128
+ Perl::Critic::Policy::Modules::RequireVersionVar 1.128
+ Perl::Critic::Policy::NamingConventions::Capitalization 1.128
+ Perl::Critic::Policy::NamingConventions::ProhibitAmbiguousNames 1.128
+ Perl::Critic::Policy::Objects::ProhibitIndirectSyntax 1.128
+ Perl::Critic::Policy::References::ProhibitDoubleSigils 1.128
+ Perl::Critic::Policy::RegularExpressions::ProhibitCaptureWithoutTest 1.128
+ Perl::Critic::Policy::RegularExpressions::ProhibitComplexRegexes 1.128
+ Perl::Critic::Policy::RegularExpressions::ProhibitEnumeratedClasses 1.128
+ Perl::Critic::Policy::RegularExpressions::ProhibitEscapedMetacharacters 1.128
+ Perl::Critic::Policy::RegularExpressions::ProhibitFixedStringMatches 1.128
+ Perl::Critic::Policy::RegularExpressions::ProhibitSingleCharAlternation 1.128
+ Perl::Critic::Policy::RegularExpressions::ProhibitUnusedCapture 1.128
+ Perl::Critic::Policy::RegularExpressions::ProhibitUnusualDelimiters 1.128
+ Perl::Critic::Policy::RegularExpressions::ProhibitUselessTopic 1.128
+ Perl::Critic::Policy::RegularExpressions::RequireBracesForMultiline 1.128
+ Perl::Critic::Policy::RegularExpressions::RequireDotMatchAnything 1.128
+ Perl::Critic::Policy::RegularExpressions::RequireExtendedFormatting 1.128
+ Perl::Critic::Policy::RegularExpressions::RequireLineBoundaryMatching 1.128
+ Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils 1.128
+ Perl::Critic::Policy::Subroutines::ProhibitBuiltinHomonyms 1.128
+ Perl::Critic::Policy::Subroutines::ProhibitExcessComplexity 1.128
+ Perl::Critic::Policy::Subroutines::ProhibitExplicitReturnUndef 1.128
+ Perl::Critic::Policy::Subroutines::ProhibitManyArgs 1.128
+ Perl::Critic::Policy::Subroutines::ProhibitNestedSubs 1.128
+ Perl::Critic::Policy::Subroutines::ProhibitReturnSort 1.128
+ Perl::Critic::Policy::Subroutines::ProhibitSubroutinePrototypes 1.128
+ Perl::Critic::Policy::Subroutines::ProhibitUnusedPrivateSubroutines 1.128
+ Perl::Critic::Policy::Subroutines::ProtectPrivateSubs 1.128
+ Perl::Critic::Policy::Subroutines::RequireArgUnpacking 1.128
+ Perl::Critic::Policy::Subroutines::RequireFinalReturn 1.128
+ Perl::Critic::Policy::TestingAndDebugging::ProhibitNoStrict 1.128
+ Perl::Critic::Policy::TestingAndDebugging::ProhibitNoWarnings 1.128
+ Perl::Critic::Policy::TestingAndDebugging::ProhibitProlongedStrictureOverride 1.128
+ Perl::Critic::Policy::TestingAndDebugging::RequireTestLabels 1.128
+ Perl::Critic::Policy::TestingAndDebugging::RequireUseStrict 1.128
+ Perl::Critic::Policy::TestingAndDebugging::RequireUseWarnings 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitCommaSeparatedStatements 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitComplexVersion 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitConstantPragma 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitEmptyQuotes 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitEscapedCharacters 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitImplicitNewlines 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitInterpolationOfLiterals 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitLeadingZeros 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitLongChainsOfMethodCalls 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitMagicNumbers 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitMismatchedOperators 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitNoisyQuotes 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitQuotesAsQuotelikeOperatorDelimiters 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitSpecialLiteralHeredocTerminator 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::ProhibitVersionStrings 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::RequireInterpolationOfMetachars 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::RequireNumberSeparators 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::RequireQuotedHeredocTerminator 1.128
+ Perl::Critic::Policy::ValuesAndExpressions::RequireUpperCaseHeredocTerminator 1.128
+ Perl::Critic::Policy::Variables::ProhibitAugmentedAssignmentInDeclaration 1.128
+ Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations 1.128
+ Perl::Critic::Policy::Variables::ProhibitEvilVariables 1.128
+ Perl::Critic::Policy::Variables::ProhibitLocalVars 1.128
+ Perl::Critic::Policy::Variables::ProhibitMatchVars 1.128
+ Perl::Critic::Policy::Variables::ProhibitPackageVars 1.128
+ Perl::Critic::Policy::Variables::ProhibitPerl4PackageNames 1.128
+ Perl::Critic::Policy::Variables::ProhibitPunctuationVars 1.128
+ Perl::Critic::Policy::Variables::ProhibitReusedNames 1.128
+ Perl::Critic::Policy::Variables::ProhibitUnusedVariables 1.128
+ Perl::Critic::Policy::Variables::ProtectPrivateVars 1.128
+ Perl::Critic::Policy::Variables::RequireInitializationForLocalVars 1.128
+ Perl::Critic::Policy::Variables::RequireLexicalLoopIterators 1.128
+ Perl::Critic::Policy::Variables::RequireLocalizedPunctuationVars 1.128
+ Perl::Critic::Policy::Variables::RequireNegativeIndices 1.128
+ Perl::Critic::PolicyConfig 1.128
+ Perl::Critic::PolicyFactory 1.128
+ Perl::Critic::PolicyListing 1.128
+ Perl::Critic::PolicyParameter 1.128
+ Perl::Critic::PolicyParameter::Behavior 1.128
+ Perl::Critic::PolicyParameter::Behavior::Boolean 1.128
+ Perl::Critic::PolicyParameter::Behavior::Enumeration 1.128
+ Perl::Critic::PolicyParameter::Behavior::Integer 1.128
+ Perl::Critic::PolicyParameter::Behavior::String 1.128
+ Perl::Critic::PolicyParameter::Behavior::StringList 1.128
+ Perl::Critic::ProfilePrototype 1.128
+ Perl::Critic::Statistics 1.128
+ Perl::Critic::TestUtils 1.128
+ Perl::Critic::Theme 1.128
+ Perl::Critic::ThemeListing 1.128
+ Perl::Critic::UserProfile 1.128
+ Perl::Critic::Utils 1.128
+ Perl::Critic::Utils::Constants 1.128
+ Perl::Critic::Utils::DataConversion 1.128
+ Perl::Critic::Utils::McCabe 1.128
+ Perl::Critic::Utils::POD 1.128
+ Perl::Critic::Utils::POD::ParseInteriorSequence 1.128
+ Perl::Critic::Utils::PPI 1.128
+ Perl::Critic::Utils::Perl 1.128
+ Perl::Critic::Violation 1.128
+ Test::Perl::Critic::Policy 1.128
requirements:
B::Keywords 1.05
Carp 0
@@ -4492,12 +4301,12 @@ DISTRIBUTIONS
List::Util 0
Module::Build 0.4024
Module::Pluggable 3.1
- PPI 1.220
- PPI::Document 1.220
- PPI::Document::File 1.220
- PPI::Node 1.220
- PPI::Token::Quote::Single 1.220
- PPI::Token::Whitespace 1.220
+ PPI 1.224
+ PPI::Document 1.224
+ PPI::Document::File 1.224
+ PPI::Node 1.224
+ PPI::Token::Quote::Single 1.224
+ PPI::Token::Whitespace 1.224
PPIx::Regexp 0.027
PPIx::Utilities::Node 1.001
PPIx::Utilities::Statement 1.001
@@ -4520,6 +4329,7 @@ DISTRIBUTIONS
charnames 0
lib 0
overload 0
+ perl 5.006001
strict 0
version 0.77
warnings 0
@@ -4546,12 +4356,6 @@ DISTRIBUTIONS
Perl::Tidy::VerticalAligner::Line 20170521
requirements:
ExtUtils::MakeMaker 0
- PerlIO-gzip-0.19
- pathname: N/NW/NWCLARK/PerlIO-gzip-0.19.tar.gz
- provides:
- PerlIO::gzip 0.19
- requirements:
- ExtUtils::MakeMaker 0
PerlIO-utf8_strict-0.007
pathname: L/LE/LEONT/PerlIO-utf8_strict-0.007.tar.gz
provides:
@@ -4890,106 +4694,6 @@ DISTRIBUTIONS
ExtUtils::MakeMaker 0
Test::More 0
perl 5.006
- Search-Elasticsearch-2.03
- pathname: D/DR/DRTECH/Search-Elasticsearch-2.03.tar.gz
- provides:
- Search::Elasticsearch 2.03
- Search::Elasticsearch::Bulk 2.03
- Search::Elasticsearch::Client::0_90::Direct 2.03
- Search::Elasticsearch::Client::0_90::Direct::Cluster 2.03
- Search::Elasticsearch::Client::0_90::Direct::Indices 2.03
- Search::Elasticsearch::Client::1_0::Direct 2.03
- Search::Elasticsearch::Client::1_0::Direct::Cat 2.03
- Search::Elasticsearch::Client::1_0::Direct::Cluster 2.03
- Search::Elasticsearch::Client::1_0::Direct::Indices 2.03
- Search::Elasticsearch::Client::1_0::Direct::Nodes 2.03
- Search::Elasticsearch::Client::1_0::Direct::Snapshot 2.03
- Search::Elasticsearch::Client::2_0::Direct 2.03
- Search::Elasticsearch::Client::2_0::Direct::Cat 2.03
- Search::Elasticsearch::Client::2_0::Direct::Cluster 2.03
- Search::Elasticsearch::Client::2_0::Direct::Indices 2.03
- Search::Elasticsearch::Client::2_0::Direct::Nodes 2.03
- Search::Elasticsearch::Client::2_0::Direct::Snapshot 2.03
- Search::Elasticsearch::Client::2_0::Direct::Tasks 2.03
- Search::Elasticsearch::Cxn::Factory 2.03
- Search::Elasticsearch::Cxn::HTTPTiny 2.03
- Search::Elasticsearch::Cxn::Hijk 2.03
- Search::Elasticsearch::Cxn::LWP 2.03
- Search::Elasticsearch::CxnPool::Sniff 2.03
- Search::Elasticsearch::CxnPool::Static 2.03
- Search::Elasticsearch::CxnPool::Static::NoPing 2.03
- Search::Elasticsearch::Error 2.03
- Search::Elasticsearch::Logger::LogAny 2.03
- Search::Elasticsearch::Role::API::0_90 2.03
- Search::Elasticsearch::Role::API::1_0 2.03
- Search::Elasticsearch::Role::API::2_0 2.03
- Search::Elasticsearch::Role::Bulk 2.03
- Search::Elasticsearch::Role::Client 2.03
- Search::Elasticsearch::Role::Client::Direct 2.03
- Search::Elasticsearch::Role::Client::Direct::Main 2.03
- Search::Elasticsearch::Role::Cxn 2.03
- Search::Elasticsearch::Role::Cxn::HTTP 2.03
- Search::Elasticsearch::Role::CxnPool 2.03
- Search::Elasticsearch::Role::CxnPool::Sniff 2.03
- Search::Elasticsearch::Role::CxnPool::Static 2.03
- Search::Elasticsearch::Role::CxnPool::Static::NoPing 2.03
- Search::Elasticsearch::Role::Is_Sync 2.03
- Search::Elasticsearch::Role::Logger 2.03
- Search::Elasticsearch::Role::Scroll 2.03
- Search::Elasticsearch::Role::Serializer 2.03
- Search::Elasticsearch::Role::Serializer::JSON 2.03
- Search::Elasticsearch::Role::Transport 2.03
- Search::Elasticsearch::Scroll 2.03
- Search::Elasticsearch::Serializer::JSON 2.03
- Search::Elasticsearch::Serializer::JSON::Cpanel 2.03
- Search::Elasticsearch::Serializer::JSON::PP 2.03
- Search::Elasticsearch::Serializer::JSON::XS 2.03
- Search::Elasticsearch::TestServer 2.03
- Search::Elasticsearch::Transport 2.03
- Search::Elasticsearch::Util 2.03
- Search::Elasticsearch::Util::API::Path 2.03
- Search::Elasticsearch::Util::API::QS 2.03
- requirements:
- Any::URI::Escape 0
- Data::Dumper 0
- Devel::GlobalDestruction 0
- Encode 0
- ExtUtils::MakeMaker 0
- File::Temp 0
- HTTP::Headers 0
- HTTP::Request 0
- HTTP::Tiny 0.043
- IO::Select 0
- IO::Socket 0
- IO::Uncompress::Inflate 0
- JSON::MaybeXS 1.002002
- JSON::PP 0
- LWP::UserAgent 0
- List::Util 0
- Log::Any 1.02
- Log::Any::Adapter 0
- MIME::Base64 0
- Module::Runtime 0
- Moo 1.003
- Moo::Role 0
- POSIX 0
- Package::Stash 0.34
- Scalar::Util 0
- Sub::Exporter 0
- Time::HiRes 0
- Try::Tiny 0
- URI 0
- namespace::clean 0
- overload 0
- strict 0
- warnings 0
- Sort-Naturally-1.03
- pathname: B/BI/BINGOS/Sort-Naturally-1.03.tar.gz
- provides:
- Sort::Naturally 1.03
- requirements:
- ExtUtils::MakeMaker 0
- perl 5
Specio-0.37
pathname: D/DR/DROLSKY/Specio-0.37.tar.gz
provides:
@@ -5126,6 +4830,12 @@ DISTRIBUTIONS
Sub::Exporter 0.972
strict 0
warnings 0
+ Struct-Dumb-0.09
+ pathname: P/PE/PEVANS/Struct-Dumb-0.09.tar.gz
+ provides:
+ Struct::Dumb 0.09
+ requirements:
+ Module::Build 0.4004
Sub-Exporter-0.987
pathname: R/RJ/RJBS/Sub-Exporter-0.987.tar.gz
provides:
@@ -5185,11 +4895,11 @@ DISTRIBUTIONS
perl 5.006
strict 0
warnings 0
- Sub-Quote-2.003001
- pathname: H/HA/HAARG/Sub-Quote-2.003001.tar.gz
+ Sub-Quote-2.004000
+ pathname: H/HA/HAARG/Sub-Quote-2.004000.tar.gz
provides:
- Sub::Defer 2.003001
- Sub::Quote 2.003001
+ Sub::Defer 2.004000
+ Sub::Quote 2.004000
requirements:
ExtUtils::MakeMaker 0
Scalar::Util 0
@@ -5470,6 +5180,14 @@ DISTRIBUTIONS
Try::Tiny 0.07
strict 0
warnings 0
+ Test-Identity-0.01
+ pathname: P/PE/PEVANS/Test-Identity-0.01.tar.gz
+ provides:
+ Test::Identity 0.01
+ requirements:
+ Scalar::Util 0
+ Test::Builder::Tester 0
+ Test::More 0
Test-LongString-0.17
pathname: R/RG/RGARCIA/Test-LongString-0.17.tar.gz
provides:
@@ -5556,6 +5274,16 @@ DISTRIBUTIONS
Test::More 0
strict 0
warnings 0
+ Test-Refcount-0.08
+ pathname: P/PE/PEVANS/Test-Refcount-0.08.tar.gz
+ provides:
+ Test::Refcount 0.08
+ requirements:
+ B 0
+ Scalar::Util 0
+ Test::Builder 0
+ Test::Builder::Tester 0
+ Test::More 0
Test-Requires-0.10
pathname: T/TO/TOKUHIROM/Test-Requires-0.10.tar.gz
provides:
@@ -5923,44 +5651,44 @@ DISTRIBUTIONS
perl 5.006
strict 0
warnings 0
- Type-Tiny-1.002000
- pathname: T/TO/TOBYINK/Type-Tiny-1.002000.tar.gz
- provides:
- Devel::TypeTiny::Perl56Compat 1.002000
- Devel::TypeTiny::Perl58Compat 1.002000
- Error::TypeTiny 1.002000
- Error::TypeTiny::Assertion 1.002000
- Error::TypeTiny::Compilation 1.002000
- Error::TypeTiny::WrongNumberOfParameters 1.002000
- Eval::TypeTiny 1.002000
- Reply::Plugin::TypeTiny 1.002000
- Test::TypeTiny 1.002000
- Type::Coercion 1.002000
- Type::Coercion::FromMoose 1.002000
- Type::Coercion::Union 1.002000
- Type::Library 1.002000
- Type::Params 1.002000
- Type::Parser 1.002000
- Type::Registry 1.002000
- Type::Tiny 1.002000
- Type::Tiny::Class 1.002000
- Type::Tiny::Duck 1.002000
- Type::Tiny::Enum 1.002000
- Type::Tiny::Intersection 1.002000
- Type::Tiny::Role 1.002000
- Type::Tiny::Union 1.002000
- Type::Utils 1.002000
- Types::Common::Numeric 1.002000
- Types::Common::String 1.002000
- Types::Standard 1.002000
- Types::Standard::ArrayRef 1.002000
- Types::Standard::CycleTuple 1.002000
- Types::Standard::Dict 1.002000
- Types::Standard::HashRef 1.002000
- Types::Standard::Map 1.002000
- Types::Standard::ScalarRef 1.002000
- Types::Standard::Tuple 1.002000
- Types::TypeTiny 1.002000
+ Type-Tiny-1.002001
+ pathname: T/TO/TOBYINK/Type-Tiny-1.002001.tar.gz
+ provides:
+ Devel::TypeTiny::Perl56Compat 1.002001
+ Devel::TypeTiny::Perl58Compat 1.002001
+ Error::TypeTiny 1.002001
+ Error::TypeTiny::Assertion 1.002001
+ Error::TypeTiny::Compilation 1.002001
+ Error::TypeTiny::WrongNumberOfParameters 1.002001
+ Eval::TypeTiny 1.002001
+ Reply::Plugin::TypeTiny 1.002001
+ Test::TypeTiny 1.002001
+ Type::Coercion 1.002001
+ Type::Coercion::FromMoose 1.002001
+ Type::Coercion::Union 1.002001
+ Type::Library 1.002001
+ Type::Params 1.002001
+ Type::Parser 1.002001
+ Type::Registry 1.002001
+ Type::Tiny 1.002001
+ Type::Tiny::Class 1.002001
+ Type::Tiny::Duck 1.002001
+ Type::Tiny::Enum 1.002001
+ Type::Tiny::Intersection 1.002001
+ Type::Tiny::Role 1.002001
+ Type::Tiny::Union 1.002001
+ Type::Utils 1.002001
+ Types::Common::Numeric 1.002001
+ Types::Common::String 1.002001
+ Types::Standard 1.002001
+ Types::Standard::ArrayRef 1.002001
+ Types::Standard::CycleTuple 1.002001
+ Types::Standard::Dict 1.002001
+ Types::Standard::HashRef 1.002001
+ Types::Standard::Map 1.002001
+ Types::Standard::ScalarRef 1.002001
+ Types::Standard::Tuple 1.002001
+ Types::TypeTiny 1.002001
requirements:
Exporter::Tiny 0.026
ExtUtils::MakeMaker 6.17
@@ -6127,16 +5855,6 @@ DISTRIBUTIONS
base 0
lib 0
perl 5.008
- WWW-Curl-4.17
- pathname: S/SZ/SZBALINT/WWW-Curl-4.17.tar.gz
- provides:
- WWW::Curl 4.17
- WWW::Curl::Easy 4.17
- WWW::Curl::Form 4.17
- WWW::Curl::Multi undef
- WWW::Curl::Share undef
- requirements:
- ExtUtils::MakeMaker 6.42
WWW-Form-UrlEncoded-0.24
pathname: K/KA/KAZEBURO/WWW-Form-UrlEncoded-0.24.tar.gz
provides:
@@ -6381,16 +6099,6 @@ DISTRIBUTIONS
XML::Parser 2.27
XML::SAX 0.03
XML::SAX::Base 1.00
- XML-Simple-2.24
- pathname: G/GR/GRANTM/XML-Simple-2.24.tar.gz
- provides:
- XML::Simple 2.24
- requirements:
- ExtUtils::MakeMaker 0
- XML::NamespaceSupport 1.04
- XML::SAX 0.15
- XML::SAX::Expat 0
- perl 5.008
XML-XPath-1.40
pathname: M/MA/MANWAR/XML-XPath-1.40.tar.gz
provides:
diff --git a/lib/MetaCPAN/Middleware/Static.pm b/lib/MetaCPAN/Middleware/Static.pm
index 4ca88ed0ae..cfc48cc507 100644
--- a/lib/MetaCPAN/Middleware/Static.pm
+++ b/lib/MetaCPAN/Middleware/Static.pm
@@ -82,6 +82,11 @@ sub wrap {
};
}
+ mount '/sitemap-authors.xml.gz' => Plack::App::File->new(
+ file => 'root/static/sitemaps/sitemap-authors.xml.gz' )->to_app;
+ mount '/sitemap-releases.xml.gz' => Plack::App::File->new(
+ file => 'root/static/sitemaps/sitemap-releases.xml.gz' )->to_app;
+
mount '/favicon.ico' =>
Plack::App::File->new( file => 'root/static/icons/favicon.ico' )
->to_app;
diff --git a/lib/MetaCPAN/Sitemap.pm b/lib/MetaCPAN/Sitemap.pm
index 7fe589f798..fd9c4d6e91 100644
--- a/lib/MetaCPAN/Sitemap.pm
+++ b/lib/MetaCPAN/Sitemap.pm
@@ -1,41 +1,42 @@
package MetaCPAN::Sitemap;
-
-=head1 DESCRIPTION
-
-Generate an XML file containing URLs use by the robots.txt Sitemap. We use this
-module to generate one each for authors, modules and releases.
-
-=cut
-
use strict;
use warnings;
-use MetaCPAN::Moose;
-
-use autodie;
-
-use Carp;
-use Search::Elasticsearch;
-use File::Spec;
-use MetaCPAN::Web::Types qw( HashRef Int Str );
-use MooseX::StrictConstructor;
-use PerlIO::gzip;
-use XML::Simple qw(:strict);
-
-has [ 'cpan_directory', 'object_type', 'field_name', 'xml_file', ] => (
- is => 'ro',
- isa => Str,
- required => 1,
-);
-
-has 'filter' => (
- is => 'ro',
- isa => HashRef,
+use IO::Socket::SSL qw(SSL_VERIFY_PEER);
+use IO::Async::Loop;
+use IO::Async::SSL;
+use Net::Async::HTTP;
+use Cpanel::JSON::XS;
+use IO::Compress::Gzip;
+use HTML::Entities qw(encode_entities_numeric);
+
+use Moo;
+
+has api_secure => ( is => 'ro', required => 1 );
+has url_prefix => ( is => 'ro', required => 1 );
+has object_type => ( is => 'ro', required => 1 );
+has field_name => ( is => 'ro', required => 1 );
+has filter => ( is => 'ro' );
+has size => ( is => 'ro', default => 1000 );
+has loop => ( is => 'lazy', default => sub { IO::Async::Loop->new } );
+has ua => (
+ is => 'lazy',
+ default => sub {
+ my $self = shift;
+ my $http = Net::Async::HTTP->new(
+ user_agent =>
+ 'MetaCPAN-Web/1.0 (https://github.com/metacpan/metacpan-web)',
+ max_connections_per_host => 5,
+ SSL_verify_mode => SSL_VERIFY_PEER,
+ timeout => 10,
+ );
+ $self->loop->add($http);
+ $http;
+ }
);
-has 'size' => (
- is => 'ro',
- isa => Int,
-);
+sub DEMOLISH {
+ $_[0]->ua->remove_from_parent;
+}
# Mandatory arguments to this function are
# [] search object_type (author and release)
@@ -48,82 +49,72 @@ has 'size' => (
# [] filter - contains filter for a field that also needs to be included in
# the list of form fields.
-sub process {
- my $self = shift;
-
- # Check that a) the directory where the output file wants to be does
- # actually exist and b) the directory itself is writeable.
-
- # Get started. Create the ES object and the scrolled search object.
- # XXX Remove this hardcoded URL
- my $es = Search::Elasticsearch->new(
- cxn_pool => 'Static::NoPing',
- nodes => ['https://fastapi.metacpan.org'],
- send_get_body_as => 'POST',
- );
-
- my $field_name = $self->field_name;
-
- # Start off with standard search parameters ..
-
- my %search_parameters = (
- index => 'v1',
- size => 5000,
- type => $self->object_type,
- fields => [$field_name],
- );
-
- # ..and augment them if necesary.
-
- if ( $self->filter ) {
+my $json = Cpanel::JSON::XS->new->utf8->canonical;
- # Copy the filter over wholesale into the search parameters, and add
- # the filter fields to the field list.
-
- $search_parameters{'body'}{'query'}{'match'} = $self->filter;
- push @{ $search_parameters{'fields'} }, keys %{ $self->filter };
- }
-
- my $scrolled_search = $es->scroll_helper(%search_parameters);
-
- # Open the output file, get ready to pump out the XML.
-
- open my $fh, '>:gzip', $self->xml_file;
-
- my @urls;
- my $metacpan_url = q{};
- if ( $self->cpan_directory ) {
- $metacpan_url
- = 'https://metacpan.org/' . $self->cpan_directory . q{/};
+sub _request {
+ my ( $self, $content, $cb ) = @_;
+ my $url = $self->api_secure . '/';
+ my $content_type = 'text/plain';
+ if ( ref $content ) {
+ $url .= $self->object_type . '/';
+ $content_type = 'application/json';
+ $content = $json->encode($content);
}
+ $url .= '_search/scroll?scroll=1m&size=' . $self->size;
+ $self->ua->POST( $url, $content, content_type => $content_type, )->then(
+ sub {
+ my $response = shift;
+ my $content = $json->decode( $response->content );
+ return Future->done
+ if !@{ $content->{hits}{hits} };
+ $cb->( $content->{hits}{hits} );
+ return $self->_request( $content->{_scroll_id}, $cb );
+ }
+ );
+}
- while ( $scrolled_search->refill_buffer ) {
- push @urls,
- map { $metacpan_url . $_->{'fields'}->{$field_name} }
- $scrolled_search->drain_buffer;
- }
+sub write {
+ my ( $self, $file ) = @_;
- $_ = $_ . q{ } for @urls;
+ my $fh = IO::Compress::Gzip->new( $file . '.new' );
+ $fh->print(<<'END_XML_HEADER');
+
+
+END_XML_HEADER
- $self->{size} = @urls;
- XMLout(
+ $self->_request(
{
- 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
- 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
- 'xsi:schemaLocation' =>
- 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd',
- 'url' => [ sort @urls ],
+ fields => [ $self->field_name ],
+ query => { match_all => {} },
+ ( $self->filter ? ( filter => $self->filter ) : () ),
+ sort => [ $self->field_name ],
},
- 'KeyAttr' => [],
- 'RootName' => 'urlset',
- 'XMLDecl' => q//,
- 'OutputFile' => $fh,
- );
-
- close $fh;
+ sub {
+ my $hits = shift;
+ for my $hit (@$hits) {
+ my $link_field = $hit->{fields}{ $self->field_name };
+ $link_field = $link_field->[0] if ref $link_field;
+ my $url = $self->url_prefix . $link_field;
+ $fh->print( " "
+ . encode_entities_numeric($url)
+ . "\n" );
+ }
+ }
+ )->get;
+ $fh->print("\n");
+ $fh->close;
+ rename "$file.new", "$file";
return;
}
-__PACKAGE__->meta->make_immutable;
-
1;
+__END__
+
+=head1 DESCRIPTION
+
+Generate an XML file containing URLs use by the robots.txt Sitemap. We use this
+module to generate one each for authors, modules and releases.
+
+=cut
diff --git a/lib/MetaCPAN/Web/Controller/Account.pm b/lib/MetaCPAN/Web/Controller/Account.pm
index 8820924a29..3f21b19476 100644
--- a/lib/MetaCPAN/Web/Controller/Account.pm
+++ b/lib/MetaCPAN/Web/Controller/Account.pm
@@ -35,14 +35,14 @@ sub identities : Local : Args(0) {
if ( $c->req->method eq 'POST'
&& ( my $delete = $c->req->params->{delete} ) )
{
- $c->model('API::User')->delete_identity( $delete, $c->token )->recv;
+ $c->model('API::User')->delete_identity( $delete, $c->token )->get;
$c->res->redirect('/account/identities');
}
}
sub profile : Local : Args(0) {
my ( $self, $c ) = @_;
- my $author = $c->model('API::User')->get_profile( $c->token )->recv;
+ my $author = $c->model('API::User')->get_profile( $c->token )->get;
$c->stash(
$author->{error} ? { no_profile => 1 } : { author => $author } );
my $req = $c->req;
@@ -92,8 +92,7 @@ sub profile : Local : Args(0) {
$data->{donation} = undef unless ( $req->params->{donations} );
- my $res
- = $c->model('API::User')->update_profile( $data, $c->token )->recv;
+ my $res = $c->model('API::User')->update_profile( $data, $c->token )->get;
if ( $res->{error} ) {
$c->stash( { author => $data, errors => $res->{errors} } );
}
diff --git a/lib/MetaCPAN/Web/Controller/Account/Favorite.pm b/lib/MetaCPAN/Web/Controller/Account/Favorite.pm
index f54ff9768f..2ded7b346a 100644
--- a/lib/MetaCPAN/Web/Controller/Account/Favorite.pm
+++ b/lib/MetaCPAN/Web/Controller/Account/Favorite.pm
@@ -22,10 +22,10 @@ sub add : Local : Args(0) {
my $data = $c->req->params;
my $res;
if ( $data->{remove} ) {
- $res = $model->remove_favorite( $data, $c->token )->recv;
+ $res = $model->remove_favorite( $data, $c->token )->get;
}
else {
- $res = $model->add_favorite( $data, $c->token )->recv;
+ $res = $model->add_favorite( $data, $c->token )->get;
}
# We need to purge if the rating has changes until the fav count
@@ -79,7 +79,7 @@ sub _cache_key_for_user {
sub _add_fav_list_to_stash {
my ( $self, $c, $size ) = @_;
my $user = $c->user;
- my $faves = $c->model('API::Favorite')->by_user( $user->id, $size );
+ my $faves = $c->model('API::Favorite')->by_user( $user->id, $size )->get;
$c->stash( { faves => $faves } );
return $user;
}
diff --git a/lib/MetaCPAN/Web/Controller/Account/Turing.pm b/lib/MetaCPAN/Web/Controller/Account/Turing.pm
index 6f2d91cf6b..71872c03a3 100644
--- a/lib/MetaCPAN/Web/Controller/Account/Turing.pm
+++ b/lib/MetaCPAN/Web/Controller/Account/Turing.pm
@@ -13,7 +13,7 @@ sub index : Path('') : Args(0) {
my $res = $c->model('API::User')->turing(
@$params{qw(recaptcha_challenge_field recaptcha_response_field)},
$c->token
- )->recv;
+ )->get;
$c->stash(
{
success => $res->{looks_human},
diff --git a/lib/MetaCPAN/Web/Controller/Activity.pm b/lib/MetaCPAN/Web/Controller/Activity.pm
index 1599490597..fa3f6dbde3 100644
--- a/lib/MetaCPAN/Web/Controller/Activity.pm
+++ b/lib/MetaCPAN/Web/Controller/Activity.pm
@@ -11,7 +11,7 @@ sub index : Path : Args(0) {
my %args = map { $_ => $c->req->parameters->{$_} }
keys %{ $c->req->parameters };
- my $line = $c->model('API')->request( '/activity', undef, \%args )->recv;
+ my $line = $c->model('API')->request( '/activity', undef, \%args )->get;
return unless $line and exists $line->{activity};
$c->res->content_type('image/svg+xml');
diff --git a/lib/MetaCPAN/Web/Controller/Author.pm b/lib/MetaCPAN/Web/Controller/Author.pm
index c07e2f219b..1ab4008c54 100644
--- a/lib/MetaCPAN/Web/Controller/Author.pm
+++ b/lib/MetaCPAN/Web/Controller/Author.pm
@@ -46,18 +46,17 @@ sub index : Chained('root') PathPart('') Args(0) {
my $pauseid = $c->stash->{pauseid};
- my $author_cv = $c->model('API::Author')->get($pauseid);
- my $author = $author_cv->recv;
+ my $author = $c->model('API::Author')->get($pauseid)->get;
$c->detach('/not_found') unless ( $author->{pauseid} );
- my $releases = $c->model('API::Release')->latest_by_author($pauseid);
+ my $releases = $c->model('API::Release')->latest_by_author($pauseid)->get;
my $date = List::Util::max
map { DateTime::Format::ISO8601->parse_datetime( $_->{date} ) }
@{ $releases->{releases} };
$c->res->last_modified($date) if $date;
- my $faves = $c->model('API::Favorite')->by_user( $author->{user} );
+ my $faves = $c->model('API::Favorite')->by_user( $author->{user} )->get;
my $took = $releases->{took};
@@ -88,9 +87,10 @@ sub releases : Chained('root') PathPart Args(0) {
my $page = $req->page > 0 ? $req->page : 1;
my $author_cv = $c->model('API::Author')->get($id);
my $releases
- = $c->model('API::Release')->all_by_author( $id, $page_size, $page );
+ = $c->model('API::Release')->all_by_author( $id, $page_size, $page )
+ ->get;
- my $author = $author_cv->recv;
+ my $author = $author_cv->get;
$c->detach('/not_found') unless ( $author->{pauseid} );
$c->stash(
diff --git a/lib/MetaCPAN/Web/Controller/Changes.pm b/lib/MetaCPAN/Web/Controller/Changes.pm
index d32c17dec8..0be871fa73 100644
--- a/lib/MetaCPAN/Web/Controller/Changes.pm
+++ b/lib/MetaCPAN/Web/Controller/Changes.pm
@@ -27,7 +27,7 @@ sub release : Local Args(2) {
sub get : Private {
my ( $self, $c, @args ) = @_;
- my $file = $c->model('API::Changes')->get(@args)->recv;
+ my $file = $c->model('API::Changes')->get(@args)->get;
# NOTE: There is currently no differentiation (from the API)
# of whether the release doesn't exist or we couldn't find a change log.
diff --git a/lib/MetaCPAN/Web/Controller/Diff.pm b/lib/MetaCPAN/Web/Controller/Diff.pm
index 5f4b17d2da..0807ea916f 100644
--- a/lib/MetaCPAN/Web/Controller/Diff.pm
+++ b/lib/MetaCPAN/Web/Controller/Diff.pm
@@ -10,7 +10,7 @@ sub index : PathPart('diff') : Chained('/') : CaptureArgs(0) {
sub release : Local : Args(4) {
my ( $self, $c, @path ) = @_;
- my $diff = $c->model('API::Diff')->releases(@path)->recv;
+ my $diff = $c->model('API::Diff')->releases(@path)->get;
$c->stash(
{ diff => $diff, template => 'diff.html', type => 'release' } );
}
@@ -18,7 +18,7 @@ sub release : Local : Args(4) {
sub file : Local : Args(0) {
my ( $self, $c ) = @_;
my $diff = $c->model('API::Diff')
- ->files( $c->req->params->{source}, $c->req->params->{target} )->recv;
+ ->files( $c->req->params->{source}, $c->req->params->{target} )->get;
$c->stash( { diff => $diff, template => 'diff.html', type => 'source' } );
}
diff --git a/lib/MetaCPAN/Web/Controller/Favorite.pm b/lib/MetaCPAN/Web/Controller/Favorite.pm
index 5e5764a26e..fa61b19dda 100644
--- a/lib/MetaCPAN/Web/Controller/Favorite.pm
+++ b/lib/MetaCPAN/Web/Controller/Favorite.pm
@@ -6,7 +6,8 @@ sub recent : Local : Args(0) {
my ( $self, $c ) = @_;
my $page_size = $c->req->get_page_size(100);
my $data
- = $c->model('API::Favorite')->recent( $c->req->page, $page_size );
+ = $c->model('API::Favorite')->recent( $c->req->page, $page_size )
+ ->get;
$c->stash(
{
header => 1,
@@ -23,7 +24,7 @@ sub recent : Local : Args(0) {
sub leaderboard : Local : Args(0) {
my ( $self, $c ) = @_;
- my $data = $c->model('API::Favorite')->leaderboard();
+ my $data = $c->model('API::Favorite')->leaderboard->get;
return unless $data;
$c->stash(
diff --git a/lib/MetaCPAN/Web/Controller/Feed.pm b/lib/MetaCPAN/Web/Controller/Feed.pm
index e5c6d6988f..e834893c27 100644
--- a/lib/MetaCPAN/Web/Controller/Feed.pm
+++ b/lib/MetaCPAN/Web/Controller/Feed.pm
@@ -103,8 +103,7 @@ sub author : Local : Args(1) {
$c->cdn_max_age('1y');
$c->add_author_key($author);
- my $author_cv = $c->model('API::Author')->get($author);
- my $author_info = $author_cv->recv;
+ my $author_info = $c->model('API::Author')->get($author)->get;
# If the author can be found, we get the hashref of author info. If it
# can't be found, we (confusingly) get a HashRef with "code" and "message"
@@ -114,9 +113,10 @@ sub author : Local : Args(1) {
$c->detach( '/not_found', [] );
}
- my $releases = $c->model('API::Release')->latest_by_author($author);
+ my $releases = $c->model('API::Release')->latest_by_author($author)->get;
- my $faves = $c->model('API::Favorite')->by_user( $author_info->{user} );
+ my $faves
+ = $c->model('API::Favorite')->by_user( $author_info->{user} )->get;
$c->stash->{feed} = $self->build_feed(
host => $c->config->{web_host},
@@ -136,7 +136,7 @@ sub distribution : Local : Args(1) {
$c->cdn_max_age('1y');
$c->add_dist_key($distribution);
- my $data = $c->model('API::Release')->versions($distribution)->recv;
+ my $data = $c->model('API::Release')->versions($distribution)->get;
$c->stash->{feed} = $self->build_feed(
host => $c->config->{web_host},
title => "Recent CPAN uploads of $distribution - MetaCPAN",
diff --git a/lib/MetaCPAN/Web/Controller/Lab.pm b/lib/MetaCPAN/Web/Controller/Lab.pm
index 6f4f16a257..d43fcf2263 100644
--- a/lib/MetaCPAN/Web/Controller/Lab.pm
+++ b/lib/MetaCPAN/Web/Controller/Lab.pm
@@ -28,7 +28,7 @@ sub dependencies : Local : Args(0) : Does('Sortable') {
my $data;
if ( $module = $c->req->params->{'module'} ) {
- $data = $c->model('API::Lab')->dependencies($module);
+ $data = $c->model('API::Lab')->dependencies($module)->get;
}
$c->stash(
@@ -43,7 +43,7 @@ sub dependencies : Local : Args(0) : Does('Sortable') {
sub dashboard : Local : Args(0) {
my ( $self, $c ) = @_;
- my $user = $c->model('API::User')->get_profile( $c->token )->recv;
+ my $user = $c->model('API::User')->get_profile( $c->token )->get;
my $report;
my $pauseid = $c->req->params->{'pauseid'};
@@ -55,7 +55,7 @@ sub dashboard : Local : Args(0) {
$pauseid = $user->{pauseid};
if ($pauseid) {
$report = $c->model('API::Lab')
- ->fetch_latest_distros( 1000, $pauseid );
+ ->fetch_latest_distros( 1000, $pauseid )->get;
}
}
diff --git a/lib/MetaCPAN/Web/Controller/Login.pm b/lib/MetaCPAN/Web/Controller/Login.pm
index 6d32570071..e942e12dd9 100644
--- a/lib/MetaCPAN/Web/Controller/Login.pm
+++ b/lib/MetaCPAN/Web/Controller/Login.pm
@@ -20,7 +20,7 @@ sub index : Path : Args(0) {
client_secret => $c->config->{consumer_secret},
code => $code,
},
- )->recv;
+ )->get;
$c->req->session->set( token => $data->{access_token} );
$c->authenticate( { token => $data->{access_token} } );
my $state = $c->req->params->{state} || q{};
diff --git a/lib/MetaCPAN/Web/Controller/Mirrors.pm b/lib/MetaCPAN/Web/Controller/Mirrors.pm
index dec1dcc4a9..1cae2746cd 100644
--- a/lib/MetaCPAN/Web/Controller/Mirrors.pm
+++ b/lib/MetaCPAN/Web/Controller/Mirrors.pm
@@ -52,7 +52,7 @@ sub index : Path : Args(0) {
)
: ( sort => [ 'continent', 'country' ] )
}
- )->recv;
+ )->get;
my $latest = [
map {
{
diff --git a/lib/MetaCPAN/Web/Controller/Permission.pm b/lib/MetaCPAN/Web/Controller/Permission.pm
index f58dc91140..cea67fd048 100644
--- a/lib/MetaCPAN/Web/Controller/Permission.pm
+++ b/lib/MetaCPAN/Web/Controller/Permission.pm
@@ -28,7 +28,7 @@ sub get : Private {
my $c = shift;
my ( $type, $name ) = @_;
- my $perms = $c->model('API::Permission')->get( $type, $name );
+ my $perms = $c->model('API::Permission')->get( $type, $name )->get;
if ( !$perms ) {
$c->stash(
diff --git a/lib/MetaCPAN/Web/Controller/Pod.pm b/lib/MetaCPAN/Web/Controller/Pod.pm
index ac2620a22a..6063d3d6c9 100644
--- a/lib/MetaCPAN/Web/Controller/Pod.pm
+++ b/lib/MetaCPAN/Web/Controller/Pod.pm
@@ -21,7 +21,7 @@ sub find : Path : Args(1) {
$c->browser_max_age('1h');
# TODO: Pass size param so we can disambiguate?
- $c->stash->{pod_file} = $c->model('API::Module')->find(@path)->recv;
+ $c->stash->{pod_file} = $c->model('API::Module')->find(@path)->get;
# TODO: Disambiguate if there's more than once match. #176
@@ -41,7 +41,7 @@ sub release : Local : Args {
$c->detach();
}
- $c->stash->{pod_file} = $c->model('API::Module')->get(@path)->recv;
+ $c->stash->{pod_file} = $c->model('API::Module')->get(@path)->get;
$c->stash->{permalinks} = 1;
$c->forward( 'view', [@path] );
}
@@ -58,7 +58,7 @@ sub distribution : Local : Args {
# Get latest "author/release" of dist so we can use it to find the file.
# TODO: Pass size param so we can disambiguate?
my $release = try {
- $c->model('API::Release')->find($dist)->recv->{hits}{hits}->[0]
+ $c->model('API::Release')->find($dist)->get->{hits}{hits}->[0]
->{_source};
} or $c->detach('/not_found');
@@ -66,7 +66,7 @@ sub distribution : Local : Args {
unshift @path, @$release{qw( author name )};
- $c->stash->{pod_file} = $c->model('API::Module')->get(@path)->recv;
+ $c->stash->{pod_file} = $c->model('API::Module')->get(@path)->get;
$c->forward( 'view', [@path] );
}
@@ -116,9 +116,7 @@ sub view : Private {
->get( @{$data}{qw(author release)} ),
},
$data,
- );
- $reqs = $self->recv_all($reqs);
-
+ )->get;
$self->stash_api_results( $c, $reqs, $data );
$self->add_favorites_data( $data, $reqs->{favorites}, $data );
@@ -224,7 +222,7 @@ sub view : Private {
$c->add_dist_key($dist);
$c->add_author_key( $release->{author} );
- $c->stash( $c->model('API::Favorite')->find_plussers($dist) );
+ $c->stash( $c->model('API::Favorite')->find_plussers($dist)->get );
$c->stash(
$c->model(
diff --git a/lib/MetaCPAN/Web/Controller/Raw.pm b/lib/MetaCPAN/Web/Controller/Raw.pm
index 4628e6a781..a4922c1d02 100644
--- a/lib/MetaCPAN/Web/Controller/Raw.pm
+++ b/lib/MetaCPAN/Web/Controller/Raw.pm
@@ -8,9 +8,9 @@ BEGIN { extends 'MetaCPAN::Web::Controller' }
sub index : Path : Args {
my ( $self, $c, @module ) = @_;
- my ( $source, $module ) = (
- $c->model('API::Module')->source(@module)->recv,
- $c->model('API::Module')->get(@module)->recv
+ my ( $source, $module ) = map { $_->get } (
+ $c->model('API::Module')->source(@module),
+ $c->model('API::Module')->get(@module),
);
$c->detach('/not_found') unless ( $source->{raw} );
if ( $c->req->parameters->{download} ) {
diff --git a/lib/MetaCPAN/Web/Controller/Recent.pm b/lib/MetaCPAN/Web/Controller/Recent.pm
index 8f55e1554d..1f913e4069 100644
--- a/lib/MetaCPAN/Web/Controller/Recent.pm
+++ b/lib/MetaCPAN/Web/Controller/Recent.pm
@@ -14,7 +14,7 @@ sub index : Path : Args(0) {
my ($data)
= $c->model('API::Release')
- ->recent( $req->page, $page_size, $req->params->{f} || 'l' )->recv;
+ ->recent( $req->page, $page_size, $req->params->{f} || 'l' )->get;
my $latest = [ map { $_->{fields} } @{ $data->{hits}->{hits} } ];
single_valued_arrayref_to_scalar($latest);
diff --git a/lib/MetaCPAN/Web/Controller/Recent/TopUploaders.pm b/lib/MetaCPAN/Web/Controller/Recent/TopUploaders.pm
index e9367e1a38..387221e4c9 100644
--- a/lib/MetaCPAN/Web/Controller/Recent/TopUploaders.pm
+++ b/lib/MetaCPAN/Web/Controller/Recent/TopUploaders.pm
@@ -25,10 +25,10 @@ sub all : Local : Args(0) {
sub topuploaders : Private {
my ( $self, $c, $range ) = @_;
- my $data = $c->model('API::Release')->topuploaders($range);
+ my $data = $c->model('API::Release')->topuploaders($range)->get;
my $authors
- = $c->model('API::Author')->get( keys %{ $data->{counts} } )->recv;
+ = $c->model('API::Author')->get( keys %{ $data->{counts} } )->get;
$c->stash(
{
diff --git a/lib/MetaCPAN/Web/Controller/Release.pm b/lib/MetaCPAN/Web/Controller/Release.pm
index 7e42bc70f4..ebce23af64 100644
--- a/lib/MetaCPAN/Web/Controller/Release.pm
+++ b/lib/MetaCPAN/Web/Controller/Release.pm
@@ -31,7 +31,7 @@ sub by_distribution : Chained('root') PathPart('') Args(1) {
sub index : Chained('/') PathPart('release') CaptureArgs(1) {
my ( $self, $c, $dist ) = @_;
- $c->stash( $c->model('API::Favorite')->find_plussers($dist) );
+ $c->stash( $c->model('API::Favorite')->find_plussers($dist)->get );
}
sub plusser_display : Chained('index') PathPart('plussers') Args(0) {
@@ -66,7 +66,7 @@ sub view : Private {
my $model = $c->stash->{model};
my $data = delete $c->stash->{data};
- my $out = $data->recv->{hits}->{hits}->[0]->{_source};
+ my $out = $data->get->{hits}->{hits}->[0]->{_source};
$c->detach('/not_found') unless ($out);
@@ -81,8 +81,7 @@ sub view : Private {
changes => $c->model('API::Changes')->get( $author, $release ),
},
$out,
- );
- $reqs = $self->recv_all($reqs);
+ )->get;
$self->stash_api_results( $c, $reqs, $out );
$self->add_favorites_data( $out, $reqs->{favorites}, $out );
@@ -122,7 +121,8 @@ sub view : Private {
)->summary_hash
);
- $c->stash( $c->model('API::Favorite')->find_plussers($distribution) );
+ $c->stash(
+ $c->model('API::Favorite')->find_plussers($distribution)->get );
# Simplify the file data we pass to the template.
my @view_files = map +{ %{ $_->{fields} }, %{ $_->{_source} }, },
diff --git a/lib/MetaCPAN/Web/Controller/Requires.pm b/lib/MetaCPAN/Web/Controller/Requires.pm
index e2e859f948..eb300e6b76 100644
--- a/lib/MetaCPAN/Web/Controller/Requires.pm
+++ b/lib/MetaCPAN/Web/Controller/Requires.pm
@@ -28,7 +28,7 @@ sub distribution : Local : Args(1) : Does('Sortable') {
my $data
= $c->model('API::Release')
->reverse_dependencies( $distribution, $c->req->page, $page_size,
- $sort )->recv;
+ $sort )->get;
$c->stash(
{
%{$data},
@@ -47,7 +47,7 @@ sub module : Local : Args(1) : Does('Sortable') {
my $data
= $c->model('API::Module')
- ->requires( $module, $c->req->page, $page_size, $sort );
+ ->requires( $module, $c->req->page, $page_size, $sort )->get;
$c->stash(
{
%{$data},
diff --git a/lib/MetaCPAN/Web/Controller/Search.pm b/lib/MetaCPAN/Web/Controller/Search.pm
index 038f60f139..68aa3d3985 100644
--- a/lib/MetaCPAN/Web/Controller/Search.pm
+++ b/lib/MetaCPAN/Web/Controller/Search.pm
@@ -41,14 +41,14 @@ sub index : Path : Args(0) {
$query =~ s[^ (?: \\ | ! ) ][]x
)
{
- my $module = $model->first($query)->recv;
+ my $module = $model->first($query)->get;
$module = $module->[0] if $module and is_arrayref($module);
if ( $module && $module eq $query ) {
$c->res->redirect( '/pod/' . $module );
$c->detach;
}
else {
- my $author = $c->model('API::Author')->search($query)->recv;
+ my $author = $c->model('API::Author')->search($query)->get;
if ( $author->{total} == 1
&& $query eq $author->{results}->[0]->{pauseid} )
{
@@ -68,7 +68,7 @@ sub index : Path : Args(0) {
my $results = $model->search_web( $query, $from, $page_size );
my $authors = $c->model('API::Author')->search( $query, $from );
- ( $results, $authors ) = ( $results->recv, $authors->recv );
+ ( $results, $authors ) = ( $results->get, $authors->get );
if ( !$results->{total} && !$authors->{total} ) {
my $suggest = $query;
diff --git a/lib/MetaCPAN/Web/Controller/Search/AutoComplete.pm b/lib/MetaCPAN/Web/Controller/Search/AutoComplete.pm
index 8ebb0c4f3b..c8a2f77d4e 100644
--- a/lib/MetaCPAN/Web/Controller/Search/AutoComplete.pm
+++ b/lib/MetaCPAN/Web/Controller/Search/AutoComplete.pm
@@ -19,12 +19,12 @@ sub index : Path : Args(0) {
value => "$_->{pauseid} - $_->{name}",
data => { id => $_->{pauseid}, type => 'author' }
},
- @{ $author_data->recv->{results} }
+ @{ $author_data->get->{results} }
),
(
map +{ value => $_, data => { module => $_, type => 'module' } },
uniq map $_->{documentation},
- @{ $module_data->recv->{results} }
+ @{ $module_data->get->{results} }
),
);
diff --git a/lib/MetaCPAN/Web/Controller/Source.pm b/lib/MetaCPAN/Web/Controller/Source.pm
index 69311588fb..878d71f35f 100644
--- a/lib/MetaCPAN/Web/Controller/Source.pm
+++ b/lib/MetaCPAN/Web/Controller/Source.pm
@@ -28,19 +28,19 @@ sub index : Path : Args {
my ( $source, $module );
if ( @module == 1 ) {
- $module = $c->model('API::Module')->find(@module)->recv;
+ $module = $c->model('API::Module')->find(@module)->get;
$module[0] = join q{/}, $module->{author}, $module->{release},
$module->{path};
- $source = $c->model('API::Module')->source(@module)->recv;
+ $source = $c->model('API::Module')->source(@module)->get;
}
else {
- ( $source, $module ) = (
- $c->model('API::Module')->source(@module)->recv,
- $c->model('API::Module')->get(@module)->recv,
+ ( $source, $module ) = map { $_->get } (
+ $c->model('API::Module')->source(@module),
+ $c->model('API::Module')->get(@module),
);
}
if ( $module->{directory} ) {
- my $files = $c->model('API::File')->dir(@module);
+ my $files = $c->model('API::File')->dir(@module)->get;
$c->res->last_modified( $module->{date} );
$c->stash(
{
diff --git a/lib/MetaCPAN/Web/Model/API.pm b/lib/MetaCPAN/Web/Model/API.pm
index 0ea36c78da..7705f5f9c0 100644
--- a/lib/MetaCPAN/Web/Model/API.pm
+++ b/lib/MetaCPAN/Web/Model/API.pm
@@ -5,22 +5,39 @@ extends 'Catalyst::Model';
use namespace::autoclean;
-use AnyEvent::Curl::Multi;
-use Encode ();
-use HTTP::Request ();
+use Encode ();
use Cpanel::JSON::XS qw( decode_json encode_json );
+use IO::Async::Loop;
+use IO::Async::SSL;
+use IO::Socket::SSL qw(SSL_VERIFY_PEER);
+use Net::Async::HTTP;
+use URI;
+use URI::QueryParam;
use MetaCPAN::Web::Types qw( Uri );
-use MooseX::ClassAttribute;
use Try::Tiny qw( catch try );
-use URI::QueryParam;
use Log::Log4perl;
-class_has client => (
- is => 'ro',
- lazy => 1,
- default =>
- sub { return AnyEvent::Curl::Multi->new( max_concurrency => 5 ) },
-);
+my $loop;
+
+sub loop {
+ $loop ||= IO::Async::Loop->new;
+}
+
+my $client;
+
+sub client {
+ $client ||= do {
+ my $http = Net::Async::HTTP->new(
+ user_agent =>
+ 'MetaCPAN-Web/1.0 (https://github.com/metacpan/metacpan-web)',
+ max_connections_per_host => 5,
+ SSL_verify_mode => SSL_VERIFY_PEER,
+ timeout => 10,
+ );
+ $_[0]->loop->add($http);
+ $http;
+ };
+}
has api_secure => (
is => 'ro',
@@ -29,18 +46,6 @@ has api_secure => (
required => 1,
);
-{
- no warnings 'once';
- $AnyEvent::HTTP::PERSISTENT_TIMEOUT = 0;
- $AnyEvent::HTTP::USERAGENT
- = 'Mozilla/5.0 (compatible; U; MetaCPAN-Web/1.0; '
- . '+https://github.com/metacpan/metacpan-web)';
-}
-
-sub cv {
- AE::cv;
-}
-
=head2 COMPONENT
Set C config parameters from the app config object.
@@ -64,8 +69,6 @@ sub model {
sub request {
my ( $self, $path, $search, $params, $method ) = @_;
- my $req = $self->cv;
-
my $url = $self->api_secure->clone;
# the order of the following 2 lines matters
@@ -93,39 +96,23 @@ sub request {
# encode_json returns an octet string
$request->add_content( encode_json($search) ) if $search;
- $self->client->request($request)->cv->cb(
- sub {
- my $cv = shift;
- try {
- my ($response) = $cv->recv;
- if ( !$response ) {
- $req->croak(
- "bad response when requesting " . $request->uri );
- return;
- }
- my $content_type = $response->header('content-type') || '';
- my $data = $response->content;
-
- if ( $content_type =~ /^application\/json/ ) {
- try {
- my $json = $self->process_json_response($data);
- $req->send($json);
- }
- catch {
- $req->send( $self->raw_api_response($data) );
- };
- }
- else {
- # Response is raw data, e.g. text/plain
- $req->send( $self->raw_api_response($data) );
- }
+ $self->client->do_request( request => $request )->transform(
+ done => sub {
+ my $response = shift;
+ my $content_type = $response->header('content-type') || '';
+ my $data = $response->content;
+
+ if ( $content_type =~ /^application\/json/ ) {
+ my $out;
+ eval { $out = $self->process_json_response($data); };
+ return $out
+ if $out;
}
- catch {
- $req->croak($_);
- };
+
+ # Response is raw data, e.g. text/plain
+ return $self->raw_api_response($data);
}
);
- return $req;
}
sub process_json_response {
diff --git a/lib/MetaCPAN/Web/Model/API/Author.pm b/lib/MetaCPAN/Web/Model/API/Author.pm
index d303598b17..31761d40f1 100644
--- a/lib/MetaCPAN/Web/Model/API/Author.pm
+++ b/lib/MetaCPAN/Web/Model/API/Author.pm
@@ -49,7 +49,6 @@ sub get {
sub search {
my ( $self, $query, $from ) = @_;
- my $cv = $self->cv;
my $search = {
query => {
bool => {
@@ -75,23 +74,20 @@ sub search {
from => $from || 0,
};
- $self->request( '/author/_search', $search )->cb(
- sub {
- my $results = shift->recv
+ return $self->request( '/author/_search', $search )->transform(
+ done => sub {
+ my $results = shift
|| { hits => { total => 0, hits => [] } };
- $cv->send(
- {
- results => [
- map { +{ %{ $_->{_source} }, id => $_->{_id} } }
- @{ $results->{hits}{hits} }
- ],
- total => $results->{hits}{total} || 0,
- took => $results->{took}
- }
- );
- }
+ return {
+ results => [
+ map { +{ %{ $_->{_source} }, id => $_->{_id} } }
+ @{ $results->{hits}{hits} }
+ ],
+ total => $results->{hits}{total} || 0,
+ took => $results->{took}
+ };
+ },
);
- return $cv;
}
sub by_user {
@@ -106,10 +102,11 @@ sub by_user {
else {
$ret = $self->request("/author/by_user/$users");
}
- return unless $ret;
-
- my $data = $ret->recv;
- return ( exists $data->{authors} ? $data->{authors} : [] );
+ $ret->transform(
+ done => sub {
+ return exists $_[0]->{authors} ? $_[0]->{authors} : [];
+ }
+ );
}
__PACKAGE__->meta->make_immutable;
diff --git a/lib/MetaCPAN/Web/Model/API/Changes/Parser.pm b/lib/MetaCPAN/Web/Model/API/Changes/Parser.pm
index ce817172e9..235f80e945 100644
--- a/lib/MetaCPAN/Web/Model/API/Changes/Parser.pm
+++ b/lib/MetaCPAN/Web/Model/API/Changes/Parser.pm
@@ -17,7 +17,7 @@ sub load {
}
sub parse {
- my ( $class, $string ) = @_;
+ my ( undef, $string ) = @_;
my @lines = split /\r\n?|\n/, $string;
diff --git a/lib/MetaCPAN/Web/Model/API/Contributors.pm b/lib/MetaCPAN/Web/Model/API/Contributors.pm
index 65c4ba9151..3c1a5189fe 100644
--- a/lib/MetaCPAN/Web/Model/API/Contributors.pm
+++ b/lib/MetaCPAN/Web/Model/API/Contributors.pm
@@ -25,19 +25,17 @@ it under the same terms as Perl itself.
sub get {
my ( $self, $author, $release ) = @_;
- my $cv = $self->cv;
# If there's no release, we'll just redirect
$release //= {};
$self->request( '/release/contributors/' . $author . '/' . $release, )
- ->cb(
- sub {
- my ($contributors) = shift->recv;
- $cv->send( $contributors->{contributors} );
+ ->transform(
+ done => sub {
+ my $data = shift;
+ return $data->{contributors};
}
);
- return $cv;
}
__PACKAGE__->meta->make_immutable;
diff --git a/lib/MetaCPAN/Web/Model/API/Favorite.pm b/lib/MetaCPAN/Web/Model/API/Favorite.pm
index 70723e2fce..73d3e9bd65 100644
--- a/lib/MetaCPAN/Web/Model/API/Favorite.pm
+++ b/lib/MetaCPAN/Web/Model/API/Favorite.pm
@@ -5,6 +5,7 @@ use namespace::autoclean;
extends 'MetaCPAN::Web::Model::API';
use List::Util qw(uniq);
+use Future;
use Importer 'MetaCPAN::Web::Elasticsearch::Adapter' =>
qw/ single_valued_arrayref_to_scalar /;
@@ -12,16 +13,14 @@ use Importer 'MetaCPAN::Web::Elasticsearch::Adapter' =>
sub get {
my ( $self, $user, @distributions ) = @_;
@distributions = uniq @distributions;
- my $cv = $self->cv;
# If there are no distributions this will build a query with an empty
# filter and ES will return a parser error... so just skip it.
if ( !@distributions ) {
- $cv->send( {} );
- return $cv;
+ return Future->wrap( {} );
}
- $self->request(
+ return $self->request(
'/favorite/_search',
{
size => 0,
@@ -49,113 +48,128 @@ sub get {
: (),
}
}
- )->cb(
- sub {
- my $data = shift->recv;
- $cv->send(
- {
- took => $data->{took},
- favorites => {
- map { $_->{key} => $_->{doc_count} }
- @{ $data->{aggregations}->{favorites}->{buckets} }
- },
- myfavorites => $user
- ? {
- map { $_->{key} => $_->{doc_count} } @{
- $data->{aggregations}->{myfavorites}->{entries}
- ->{buckets}
- }
- }
- : {},
- }
- );
+ )->transform(
+ done => sub {
+ my $data = shift;
+ return {
+ took => $data->{took},
+ favorites => {
+ map { $_->{key} => $_->{doc_count} }
+ @{ $data->{aggregations}->{favorites}->{buckets} }
+ },
+ myfavorites => $user
+ ? {
+ map { $_->{key} => $_->{doc_count} } @{
+ $data->{aggregations}->{myfavorites}->{entries}
+ ->{buckets}
+ }
+ }
+ : {},
+ };
}
);
- return $cv;
}
sub by_user {
my ( $self, $user, $size ) = @_;
$size ||= 250;
- my $ret = $self->request( "/favorite/by_user/$user", { size => $size } );
- return unless $ret;
- my $data = $ret->recv;
- return [] unless exists $data->{favorites};
- return $data->{favorites};
+ my $ret
+ = $self->request( "/favorite/by_user/$user", { size => $size } )
+ ->transform(
+ done => sub {
+ my $data = shift;
+ return [] unless exists $data->{favorites};
+ return $data->{favorites};
+ }
+ );
}
sub recent {
my ( $self, $page, $page_size ) = @_;
- my $data = $self->request( '/favorite/recent',
- { size => $page_size, page => $page } )->recv;
-
- my @user_ids = map { $_->{user} } @{ $data->{favorites} };
- return $data unless @user_ids;
-
- my $authors
- = $self->request( '/author/by_user', undef, { user => \@user_ids } )
- ->recv;
- if ( $authors and exists $authors->{authors} ) {
- my %author_for_user_id
- = map { $_->{user} => $_->{pauseid} } @{ $authors->{authors} };
- for my $fav ( @{ $data->{favorites} } ) {
- next unless exists $author_for_user_id{ $fav->{user} };
- $fav->{clicked_by_author} = $author_for_user_id{ $fav->{user} };
+ $self->request( '/favorite/recent',
+ { size => $page_size, page => $page } )->then(
+ sub {
+ my $data = shift;
+ my @user_ids = map { $_->{user} } @{ $data->{favorites} };
+ return Future->done unless @user_ids;
+ $self->request( '/author/by_user', undef, { user => \@user_ids } )
+ ->transform(
+ done => sub {
+ my $authors = shift;
+ if ( $authors and exists $authors->{authors} ) {
+ my %author_for_user_id
+ = map { $_->{user} => $_->{pauseid} }
+ @{ $authors->{authors} };
+ for my $fav ( @{ $data->{favorites} } ) {
+ next
+ unless
+ exists $author_for_user_id{ $fav->{user} };
+ $fav->{clicked_by_author}
+ = $author_for_user_id{ $fav->{user} };
+ }
+ }
+ }
+ );
}
- }
-
- return $data;
+ );
}
sub leaderboard {
my ($self) = @_;
- my $data = $self->request('/favorite/leaderboard')->recv;
- return $data;
+ $self->request('/favorite/leaderboard');
}
sub find_plussers {
my ( $self, $distribution ) = @_;
# search for all users, match all according to the distribution.
- my $plusser = $self->by_dist($distribution);
- my $plusser_data = $plusser->recv;
-
- # store in an array.
- my @plusser_users = map { $_->{user} }
- map { single_valued_arrayref_to_scalar( $_->{_source} ) }
- @{ $plusser_data->{hits}->{hits} };
- my $total_plussers = @plusser_users;
-
- # find plussers by pause ids.
- my $authors
- = @plusser_users
- ? $self->plusser_by_id( \@plusser_users )->recv->{hits}->{hits}
- : [];
-
- my @plusser_details = map {
- {
- id => $_->{_source}->{pauseid},
- pic => $_->{_source}->{gravatar_url},
+ $self->by_dist($distribution)->then(
+ sub {
+ my $plusser_data = shift;
+
+ # store in an array.
+ my @plusser_users = map { $_->{user} }
+ map { single_valued_arrayref_to_scalar( $_->{_source} ) }
+ @{ $plusser_data->{hits}->{hits} };
+ my $total_plussers = @plusser_users;
+
+ # find plussers by pause ids.
+ return Future->done( { hits => { hits => [] } }, $total_plussers )
+ unless @plusser_users;
+ $self->plusser_by_id( \@plusser_users )->transform(
+ done => sub {
+ return ( $_[0], $total_plussers );
+ }
+ );
}
- } @{$authors};
-
- my $total_authors = @plusser_details;
+ )->transform(
+ done => sub {
+ my ( $data, $total_plussers ) = @_;
+ my $authors = $data->{hits}{hits};
+ my @plusser_details = map {
+ {
+ id => $_->{_source}->{pauseid},
+ pic => $_->{_source}->{gravatar_url},
+ }
+ } @{$authors};
+ my $total_authors = @plusser_details;
- # find total non pauseid users who have ++ed the dist.
- my $total_nonauthors = ( $total_plussers - $total_authors );
+ # find total non pauseid users who have ++ed the dist.
+ my $total_nonauthors = ( $total_plussers - $total_authors );
- # number of pauseid users can be more than total plussers
- # then set 0 to non pauseid users
- $total_nonauthors = 0 if $total_nonauthors < 0;
+ # number of pauseid users can be more than total plussers
+ # then set 0 to non pauseid users
+ $total_nonauthors = 0 if $total_nonauthors < 0;
- return (
- {
- plusser_authors => \@plusser_details,
- plusser_others => $total_nonauthors,
- plusser_data => $distribution
+ return (
+ {
+ plusser_authors => \@plusser_details,
+ plusser_others => $total_nonauthors,
+ plusser_data => $distribution
+ }
+ );
}
- );
-
+ );
}
# to search for v0/favorite/_search/{user} for the particular $distribution.
diff --git a/lib/MetaCPAN/Web/Model/API/File.pm b/lib/MetaCPAN/Web/Model/API/File.pm
index 59d27f9015..ba3ca8f100 100644
--- a/lib/MetaCPAN/Web/Model/API/File.pm
+++ b/lib/MetaCPAN/Web/Model/API/File.pm
@@ -15,8 +15,11 @@ sub source {
sub dir {
my ( $self, @path ) = @_;
my $path = join '/', @path;
- my $data = $self->request("/file/dir/$path")->recv;
- return $data->{dir};
+ my $data = $self->request("/file/dir/$path")->transform(
+ done => sub {
+ $_[0]->{dir};
+ }
+ );
}
__PACKAGE__->meta->make_immutable;
diff --git a/lib/MetaCPAN/Web/Model/API/Lab.pm b/lib/MetaCPAN/Web/Model/API/Lab.pm
index 05756e272e..4c86618a10 100644
--- a/lib/MetaCPAN/Web/Model/API/Lab.pm
+++ b/lib/MetaCPAN/Web/Model/API/Lab.pm
@@ -27,12 +27,14 @@ sub dependencies {
}
$deps{$module}{orig} = 1;
- return [
- map { $deps{$_} }
- reverse
- sort { $deps{$a}{date} cmp $deps{$b}{date} }
- keys %deps
- ];
+ return Future->done(
+ [
+ map { $deps{$_} }
+ reverse
+ sort { $deps{$a}{date} cmp $deps{$b}{date} }
+ keys %deps
+ ]
+ );
}
my %CORE = map { $_ => 1 } qw(
@@ -55,13 +57,13 @@ sub _handle_module {
}
# get the distribution that provides this module
- my $rm = $self->request("/module/$module")->recv;
+ my $rm = $self->request("/module/$module")->get;
my %dep = (
dist => $rm->{distribution},
date => $rm->{date},
);
- my $rd = $self->request("/release/$rm->{distribution}")->recv;
+ my $rd = $self->request("/release/$rm->{distribution}")->get;
$dep{license} = $rd->{license};
@@ -73,7 +75,7 @@ sub _handle_module {
sub fetch_latest_distros {
my ( $self, $size, $pauseid ) = @_;
- my $r = $self->request(
+ $self->request(
'/release/_search',
{
query => {
@@ -94,64 +96,73 @@ sub fetch_latest_distros {
],
size => $size,
},
- )->recv;
- my %licenses;
- my %distros;
+ )->transform(
+ done => sub {
+ my $data = shift;
+ my %licenses;
+ my %distros;
- foreach my $d ( @{ $r->{hits}{hits} } ) {
- my $license = $d->{_source}{license}[0];
- my $distro = $d->{_source}{distribution};
- my $repo = $d->{_source}{'resources.repository'};
+ foreach my $d ( @{ $data->{hits}{hits} } ) {
+ my $license = $d->{_source}{license}[0];
+ my $distro = $d->{_source}{distribution};
+ my $repo = $d->{_source}{'resources.repository'};
- next if $distros{$distro}; # show the first one
+ next if $distros{$distro}; # show the first one
# TODO: can we fetch the bug count in one call for all the distributions?
- my $distribution = $self->request("/distribution/$distro")->recv;
- if ( $distribution->{bugs} ) {
- $distros{$distro}{bugs} = $distribution->{bugs}{active};
- }
+ my $distribution
+ = $self->request("/distribution/$distro")->get;
+ if ( $distribution->{bugs} ) {
+ $distros{$distro}{bugs} = $distribution->{bugs}{active};
+ }
- $distros{$distro}{test} = $d->{_source}{tests};
- my $total = 0;
- $total += ( $distros{$distro}{test}{$_} // 0 ) for qw(pass fail na);
- $distros{$distro}{test}{ratio}
- = $total
- ? int( 100 * ( $distros{$distro}{test}{pass} // 0 ) / $total )
- : q{};
-
- if ( $license
- and $license ne 'unknown'
- and $license ne 'open_source' )
- {
- $licenses{$license}++;
- }
- else {
- $distros{$distro}{license} = 1;
- }
+ $distros{$distro}{test} = $d->{_source}{tests};
+ my $total = 0;
+ $total += ( $distros{$distro}{test}{$_} // 0 )
+ for qw(pass fail na);
+ $distros{$distro}{test}{ratio}
+ = $total
+ ? int(
+ 100 * ( $distros{$distro}{test}{pass} // 0 ) / $total )
+ : q{};
+
+ if ( $license
+ and $license ne 'unknown'
+ and $license ne 'open_source' )
+ {
+ $licenses{$license}++;
+ }
+ else {
+ $distros{$distro}{license} = 1;
+ }
- $distros{$distro}{unauthorized}
- = $d->{_source}{authorized} eq 'false' ? 1 : 0;
+ $distros{$distro}{unauthorized}
+ = $d->{_source}{authorized} eq 'false' ? 1 : 0;
- # See also root/inc/release-infro.html
- if ( $repo and ( $repo->{url} or $repo->{web} ) ) {
+ # See also root/inc/release-infro.html
+ if ( $repo and ( $repo->{url} or $repo->{web} ) ) {
- # TODO: shall we collect the types and list them?
- }
- else {
- $distros{$distro}{repo} = 1;
- }
- if ( not $d->{_source}{abstract} ) {
- $distros{$distro}{abstract} = 1;
- }
+ # TODO: shall we collect the types and list them?
+ }
+ else {
+ $distros{$distro}{repo} = 1;
+ }
+ if ( not $d->{_source}{abstract} ) {
+ $distros{$distro}{abstract} = 1;
+ }
- ( $distros{$distro}{date} = $d->{_source}{date} ) =~ s/\.\d+Z$//;
- $distros{$distro}{version} = $d->{_source}{'metadata.version'};
- }
+ ( $distros{$distro}{date} = $d->{_source}{date} )
+ =~ s/\.\d+Z$//;
+ $distros{$distro}{version}
+ = $d->{_source}{'metadata.version'};
+ }
- return {
- licenses => \%licenses,
- distros => \%distros,
- };
+ return {
+ licenses => \%licenses,
+ distros => \%distros,
+ };
+ }
+ );
}
__PACKAGE__->meta->make_immutable;
diff --git a/lib/MetaCPAN/Web/Model/API/Module.pm b/lib/MetaCPAN/Web/Model/API/Module.pm
index d9750f2da1..f8c1a8f9e4 100644
--- a/lib/MetaCPAN/Web/Model/API/Module.pm
+++ b/lib/MetaCPAN/Web/Model/API/Module.pm
@@ -33,63 +33,46 @@ sub find {
sub autocomplete {
my ( $self, $query ) = @_;
- my $cv = $self->cv;
$self->request( "/search/autocomplete", undef,
- { q => $query, size => 50 } )->cb(
- sub {
- my $data = shift->recv;
- $cv->send(
- {
- results => [
- map { $_->{fields} } @{ $data->{hits}->{hits} || [] }
- ]
- }
- );
+ { q => $query, size => 50 } )->transform(
+ done => sub {
+ my $data = shift;
+ return { results =>
+ [ map { $_->{fields} } @{ $data->{hits}->{hits} || [] } ]
+ };
}
);
- return $cv;
}
sub search_web {
my ( $self, $query, $from, $page_size ) = @_;
- my $cv = $self->cv;
$self->request( "/search/web", undef,
- { q => $query, size => $page_size // 20, from => $from // 0 } )->cb(
- sub {
- my $data = shift->recv;
- $cv->send($data);
- }
- );
- return $cv;
+ { q => $query, size => $page_size // 20, from => $from // 0 } );
}
sub first {
my ( $self, $query ) = @_;
- my $cv = $self->cv;
- $self->request( "/search/simple", undef, { q => $query } )->cb(
- sub {
- my ($result) = shift->recv;
- return $cv->send(undef) unless ( $result->{hits}->{total} );
- $cv->send(
- $result->{hits}->{hits}->[0]->{fields}->{documentation} );
+ $self->request( "/search/simple", undef, { q => $query } )->transform(
+ done => sub {
+ my $data = shift;
+ return undef
+ unless ( $data->{hits}->{total} );
+ return $data->{hits}->{hits}->[0]->{fields}->{documentation};
}
);
- return $cv;
}
sub requires {
my ( $self, $module, $page, $page_size ) = @_;
- my $data = $self->request(
+ $self->request(
"/release/requires/$module",
undef,
{
page => $page,
page_size => $page_size,
},
- )->recv;
-
- return $data;
+ );
}
__PACKAGE__->meta->make_immutable;
diff --git a/lib/MetaCPAN/Web/Model/API/Permission.pm b/lib/MetaCPAN/Web/Model/API/Permission.pm
index 3acbc67188..82aba9a9ee 100644
--- a/lib/MetaCPAN/Web/Model/API/Permission.pm
+++ b/lib/MetaCPAN/Web/Model/API/Permission.pm
@@ -16,10 +16,14 @@ sub get {
my ( $self, $type, $name ) = @_;
if ( $type eq 'module' ) {
- my $module = $self->request( '/permission/' . $name )->recv;
-
- # return undef if there's a 404
- return $module->{code} ? undef : $module;
+ return $self->request( '/permission/' . $name )->transform(
+ done => sub {
+
+ # return undef if there's a 404
+ my $data = shift;
+ return $data->{code} ? undef : $data;
+ }
+ );
}
if ( $type eq 'distribution' ) {
@@ -51,32 +55,40 @@ sub _get_author_modules {
sub _get_modules_in_distribution {
my $self = shift;
my $name = shift;
- return undef unless $name;
+ return Future->done(undef) unless $name;
- my $res = $self->request("/package/modules/$name")->recv;
- my @modules = $res->{modules} ? @{ $res->{modules} } : undef;
+ $self->request("/package/modules/$name")->then(
+ sub {
+ my $res = shift;
+ my @modules = $res->{modules} ? @{ $res->{modules} } : undef;
- return undef unless @modules;
+ return Future->done(undef) unless @modules;
- my @perm_search
- = map { +{ term => { module_name => $_ } } } @modules;
+ my @perm_search
+ = map { +{ term => { module_name => $_ } } } @modules;
- my $search = {
- query => { bool => { should => \@perm_search } },
- size => 1_000,
- };
+ my $search = {
+ query => { bool => { should => \@perm_search } },
+ size => 1_000,
+ };
- return $self->_search_perms($search);
+ return $self->_search_perms($search);
+ }
+ );
}
sub _search_perms {
my $self = shift;
my $search = shift;
- my $perms_found = $self->request( '/permission/_search', $search )->recv;
- my @perms = sort { $a->{module_name} cmp $b->{module_name} }
- map { $_->{_source} } @{ $perms_found->{hits}->{hits} };
- return @perms ? \@perms : undef;
+ $self->request( '/permission/_search', $search )->transform(
+ done => sub {
+ my $perms = shift;
+ my @perms = sort { $a->{module_name} cmp $b->{module_name} }
+ map { $_->{_source} } @{ $perms->{hits}->{hits} };
+ return @perms ? \@perms : undef;
+ }
+ );
}
__PACKAGE__->meta->make_immutable;
diff --git a/lib/MetaCPAN/Web/Model/API/Rating.pm b/lib/MetaCPAN/Web/Model/API/Rating.pm
index b06da355a1..e2d64db5f3 100644
--- a/lib/MetaCPAN/Web/Model/API/Rating.pm
+++ b/lib/MetaCPAN/Web/Model/API/Rating.pm
@@ -1,6 +1,7 @@
package MetaCPAN::Web::Model::API::Rating;
use Moose;
use namespace::autoclean;
+use Future;
extends 'MetaCPAN::Web::Model::API';
@@ -28,16 +29,14 @@ use List::Util qw(uniq);
sub get {
my ( $self, @distributions ) = @_;
@distributions = uniq @distributions;
- my $cv = $self->cv;
# If there are no distributions this will build a query with an empty
# filter and ES will return a parser error... so just skip it.
if ( !@distributions ) {
- $cv->send( {} );
- return $cv;
+ return Future->done( {} );
}
- $self->request(
+ return $self->request(
'/rating/_search',
{
size => 0,
@@ -59,22 +58,18 @@ sub get {
}
}
}
- )->cb(
- sub {
- my ($ratings) = shift->recv;
- $cv->send(
- {
- took => $ratings->{took},
- ratings => {
- map { $_->{key} => $_->{ratings_dist} } @{
- $ratings->{aggregations}->{ratings}->{buckets}
- }
- }
+ )->transform(
+ done => sub {
+ my $data = shift;
+ return {
+ took => $data->{took},
+ ratings => {
+ map { $_->{key} => $_->{ratings_dist} }
+ @{ $data->{aggregations}->{ratings}->{buckets} }
}
- );
+ };
}
);
- return $cv;
}
__PACKAGE__->meta->make_immutable;
diff --git a/lib/MetaCPAN/Web/Model/API/Release.pm b/lib/MetaCPAN/Web/Model/API/Release.pm
index c19ec33415..c59d8e43e7 100644
--- a/lib/MetaCPAN/Web/Model/API/Release.pm
+++ b/lib/MetaCPAN/Web/Model/API/Release.pm
@@ -49,15 +49,13 @@ sub distribution {
sub latest_by_author {
my ( $self, $pauseid ) = @_;
- my $data = $self->request("/release/latest_by_author/$pauseid")->recv;
- return $data;
+ $self->request("/release/latest_by_author/$pauseid");
}
sub all_by_author {
my ( $self, $pauseid, $page, $page_size ) = @_;
- my $data = $self->request( "/release/all_by_author/$pauseid",
- undef, { page => $page, page_size => $page_size } )->recv;
- return $data;
+ $self->request( "/release/all_by_author/$pauseid",
+ undef, { page => $page, page_size => $page_size } );
}
sub recent {
@@ -208,11 +206,10 @@ sub find {
sub reverse_dependencies {
my ( $self, $distribution, $page, $page_size, $sort ) = @_;
$sort ||= { date => 'desc' };
- my $cv = $self->cv;
# TODO: do we need to do a taint-check on $distribution before inserting it into the url?
# maybe the fact that it came through as a Catalyst Arg is enough?
- $self->request(
+ return $self->request(
"/search/reverse_dependencies/$distribution",
{
query => {
@@ -227,20 +224,16 @@ sub reverse_dependencies {
from => $page * $page_size - $page_size,
sort => [$sort],
}
- )->cb(
- sub {
- my $data = shift->recv;
- $cv->send(
- {
- data =>
- [ map { $_->{_source} } @{ $data->{hits}->{hits} } ],
- total => $data->{hits}->{total},
- took => $data->{took}
- }
- );
+ )->transform(
+ done => sub {
+ my $data = shift;
+ return {
+ data => [ map { $_->{_source} } @{ $data->{hits}->{hits} } ],
+ total => $data->{hits}->{total},
+ took => $data->{took}
+ };
}
);
- return $cv;
}
sub interesting_files {
@@ -360,17 +353,14 @@ sub favorites {
sub topuploaders {
my ( $self, $range ) = @_;
my $param = $range ? { range => $range } : ();
- my $data
- = $self->request( '/release/top_uploaders', undef, $param )->recv;
- return $data;
+ $self->request( '/release/top_uploaders', undef, $param );
}
sub no_latest {
my ( $self, @distributions ) = @_;
- my $cv = $self->cv;
# If there are no distributions return
- return {} unless (@distributions);
+ return Future->done( {} ) unless (@distributions);
@distributions = uniq @distributions;
$self->request(
@@ -387,13 +377,13 @@ sub no_latest {
},
fields => [qw(distribution status)]
}
- )->cb(
- sub {
- my $data = shift->recv;
+ )->transform(
+ done => sub {
+ my $data = shift;
my @latest
= map { $_->{fields}->{distribution} }
@{ $data->{hits}->{hits} };
- $cv->send(
+ return (
{
took => $data->{took},
no_latest => {
@@ -408,7 +398,6 @@ sub no_latest {
);
}
);
- return $cv;
}
__PACKAGE__->meta->make_immutable;
diff --git a/lib/MetaCPAN/Web/Role/ReleaseInfo.pm b/lib/MetaCPAN/Web/Role/ReleaseInfo.pm
index 94074b9623..50d99dcc2a 100644
--- a/lib/MetaCPAN/Web/Role/ReleaseInfo.pm
+++ b/lib/MetaCPAN/Web/Role/ReleaseInfo.pm
@@ -1,6 +1,7 @@
package MetaCPAN::Web::Role::ReleaseInfo;
use Moose::Role;
+use Future;
use Importer 'MetaCPAN::Web::Elasticsearch::Adapter' =>
qw/ single_valued_arrayref_to_scalar /;
@@ -28,7 +29,7 @@ sub add_favorites_data {
sub api_requests {
my ( $self, $c, $reqs, $data ) = @_;
- return {
+ my %reqs = (
author => $c->model('API::Author')->get( $data->{author} ),
favorites => $c->model('API::Favorite')->get(
@@ -46,7 +47,16 @@ sub api_requests {
distribution =>
$c->model('API::Release')->distribution( $data->{distribution} ),
%$reqs,
- };
+ );
+ my @names = keys %reqs;
+ my @futures = values %reqs;
+ return Future->needs_all(@futures)->transform(
+ done => sub {
+ my %results;
+ @results{@names} = @_;
+ return \%results;
+ }
+ );
}
# organize the api results into simple variables for the template
@@ -70,10 +80,4 @@ sub stash_api_results {
$c->stash( \%stash );
}
-# call recv() on all values in the provided hashref
-sub recv_all {
- my ( $self, $condvars ) = @_;
- return +{ map { $_ => $condvars->{$_}->recv } keys %$condvars };
-}
-
1;
diff --git a/lib/MetaCPAN/Web/Test.pm b/lib/MetaCPAN/Web/Test.pm
index 0d48514f31..fcf958d57a 100644
--- a/lib/MetaCPAN/Web/Test.pm
+++ b/lib/MetaCPAN/Web/Test.pm
@@ -15,6 +15,7 @@ use Test::More;
use Test::XPath;
use Try::Tiny;
use Encode;
+use Future;
use base 'Exporter';
our @EXPORT = qw(
GET
@@ -28,7 +29,7 @@ our @EXPORT = qw(
# TODO: use Sub:Override?
# save a copy in case we override
-my $orig_request = \&AnyEvent::Curl::Multi::request;
+my $orig_request = \&Net::Async::HTTP::do_request;
sub override_api_response {
require MetaCPAN::Web::Model::API;
@@ -37,17 +38,14 @@ sub override_api_response {
my $matches = {@_};
no warnings 'redefine';
- *AnyEvent::Curl::Multi::request = sub {
- if ( ( $matches->{if} ? $matches->{if}->(@_) : 1 )
- and my $res = $responder->(@_) )
+ *Net::Async::HTTP::do_request = sub {
+ my ( $self, %args ) = @_;
+ my $request = $args{request};
+ if ( ( $matches->{if} ? $matches->{if}->( $self, $request ) : 1 )
+ and my $res = $responder->( $self, $request ) )
{
$res = HTTP::Response->from_psgi($res) if ref $res eq 'ARRAY';
-
- # return an object with a ->cv that's ready so that the cb will fire
- my $ret = bless { cv => AE::cv() },
- 'AnyEvent::Curl::Multi::Handle';
- $ret->cv->send( $res, {} );
- return $ret;
+ return Future->wrap($res);
}
else {
goto &$orig_request;
diff --git a/lib/MetaCPAN/Web/User.pm b/lib/MetaCPAN/Web/User.pm
index e186873b82..793e535599 100644
--- a/lib/MetaCPAN/Web/User.pm
+++ b/lib/MetaCPAN/Web/User.pm
@@ -28,7 +28,7 @@ sub for_session {
sub from_session {
my ( $self, $c, $id ) = @_;
- my $user = $c->model('API::User')->get($id)->recv;
+ my $user = $c->model('API::User')->get($id)->get;
$self->obj( Hash::AsObject->new($user) ) if ($user);
return $user ? $self : undef;
}
@@ -36,7 +36,7 @@ sub from_session {
sub find_user {
my ( $self, $auth, $c ) = @_;
my $obj = Hash::AsObject->new(
- $c->model('API::User')->get( $auth->{token} )->recv );
+ $c->model('API::User')->get( $auth->{token} )->get );
$self->obj($obj);
return $self;
}
diff --git a/lib/MetaCPAN/Web/View/JSON.pm b/lib/MetaCPAN/Web/View/JSON.pm
index dea32a79ea..b33dfd3315 100644
--- a/lib/MetaCPAN/Web/View/JSON.pm
+++ b/lib/MetaCPAN/Web/View/JSON.pm
@@ -6,7 +6,7 @@ use Cpanel::JSON::XS ();
extends 'Catalyst::View::JSON';
sub encode_json {
- my ( $self, $c, $data ) = @_;
+ my ( $self, undef, $data ) = @_;
Cpanel::JSON::XS->new->utf8->encode($data);
}
diff --git a/lib/Plack/Middleware/Session/Cookie/MetaCPAN.pm b/lib/Plack/Middleware/Session/Cookie/MetaCPAN.pm
index 2c19779d1e..699dcc47c1 100644
--- a/lib/Plack/Middleware/Session/Cookie/MetaCPAN.pm
+++ b/lib/Plack/Middleware/Session/Cookie/MetaCPAN.pm
@@ -64,7 +64,7 @@ sub prepare_app {
sub save_state {
my $self = shift;
- my ( $id, $res, $env ) = @_;
+ my ( undef, undef, $env ) = @_;
return
if $env->{'psgix.session.options'}{no_store};
diff --git a/metacpan_web.conf b/metacpan_web.conf
index b5425a5ce5..a3dd0edd54 100644
--- a/metacpan_web.conf
+++ b/metacpan_web.conf
@@ -36,3 +36,19 @@ mark_unauthorized_releases = 0
public_key 6LeH2MsSAAAAANwz3AA73Gw5OjCVjT6I51Ev-ior
+
+ object_type = author
+ field_name = pauseid
+ metacpan_url = author
+
+
+
+ object_type = release
+ field_name = distribution
+ metacpan_url = release
+
+
+ status = latest
+
+
+
diff --git a/root/robots.txt b/root/robots.txt
index 28938f5fa3..61b426cc94 100644
--- a/root/robots.txt
+++ b/root/robots.txt
@@ -9,5 +9,5 @@ Disallow: /raw/
# Do not allow changing the default per page as is not useful
Disallow: /*?*size=*
-Sitemap: https://metacpan.org/static/sitemaps/authors.xml.gz
-Sitemap: https://metacpan.org/static/sitemaps/releases.xml.gz
+Sitemap: https://metacpan.org/sitemap-authors.xml.gz
+Sitemap: https://metacpan.org/sitemap-releases.xml.gz
diff --git a/t/encoding.t b/t/encoding.t
index e6760fe86c..9b94ae71a3 100644
--- a/t/encoding.t
+++ b/t/encoding.t
@@ -25,7 +25,7 @@ my $model
sub get_json {
$res_body = shift;
$content_type = shift if @_;
- return $model->source(qw( who cares ))->recv;
+ return $model->source(qw( who cares ))->get;
}
sub get_raw {
diff --git a/t/metacpan/sitemap.t b/t/metacpan/sitemap.t
deleted file mode 100644
index 00f6b04ee5..0000000000
--- a/t/metacpan/sitemap.t
+++ /dev/null
@@ -1,82 +0,0 @@
-use strict;
-use warnings;
-
-use File::Temp qw/ tempdir /;
-use MetaCPAN::Sitemap;
-use Test::More;
-use Try::Tiny;
-use XML::Simple;
-
-# Test each of the three things that the production script is going to do,
-# but limit the searches to a single chunk of 250 results to speed things
-# along.
-
-my @tests = (
- {
- inputs => {
- object_type => 'author',
- field_name => 'pauseid',
- xml_file => '',
- cpan_directory => 'author',
- },
- pattern => qr{https:.+/author/[a-z0-9A-Z-]+},
- },
- {
- inputs => {
- object_type => 'release',
- field_name => 'distribution',
- xml_file => '',
- cpan_directory => 'release',
- filter => { status => 'latest' },
- },
- pattern => qr{https?:.+/release/[a-z0-9A-Z-]+},
- }
-);
-
-my $temp_dir = tempdir( CLEANUP => 1 );
-
-foreach my $test (@tests) {
-
- # Generate the XML file into a file in a temporary directory, then
- # check that the file exists, is valid XML, and has the right number
- # of URLs.
-
- my $args = $test->{inputs};
- $args->{size} = 250;
- $args->{xml_file} = File::Spec->catfile( $temp_dir,
- "$test->{inputs}{object_type}.xml.gz" );
- my $sitemap = MetaCPAN::Sitemap->new($args);
- $sitemap->process();
-
- ok( -e $args->{xml_file},
- "XML output file for $args->{object_type} exists" );
-
- open( my $xml_fh, '<:gzip', $args->{xml_file} );
-
- my $xml = XMLin($xml_fh);
- ok( defined $xml, "XML for $args->{object_type} checks out" );
-
- ok( @{ $xml->{url} }, 'We have some URLs to look at' );
- is(
- $sitemap->{size},
- scalar @{ $xml->{url} },
- "Number of URLs is correct"
- );
-
- # Check that each of the urls has the right pattern.
-
- note 'Checking urls';
- my $url_tests;
- foreach my $url ( @{ $xml->{url} } ) {
-
- # Test that the url matches
- # but only print a TAP line for the first test or if there's a failure.
- # ~30,000 tests is a lot of output to sift through.
- if ( !$url_tests++ || $url !~ $test->{pattern} ) {
- like( $url, $test->{pattern}, 'URL matches' );
- }
- }
- ok( $url_tests, "Tested $url_tests urls" );
-}
-
-done_testing();
diff --git a/t/model/release.t b/t/model/release.t
index c1c0014ed7..f24b7161a0 100644
--- a/t/model/release.t
+++ b/t/model/release.t
@@ -13,7 +13,7 @@ sub search_release {
return
map { @{ $_->{hits}{hits} } }
- MetaCPAN::Web->model('API::Release')->$method(@args)->recv;
+ MetaCPAN::Web->model('API::Release')->$method(@args)->get;
}
my ( $true, $false ) = @{ decode_json('[true, false]') };