summaryrefslogtreecommitdiffstats
path: root/Bugzilla
diff options
context:
space:
mode:
authorDylan William Hardison <dylan@hardison.net>2017-03-27 15:56:14 +0200
committerDylan William Hardison <dylan@hardison.net>2017-03-27 17:18:19 +0200
commit15daaf123635c1e734dfe6e3aed60f52df0364ce (patch)
treec4823e177859f5b69a68017635bbd29491ceec90 /Bugzilla
parent08c0187b591bb1bb4248382a8106a450c9b359e3 (diff)
downloadbugzilla-15daaf123635c1e734dfe6e3aed60f52df0364ce.tar.gz
bugzilla-15daaf123635c1e734dfe6e3aed60f52df0364ce.tar.xz
Bug 1350466 - Uplift bug 1342832 to bmo for performance and other reasons
Diffstat (limited to 'Bugzilla')
-rw-r--r--Bugzilla/CPAN.pm142
-rw-r--r--Bugzilla/Constants.pm13
-rw-r--r--Bugzilla/Install/Requirements.pm27
-rw-r--r--Bugzilla/Install/Util.pm2
4 files changed, 144 insertions, 40 deletions
diff --git a/Bugzilla/CPAN.pm b/Bugzilla/CPAN.pm
new file mode 100644
index 000000000..f044e45bc
--- /dev/null
+++ b/Bugzilla/CPAN.pm
@@ -0,0 +1,142 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::CPAN;
+
+use 5.10.1;
+use strict;
+use warnings;
+
+use Bugzilla::Constants qw(bz_locations);
+use Bugzilla::Install::Requirements qw(check_cpan_feature);
+
+BEGIN {
+ my $json_xs_ok = eval {
+ require JSON::XS;
+ require JSON;
+ JSON->VERSION("2.5");
+ 1;
+ };
+ if ($json_xs_ok) {
+ $ENV{PERL_JSON_BACKEND} = 'JSON::XS';
+ }
+}
+
+use constant _CAN_HAS_FEATURE => eval {
+ require CPAN::Meta::Prereqs;
+ require CPAN::Meta::Requirements;
+ require Module::Metadata;
+ require Module::Runtime;
+ CPAN::Meta::Prereqs->VERSION('2.132830');
+ CPAN::Meta::Requirements->VERSION('2.121');
+ Module::Metadata->VERSION('1.000019');
+ 1;
+};
+
+my (%FEATURE, %FEATURE_LOADED);
+
+sub cpan_meta {
+ my ($class) = @_;
+ my $dir = bz_locations()->{libpath};
+ my $file = File::Spec->catfile($dir, 'MYMETA.json');
+ state $CPAN_META;
+
+ return $CPAN_META if $CPAN_META;
+
+ if (-f $file) {
+ open my $meta_fh, '<', $file or die "unable to open $file: $!";
+ my $str = do { local $/ = undef; scalar <$meta_fh> };
+ # detaint
+ $str =~ /^(.+)$/s; $str = $1;
+ close $meta_fh;
+
+ return $CPAN_META = CPAN::Meta->load_json_string($str);
+ }
+ else {
+ require Bugzilla::Error;
+ Bugzilla::Error::ThrowCodeError('cpan_meta_missing');
+ }
+}
+
+sub cpan_requirements {
+ my ($class, $prereqs) = @_;
+ if ($prereqs->can('merged_requirements')) {
+ return $prereqs->merged_requirements( [ 'configure', 'runtime' ], ['requires'] );
+ }
+ else {
+ my $req = CPAN::Meta::Requirements->new;
+ $req->add_requirements( $prereqs->requirements_for('configure', 'requires') );
+ $req->add_requirements( $prereqs->requirements_for('runtime', 'requires') );
+ return $req;
+ }
+}
+
+sub has_feature {
+ my ($class, $feature_name) = @_;
+
+ return 0 unless _CAN_HAS_FEATURE;
+ return $FEATURE{$feature_name} if exists $FEATURE{ $feature_name };
+
+ my $meta = $class->cpan_meta;
+ my $feature = eval { $meta->feature($feature_name) }
+ or ThrowCodeError('invalid_feature', { feature => $feature_name });
+
+ return $FEATURE{$feature_name} = check_cpan_feature($feature)->{ok};
+}
+
+
+# Bugzilla expects this will also load all the modules.. so we have to do that.
+# Later we should put a deprecation warning here, and favor calling has_feature().
+sub feature {
+ my ($class, $feature_name) = @_;
+ return 0 unless _CAN_HAS_FEATURE;
+ return 1 if $FEATURE_LOADED{$feature_name};
+ return 0 unless $class->has_feature($feature_name);
+
+ my $meta = $class->cpan_meta;
+ my $feature = $meta->feature($feature_name);
+ my @modules = $feature->prereqs->merged_requirements->required_modules;
+ Module::Runtime::require_module($_) foreach @modules;
+ return $FEATURE_LOADED{$feature_name} = 1;
+}
+
+1;
+
+__END__
+
+
+=head1 NAME
+
+Bugzilla::CPAN - Methods relating to Bugzilla's CPAN metadata (including features)
+
+=head1 SYNOPSIS
+
+ use Bugzilla;
+ Bugzilla->cpan_meta;
+ Bugzilla->feature('psgi');
+ Bugzilla->has_feature('psgi');
+
+=head1 DESCRIPTION
+
+You most likely never need to use this module directly, as the Bugzilla factory class inherits all of these class methods.
+It exists so that cpan metadata can be read in before the rest of Bugzilla.pm is loaded in checksetup.pl
+
+=head1 CLASS METHODS
+
+=head2 C<feature>
+
+Wrapper around C<has_feature()> that also loads all of required modules into the runtime.
+
+=head2 C<has_feature>
+
+Consults F<MYMETA.yml> for optional Bugzilla features and returns true if all the requirements
+are installed.
+
+=head2 C<cpan_meta>
+
+Returns a L<CPAN::Meta> from the contents of MYMETA.json in the bugzilla directory.
+
diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm
index 94d60999b..852c9c362 100644
--- a/Bugzilla/Constants.pm
+++ b/Bugzilla/Constants.pm
@@ -26,8 +26,6 @@ use Memoize;
bz_locations
- CAN_HAS_FEATURE
-
CONCATENATE_ASSETS
IS_NULL
@@ -221,17 +219,6 @@ use constant REST_DOC => "http://www.bugzilla.org/docs/tip/en/html/api/";
use constant REMOTE_FILE => 'http://updates.bugzilla.org/bugzilla-update.xml';
use constant LOCAL_FILE => 'bugzilla-update.xml'; # Relative to datadir.
-use constant CAN_HAS_FEATURE => eval {
- require CPAN::Meta::Prereqs;
- require CPAN::Meta::Requirements;
- require Module::Metadata;
- require Module::Runtime;
- CPAN::Meta::Prereqs->VERSION('2.132830');
- CPAN::Meta::Requirements->VERSION('2.121');
- Module::Metadata->VERSION('1.000019');
- 1;
-};
-
# When true CSS and JavaScript assets will be concatanted and minified at
# run-time, to reduce the number of requests required to render a page.
# Setting this to a false value can help debugging.
diff --git a/Bugzilla/Install/Requirements.pm b/Bugzilla/Install/Requirements.pm
index da06ab70c..54a45fd18 100644
--- a/Bugzilla/Install/Requirements.pm
+++ b/Bugzilla/Install/Requirements.pm
@@ -33,7 +33,6 @@ use autodie;
our @EXPORT = qw(
FEATURE_FILES
- load_cpan_meta
check_cpan_requirements
check_cpan_feature
check_all_cpan_features
@@ -104,25 +103,6 @@ use constant FEATURE_FILES => (
s3 => ['Bugzilla/S3.pm', 'Bugzilla/S3/Bucket.pm', 'Bugzilla/Attachment/S3.pm']
);
-sub load_cpan_meta {
- my $dir = bz_locations()->{libpath};
- my @meta_json = map { File::Spec->catfile($dir, $_) } qw( MYMETA.json META.json );
- my ($file) = grep { -f $_ } @meta_json;
-
- if ($file) {
- open my $meta_fh, '<', $file or die "unable to open $file: $!";
- my $str = do { local $/ = undef; scalar <$meta_fh> };
- # detaint
- $str =~ /^(.+)$/s; $str = $1;
- close $meta_fh;
-
- return CPAN::Meta->load_json_string($str);
- }
- else {
- ThrowCodeError('cpan_meta_missing');
- }
-}
-
sub check_all_cpan_features {
my ($meta, $dirs, $output) = @_;
my %report;
@@ -163,7 +143,7 @@ sub check_cpan_requirements {
sub _check_prereqs {
my ($prereqs, $dirs, $output) = @_;
$dirs //= \@INC;
- my $reqs = $prereqs->merged_requirements(['configure', 'runtime'], ['requires']);
+ my $reqs = Bugzilla::CPAN->cpan_requirements($prereqs);
my @found;
my @missing;
@@ -484,11 +464,6 @@ Returns: C<1> if the check was successful, C<0> otherwise.
Returns a hashref where file names are the keys and the value is the feature
that must be enabled in order to compile that file.
-=item C<load_cpan_meta>
-
-Load MYMETA.json or META.json from the bugzilla directory, and a return a L<CPAN::Meta> object.
-
=back
=back
-
diff --git a/Bugzilla/Install/Util.pm b/Bugzilla/Install/Util.pm
index c65c0e061..33b3d43d3 100644
--- a/Bugzilla/Install/Util.pm
+++ b/Bugzilla/Install/Util.pm
@@ -268,7 +268,7 @@ sub indicate_progress {
sub feature_description {
my ($feature_name) = @_;
eval {
- my $meta = _cache()->{cpan_meta} //= Bugzilla::Install::Requirements::load_cpan_meta();
+ my $meta = Bugzilla::CPAN->cpan_meta;
return $meta->feature($feature_name)->description
} or warn $@;