Skip to content

Commit 56ad29d

Browse files
committed
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.*).
1 parent db825d2 commit 56ad29d

File tree

3 files changed

+202
-66
lines changed

3 files changed

+202
-66
lines changed

Makefile.PL

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,9 +386,8 @@ WriteMakefile(
386386

387387
sub MY::postamble {
388388
return <<"MAKE";
389-
GEN_CPANFILE_ARGS = -D better_xff -D mysql -D jsonrpc -D xmlrpc
390389
cpanfile: MYMETA.json
391-
\t\$(PERLRUN) gen-cpanfile.pl \$(GEN_CPANFILE_ARGS)
390+
\t\$(PERLRUN) gen-cpanfile.pl
392391
393392
META.json: Makefile.PL
394393
\tmake distmeta 2>&1 /dev/null; mv */META.json .

cpanfile

Lines changed: 170 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
requires 'Algorithm::BloomFilter', '0.02';
2-
requires 'Bytes::Random::Secure';
32
requires 'CGI', '4.31';
43
requires 'CGI::Compile';
54
requires 'CGI::Emulate::PSGI';
@@ -9,9 +8,6 @@ requires 'Class::XSAccessor', '1.18';
98
requires 'Crypt::CBC';
109
requires 'Crypt::DES';
1110
requires 'Crypt::DES_EDE3';
12-
requires 'Crypt::OpenPGP', '1.12';
13-
requires 'Crypt::SMIME';
14-
requires 'DBD::mysql', '4.037';
1511
requires 'DBI', '1.614';
1612
requires 'DBIx::Class';
1713
requires 'DBIx::Class::Helpers', '== 2.034002';
@@ -20,7 +16,6 @@ requires 'Daemon::Generic';
2016
requires 'Date::Format', '2.23';
2117
requires 'Date::Parse', '2.31';
2218
requires 'DateTime', '0.75';
23-
requires 'DateTime::Format::MySQL', '0.06';
2419
requires 'DateTime::TimeZone', '2.11';
2520
requires 'Devel::NYTProf', '6.04';
2621
requires 'Digest::SHA', '5.47';
@@ -38,7 +33,6 @@ requires 'IO::Compress::Gzip';
3833
requires 'IO::Scalar';
3934
requires 'IPC::System::Simple';
4035
requires 'JSON::MaybeXS', '1.003008';
41-
requires 'JSON::RPC', '== 1.01';
4236
requires 'JSON::Validator', '3.05';
4337
requires 'JSON::XS', '2.0';
4438
requires 'LWP::Protocol::https', '6.07';
@@ -53,35 +47,24 @@ requires 'Module::Runtime', '0.014';
5347
requires 'Mojo::JWT', '0.07';
5448
requires 'MojoX::Log::Log4perl', '0.04';
5549
requires 'Mojolicious', '8.42';
56-
requires 'Mojolicious::Plugin::ForwardedFor';
5750
requires 'Moo', '2.002004';
5851
requires 'MooX::StrictConstructor', '0.008';
5952
requires 'Mozilla::CA', '20160104';
6053
requires 'Net::DNS';
6154
requires 'Package::Stash', '0.37';
6255
requires 'Parse::CPAN::Meta', '1.44';
6356
requires 'PerlX::Maybe';
64-
requires 'Pod::Coverage::TrustPod';
6557
requires 'Regexp::Common';
6658
requires 'Role::Tiny', '2.000003';
67-
requires 'SOAP::Lite', '0.712';
6859
requires 'Scope::Guard', '0.21';
6960
requires 'Sereal', '4.004';
7061
requires 'Sub::Quote', '2.005000';
71-
requires 'Sys::Syslog';
7262
requires 'Template', '2.24';
73-
requires 'Test::CPAN::Meta';
74-
requires 'Test::Pod';
75-
requires 'Test::Pod::Coverage';
76-
requires 'Test::Taint', '1.06';
7763
requires 'Text::CSV_XS', '1.26';
78-
requires 'Text::Diff';
7964
requires 'Throwable', '0.200013';
80-
requires 'Tie::IxHash';
8165
requires 'Type::Tiny', '1.004004';
8266
requires 'URI', '1.55';
8367
requires 'URI::Escape::XS', '0.14';
84-
requires 'XMLRPC::Lite', '0.712';
8568
requires 'perl', '5.010001';
8669
requires 'version', '0.87';
8770
recommends 'Safe', '2.30';
@@ -109,3 +92,173 @@ on test => sub {
10992
requires 'Test::Selenium::Firefox';
11093
requires 'Test::WWW::Selenium';
11194
};
95+
feature 'inbound_email', 'Inbound Email' => sub {
96+
requires 'Email::MIME::Attachment::Stripper';
97+
requires 'Email::Reply';
98+
};
99+
100+
feature 'jobqueue', 'Mail Queueing' => sub {
101+
requires 'Daemon::Generic';
102+
requires 'TheSchwartz', '1.10';
103+
};
104+
105+
feature 'pg', 'Postgres database support' => sub {
106+
requires 'DBD::Pg', 'v2.19.3';
107+
};
108+
109+
feature 'auth_ldap', 'LDAP Authentication' => sub {
110+
requires 'Net::LDAP';
111+
};
112+
113+
feature 'oauth2_server', 'OAuth2 Server support' => sub {
114+
requires 'Mojolicious::Plugin::OAuth2::Server', '0.44';
115+
};
116+
117+
feature 'sentry', 'Sentry Support' => sub {
118+
requires 'Log::Log4perl::Appender::Raven', '0.006';
119+
};
120+
121+
feature 'better_xff', 'Improved behavior of MOJO_REVERSE_PROXY' => sub {
122+
requires 'Mojolicious::Plugin::ForwardedFor';
123+
};
124+
125+
feature 's3', 'Amazon S3 Attachment Storage' => sub {
126+
requires 'Class::Accessor::Fast';
127+
requires 'URI::Escape';
128+
requires 'XML::Simple';
129+
};
130+
131+
feature 'linux_pdeath', 'Linux::Pdeathsig for a good parent/child relationships' => sub {
132+
requires 'Linux::Pdeathsig';
133+
};
134+
135+
feature 'html_desc', 'More HTML in Product/Group Descriptions' => sub {
136+
requires 'HTML::Parser', '3.67';
137+
requires 'HTML::Scrubber';
138+
};
139+
140+
feature 'xmlrpc', 'XML-RPC Interface' => sub {
141+
requires 'SOAP::Lite', '0.712';
142+
requires 'Test::Taint', '1.06';
143+
requires 'XMLRPC::Lite', '0.712';
144+
};
145+
146+
feature 'new_charts', 'New Charts' => sub {
147+
requires 'Chart::Lines', 'v2.4.10';
148+
requires 'GD', '1.20';
149+
};
150+
151+
feature 'old_charts', 'Old Charts' => sub {
152+
requires 'Chart::Lines', 'v2.4.10';
153+
requires 'GD', '1.20';
154+
};
155+
156+
feature 'alien_cmark', 'Support GitHub-flavored markdown' => sub {
157+
requires 'Alien::libcmark_gfm', '3';
158+
};
159+
160+
feature 'jsonrpc', 'JSON-RPC Interface' => sub {
161+
requires 'JSON::RPC', '== 1.01';
162+
requires 'Test::Taint', '1.06';
163+
};
164+
165+
feature 'sqlite', 'SQLite database support' => sub {
166+
requires 'DBD::SQLite', '1.29';
167+
requires 'DateTime::Format::SQLite', '0.11';
168+
};
169+
170+
feature 'rest', 'REST Interface' => sub {
171+
requires 'JSON::RPC', '== 1.01';
172+
requires 'Test::Taint', '1.06';
173+
};
174+
175+
feature 'smtp_auth', 'SMTP Authentication' => sub {
176+
requires 'Authen::SASL';
177+
};
178+
179+
feature 'memcached', 'Memcached Support' => sub {
180+
requires 'Cache::Memcached::Fast', '0.17';
181+
};
182+
183+
feature 'linux_pid', 'Linux::PID' => sub {
184+
requires 'Linux::Pid';
185+
};
186+
187+
feature 'datadog', 'Data Dog support' => sub {
188+
requires 'DataDog::DogStatsd', '0.05';
189+
};
190+
191+
feature 'auth_radius', 'RADIUS Authentication' => sub {
192+
requires 'Authen::Radius';
193+
};
194+
195+
feature 'chart_clicker', 'Support nice-looking charts' => sub {
196+
requires 'Chart::Clicker';
197+
};
198+
199+
feature 'mfa', 'Multi-Factor Authentication' => sub {
200+
requires 'Auth::GoogleAuth', '1.01';
201+
requires 'GD::Barcode::QRcode';
202+
};
203+
204+
feature 'markdown', 'Markdown syntax support for comments' => sub {
205+
requires 'Text::MultiMarkdown', '1.000034';
206+
requires 'Unicode::GCString';
207+
};
208+
209+
feature 'patch_viewer', 'Patch Viewer' => sub {
210+
requires 'PatchReader', 'v0.9.6';
211+
};
212+
213+
feature 'typesniffer', 'Sniff MIME type of attachments' => sub {
214+
requires 'File::MimeInfo::Magic';
215+
requires 'IO::Scalar';
216+
};
217+
218+
feature 'detect_charset', 'Automatic charset detection for text attachments' => sub {
219+
requires 'Encode', '2.21';
220+
requires 'Encode::Detect';
221+
};
222+
223+
feature 'mysql', 'MySQL database support' => sub {
224+
requires 'DBD::mysql', '4.037';
225+
requires 'DateTime::Format::MySQL', '0.06';
226+
};
227+
228+
feature 'linux_smaps', 'Linux::Smaps::Tiny for limiting memory usage' => sub {
229+
requires 'BSD::Resource';
230+
requires 'Linux::Smaps::Tiny';
231+
};
232+
233+
feature 'graphical_reports', 'Graphical Reports' => sub {
234+
requires 'GD', '1.20';
235+
requires 'GD::Graph';
236+
requires 'GD::Text';
237+
requires 'Template::Plugin::GD::Image';
238+
};
239+
240+
feature 'documentation', 'Documentation' => sub {
241+
requires 'File::Copy::Recursive';
242+
requires 'File::Which';
243+
};
244+
245+
feature 'argon2', 'Support hashing passwords with Argon2' => sub {
246+
requires 'Crypt::Argon2', '0.004';
247+
};
248+
249+
feature 'oracle', 'Oracle database support' => sub {
250+
requires 'DBD::Oracle', '1.19';
251+
};
252+
253+
feature 'moving', 'Move Bugs Between Installations' => sub {
254+
requires 'MIME::Parser', '5.406';
255+
requires 'XML::Twig';
256+
};
257+
258+
feature 'extension_push_optional', undef => sub {
259+
requires 'XML::Simple';
260+
};
261+
262+
feature 'updates', 'Automatic Update Notifications' => sub {
263+
requires 'XML::Twig';
264+
};

gen-cpanfile.pl

Lines changed: 31 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
# This Source Code Form is "Incompatible With Secondary Licenses", as
77
# defined by the Mozilla Public License, v. 2.0.
88

9-
# This file has detailed POD docs, do "perldoc checksetup.pl" to see them.
10-
119
######################################################################
1210
# Initialization
1311
######################################################################
@@ -18,51 +16,37 @@
1816

1917
use lib qw(. lib local/lib/perl5);
2018

21-
use Getopt::Long qw(:config gnu_getopt);
22-
23-
if (-f "MYMETA.json") {
24-
eval {
25-
require CPAN::Meta;
26-
require Module::CPANfile;
27-
28-
my (@with_feature, @without_feature);
29-
my $with_all_features = 0;
30-
GetOptions(
31-
'with-all-features|A!' => \$with_all_features,
32-
'with-feature|D=s@' => \@with_feature,
33-
'without-feature|U=s@' => \@without_feature
34-
);
35-
36-
37-
my $meta = CPAN::Meta->load_file("MYMETA.json");
38-
39-
my @phases = qw(configure build test develop runtime);
40-
my @types = qw(requires recommends suggests conflicts);
41-
42-
my %features;
43-
if ($with_all_features) {
44-
$features{$_->identifier} = 1 foreach ($meta->features);
45-
}
46-
$features{$_} = 1 foreach @with_feature;
47-
$features{$_} = 0 foreach @without_feature;
48-
my @features = grep { $features{$_} } keys %features;
49-
50-
my $prereqs = $meta->effective_prereqs(\@features)->as_string_hash;
51-
my $filtered = {};
52-
53-
while (my ($phase, $types) = each %$prereqs) {
54-
while (my ($type, $reqs) = each %$types) {
55-
$filtered->{$phase}{$type} = $reqs;
19+
use CPAN::Meta;
20+
use Module::CPANfile;
21+
22+
my $meta = CPAN::Meta->load_file('MYMETA.json');
23+
my $file = Module::CPANfile->from_prereqs($meta->prereqs);
24+
25+
# Manually extract and populate feature information
26+
# https://github.com/miyagawa/cpanfile/issues/52
27+
28+
for my $feature ($meta->features) {
29+
$file->{_prereqs}->add_feature($feature->identifier, $feature->description);
30+
my $prereqs = [];
31+
while (my ($phase, $types) = each %{$feature->{prereqs}->{prereqs}}) {
32+
while (my ($type, $requirements) = each %$types) {
33+
my $req_spec = $requirements->as_string_hash;
34+
while (my ($module, $version) = each %{$req_spec}) {
35+
push @{$prereqs},
36+
Module::CPANfile::Prereq->new(
37+
feature => $feature->identifier,
38+
phase => $phase,
39+
type => $type,
40+
module => $module,
41+
requirement => Module::CPANfile::Requirement->new(
42+
name => $module,
43+
version => $version,
44+
),
45+
);
5646
}
5747
}
58-
59-
my $cpanfile = Module::CPANfile->from_prereqs($filtered);
60-
open my $cpanfile_fh, '>', 'cpanfile' or die "cannot write to cpanfile: $!";
61-
print $cpanfile_fh $cpanfile->to_string();
62-
close $cpanfile_fh;
63-
};
64-
die "Unable generate cpanfile: $@\n" if $@;
65-
}
66-
else {
67-
die "MYMETA.yml is missing, cannot generate cpanfile\n";
48+
}
49+
$file->{_prereqs}->{prereqs}{$feature->identifier} = $prereqs;
6850
}
51+
52+
$file->save('cpanfile');

0 commit comments

Comments
 (0)