From 8eb93223b25bb6f967cb0376003aadad4f75958d Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Sat, 11 Dec 2021 09:31:08 +0000 Subject: [PATCH] Generate cpanfile with feature information Loading feature information from CPAN::Meta is currently not supported by Module::CPANFile, so do this by hand for now. Fixes cpanm not installing dependencies for enabled features (as it prefers reading the cpanfile over MYMETA.*). --- Makefile.PL | 3 +- cpanfile | 184 ++++++++++++++++++++++++++++++++++++++++++++---- gen-cpanfile.pl | 78 ++++++++------------ 3 files changed, 202 insertions(+), 63 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index abe59e105e..23a2de260d 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -386,9 +386,8 @@ WriteMakefile( sub MY::postamble { return <<"MAKE"; -GEN_CPANFILE_ARGS = -D better_xff -D mysql -D jsonrpc -D xmlrpc cpanfile: MYMETA.json -\t\$(PERLRUN) gen-cpanfile.pl \$(GEN_CPANFILE_ARGS) +\tPERL_HASH_SEED=0 \$(PERLRUN) gen-cpanfile.pl META.json: Makefile.PL \tmake distmeta 2>&1 /dev/null; mv */META.json . diff --git a/cpanfile b/cpanfile index f2e8429cc2..cbada59644 100644 --- a/cpanfile +++ b/cpanfile @@ -1,5 +1,4 @@ requires 'Algorithm::BloomFilter', '0.02'; -requires 'Bytes::Random::Secure'; requires 'CGI', '4.31'; requires 'CGI::Compile'; requires 'CGI::Emulate::PSGI'; @@ -9,9 +8,6 @@ requires 'Class::XSAccessor', '1.18'; requires 'Crypt::CBC'; requires 'Crypt::DES'; requires 'Crypt::DES_EDE3'; -requires 'Crypt::OpenPGP', '1.12'; -requires 'Crypt::SMIME'; -requires 'DBD::mysql', '4.037'; requires 'DBI', '1.614'; requires 'DBIx::Class'; requires 'DBIx::Class::Helpers', '== 2.034002'; @@ -20,7 +16,6 @@ requires 'Daemon::Generic'; requires 'Date::Format', '2.23'; requires 'Date::Parse', '2.31'; requires 'DateTime', '0.75'; -requires 'DateTime::Format::MySQL', '0.06'; requires 'DateTime::TimeZone', '2.11'; requires 'Devel::NYTProf', '6.04'; requires 'Digest::SHA', '5.47'; @@ -38,7 +33,6 @@ requires 'IO::Compress::Gzip'; requires 'IO::Scalar'; requires 'IPC::System::Simple'; requires 'JSON::MaybeXS', '1.003008'; -requires 'JSON::RPC', '== 1.01'; requires 'JSON::Validator', '3.05'; requires 'JSON::XS', '2.0'; requires 'LWP::Protocol::https', '6.07'; @@ -53,7 +47,6 @@ requires 'Module::Runtime', '0.014'; requires 'Mojo::JWT', '0.07'; requires 'MojoX::Log::Log4perl', '0.04'; requires 'Mojolicious', '8.42'; -requires 'Mojolicious::Plugin::ForwardedFor'; requires 'Moo', '2.002004'; requires 'MooX::StrictConstructor', '0.008'; requires 'Mozilla::CA', '20160104'; @@ -61,19 +54,13 @@ requires 'Net::DNS'; requires 'Package::Stash', '0.37'; requires 'Parse::CPAN::Meta', '1.44'; requires 'PerlX::Maybe'; -requires 'Pod::Coverage::TrustPod'; requires 'Regexp::Common'; requires 'Role::Tiny', '2.000003'; -requires 'SOAP::Lite', '0.712'; requires 'Scope::Guard', '0.21'; requires 'Sereal', '4.004'; requires 'Sub::Quote', '2.005000'; requires 'Sys::Syslog'; requires 'Template', '2.24'; -requires 'Test::CPAN::Meta'; -requires 'Test::Pod'; -requires 'Test::Pod::Coverage'; -requires 'Test::Taint', '1.06'; requires 'Text::CSV_XS', '1.26'; requires 'Text::Diff'; requires 'Throwable', '0.200013'; @@ -81,7 +68,6 @@ requires 'Tie::IxHash'; requires 'Type::Tiny', '1.004004'; requires 'URI', '1.55'; requires 'URI::Escape::XS', '0.14'; -requires 'XMLRPC::Lite', '0.712'; requires 'perl', '5.010001'; requires 'version', '0.87'; recommends 'Safe', '2.30'; @@ -109,3 +95,173 @@ on test => sub { requires 'Test::Selenium::Firefox'; requires 'Test::WWW::Selenium'; }; +feature 'html_desc', 'More HTML in Product/Group Descriptions' => sub { + requires 'HTML::Parser', '3.67'; + requires 'HTML::Scrubber'; +}; + +feature 'jobqueue', 'Mail Queueing' => sub { + requires 'Daemon::Generic'; + requires 'TheSchwartz', '1.10'; +}; + +feature 'detect_charset', 'Automatic charset detection for text attachments' => sub { + requires 'Encode', '2.21'; + requires 'Encode::Detect'; +}; + +feature 's3', 'Amazon S3 Attachment Storage' => sub { + requires 'Class::Accessor::Fast'; + requires 'URI::Escape'; + requires 'XML::Simple'; +}; + +feature 'datadog', 'Data Dog support' => sub { + requires 'DataDog::DogStatsd', '0.05'; +}; + +feature 'oracle', 'Oracle database support' => sub { + requires 'DBD::Oracle', '1.19'; +}; + +feature 'typesniffer', 'Sniff MIME type of attachments' => sub { + requires 'File::MimeInfo::Magic'; + requires 'IO::Scalar'; +}; + +feature 'extension_push_optional', undef => sub { + requires 'XML::Simple'; +}; + +feature 'markdown', 'Markdown syntax support for comments' => sub { + requires 'Text::MultiMarkdown', '1.000034'; + requires 'Unicode::GCString'; +}; + +feature 'sqlite', 'SQLite database support' => sub { + requires 'DBD::SQLite', '1.29'; + requires 'DateTime::Format::SQLite', '0.11'; +}; + +feature 'linux_pid', 'Linux::PID' => sub { + requires 'Linux::Pid'; +}; + +feature 'jsonrpc', 'JSON-RPC Interface' => sub { + requires 'JSON::RPC', '== 1.01'; + requires 'Test::Taint', '1.06'; +}; + +feature 'oauth2_server', 'OAuth2 Server support' => sub { + requires 'Mojolicious::Plugin::OAuth2::Server', '0.44'; +}; + +feature 'pg', 'Postgres database support' => sub { + requires 'DBD::Pg', 'v2.19.3'; +}; + +feature 'linux_pdeath', 'Linux::Pdeathsig for a good parent/child relationships' => sub { + requires 'Linux::Pdeathsig'; +}; + +feature 'inbound_email', 'Inbound Email' => sub { + requires 'Email::MIME::Attachment::Stripper'; + requires 'Email::Reply'; +}; + +feature 'rest', 'REST Interface' => sub { + requires 'JSON::RPC', '== 1.01'; + requires 'Test::Taint', '1.06'; +}; + +feature 'better_xff', 'Improved behavior of MOJO_REVERSE_PROXY' => sub { + requires 'Mojolicious::Plugin::ForwardedFor'; +}; + +feature 'updates', 'Automatic Update Notifications' => sub { + requires 'XML::Twig'; +}; + +feature 'new_charts', 'New Charts' => sub { + requires 'Chart::Lines', 'v2.4.10'; + requires 'GD', '1.20'; +}; + +feature 'mysql', 'MySQL database support' => sub { + requires 'DBD::mysql', '4.037'; + requires 'DateTime::Format::MySQL', '0.06'; +}; + +feature 'argon2', 'Support hashing passwords with Argon2' => sub { + requires 'Crypt::Argon2', '0.004'; +}; + +feature 'mfa', 'Multi-Factor Authentication' => sub { + requires 'Auth::GoogleAuth', '1.01'; + requires 'GD::Barcode::QRcode'; +}; + +feature 'memcached', 'Memcached Support' => sub { + requires 'Cache::Memcached::Fast', '0.17'; +}; + +feature 'auth_ldap', 'LDAP Authentication' => sub { + requires 'Net::LDAP'; +}; + +feature 'old_charts', 'Old Charts' => sub { + requires 'Chart::Lines', 'v2.4.10'; + requires 'GD', '1.20'; +}; + +feature 'documentation', 'Documentation' => sub { + requires 'File::Copy::Recursive'; + requires 'File::Which'; +}; + +feature 'auth_radius', 'RADIUS Authentication' => sub { + requires 'Authen::Radius'; +}; + +feature 'moving', 'Move Bugs Between Installations' => sub { + requires 'MIME::Parser', '5.406'; + requires 'XML::Twig'; +}; + +feature 'sentry', 'Sentry Support' => sub { + requires 'Log::Log4perl::Appender::Raven', '0.006'; +}; + +feature 'linux_smaps', 'Linux::Smaps::Tiny for limiting memory usage' => sub { + requires 'BSD::Resource'; + requires 'Linux::Smaps::Tiny'; +}; + +feature 'chart_clicker', 'Support nice-looking charts' => sub { + requires 'Chart::Clicker'; +}; + +feature 'patch_viewer', 'Patch Viewer' => sub { + requires 'PatchReader', 'v0.9.6'; +}; + +feature 'graphical_reports', 'Graphical Reports' => sub { + requires 'GD', '1.20'; + requires 'GD::Graph'; + requires 'GD::Text'; + requires 'Template::Plugin::GD::Image'; +}; + +feature 'smtp_auth', 'SMTP Authentication' => sub { + requires 'Authen::SASL'; +}; + +feature 'alien_cmark', 'Support GitHub-flavored markdown' => sub { + requires 'Alien::libcmark_gfm', '3'; +}; + +feature 'xmlrpc', 'XML-RPC Interface' => sub { + requires 'SOAP::Lite', '0.712'; + requires 'Test::Taint', '1.06'; + requires 'XMLRPC::Lite', '0.712'; +}; diff --git a/gen-cpanfile.pl b/gen-cpanfile.pl index 664e0afd2c..8d8390137d 100755 --- a/gen-cpanfile.pl +++ b/gen-cpanfile.pl @@ -6,8 +6,6 @@ # This Source Code Form is "Incompatible With Secondary Licenses", as # defined by the Mozilla Public License, v. 2.0. -# This file has detailed POD docs, do "perldoc checksetup.pl" to see them. - ###################################################################### # Initialization ###################################################################### @@ -18,51 +16,37 @@ use lib qw(. lib local/lib/perl5); -use Getopt::Long qw(:config gnu_getopt); - -if (-f "MYMETA.json") { - eval { - require CPAN::Meta; - require Module::CPANfile; - - my (@with_feature, @without_feature); - my $with_all_features = 0; - GetOptions( - 'with-all-features|A!' => \$with_all_features, - 'with-feature|D=s@' => \@with_feature, - 'without-feature|U=s@' => \@without_feature - ); - - - my $meta = CPAN::Meta->load_file("MYMETA.json"); - - my @phases = qw(configure build test develop runtime); - my @types = qw(requires recommends suggests conflicts); - - my %features; - if ($with_all_features) { - $features{$_->identifier} = 1 foreach ($meta->features); - } - $features{$_} = 1 foreach @with_feature; - $features{$_} = 0 foreach @without_feature; - my @features = grep { $features{$_} } keys %features; - - my $prereqs = $meta->effective_prereqs(\@features)->as_string_hash; - my $filtered = {}; - - while (my ($phase, $types) = each %$prereqs) { - while (my ($type, $reqs) = each %$types) { - $filtered->{$phase}{$type} = $reqs; +use CPAN::Meta; +use Module::CPANfile; + +my $meta = CPAN::Meta->load_file('MYMETA.json'); +my $file = Module::CPANfile->from_prereqs($meta->prereqs); + +# Manually extract and populate feature information +# https://github.com/miyagawa/cpanfile/issues/52 + +for my $feature ($meta->features) { + $file->{_prereqs}->add_feature($feature->identifier, $feature->description); + my $prereqs = []; + while (my ($phase, $types) = each %{$feature->{prereqs}->{prereqs}}) { + while (my ($type, $requirements) = each %$types) { + my $req_spec = $requirements->as_string_hash; + while (my ($module, $version) = each %{$req_spec}) { + push @{$prereqs}, + Module::CPANfile::Prereq->new( + feature => $feature->identifier, + phase => $phase, + type => $type, + module => $module, + requirement => Module::CPANfile::Requirement->new( + name => $module, + version => $version, + ), + ); } } - - my $cpanfile = Module::CPANfile->from_prereqs($filtered); - open my $cpanfile_fh, '>', 'cpanfile' or die "cannot write to cpanfile: $!"; - print $cpanfile_fh $cpanfile->to_string(); - close $cpanfile_fh; - }; - die "Unable generate cpanfile: $@\n" if $@; -} -else { - die "MYMETA.yml is missing, cannot generate cpanfile\n"; + } + $file->{_prereqs}->{prereqs}{$feature->identifier} = $prereqs; } + +$file->save('cpanfile');