]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 530767: Allow for CPAN distribution of extensions
authormkanat%bugzilla.org <>
Wed, 25 Nov 2009 06:19:13 +0000 (06:19 +0000)
committermkanat%bugzilla.org <>
Wed, 25 Nov 2009 06:19:13 +0000 (06:19 +0000)
Patch by Max Kanat-Alexander <mkanat@bugzilla.org> (module owner) a=mkanat

Bugzilla/Extension.pm
Bugzilla/Install/Filesystem.pm
Bugzilla/Install/Util.pm

index 48efd76f610b272ebff44acd619b4507b2c4e1b4..cd280bb8438e0ab3a288ee5cb51433dda3aa41f3 100644 (file)
@@ -93,6 +93,21 @@ sub load {
         $package->modify_inc($extension_file) if !$config_file;
     }
 
+    $class->_validate_package($package, $extension_file);
+    return $package;
+}
+
+sub _validate_package {
+    my ($class, $package, $extension_file) = @_;
+
+    # For extensions from data/extensions/additional, we don't have a file
+    # name, so we fake it.
+    if (!$extension_file) {
+        $extension_file = $package;
+        $extension_file =~ s/::/\//g;
+        $extension_file .= '.pm';
+    }
+
     if (!eval { $package->NAME }) {
         ThrowCodeError('extension_no_name', 
                        { filename => $extension_file, package => $package });
@@ -104,19 +119,30 @@ sub load {
                          package  => $package,
                          class    => $class });
     }
-
-    return $package;
 }
 
 sub load_all {
     my $class = shift;
-    my $file_sets = extension_code_files();
+    my ($file_sets, $extra_packages) = extension_code_files();
     my @packages;
     foreach my $file_set (@$file_sets) {
         my $package = $class->load(@$file_set);
         push(@packages, $package);
     }
 
+    # Extensions from data/extensions/additional
+    foreach my $package (@$extra_packages) {
+        # Don't load an "additional" extension if we already have an extension
+        # loaded with that name.
+        next if grep($_ eq $package, @packages);
+        # Untaint the package name
+        $package =~ /([\w:]+)/;
+        $package = $1;
+        eval("require $package") || die $@;
+        $package->_validate_package($package);
+        push(@packages, $package);
+    }
+
     return \@packages;
 }
 
@@ -402,6 +428,39 @@ for its module pre-requisites, but you don't want the module to be used
 by Bugzilla, then you should make your extension's L</enabled> method
 return C<0> or some false value.
 
+=head1 DISTRIBUTING EXTENSIONS
+
+If you've made an extension and you want to publish it, the first
+thing you'll want to do is package up your extension's code and
+then put a link to it in the appropriate section of 
+L<http://wiki.mozilla.org/Bugzilla:Addons>.
+
+=head2 Distributing on CPAN
+
+If you want a centralized distribution point that makes it easy
+for Bugzilla users to install your extension, it is possible to 
+distribute your Bugzilla Extension through CPAN.
+
+The details of making a standard CPAN module are too much to
+go into here, but a lot of it is covered in L<perlmodlib>
+and on L<http://www.cpan.org/> among other places.
+
+When you distribute your extension via CPAN, your F<Extension.pm>
+should simply install itself as F<Bugzilla/Extension/Foo.pm>, 
+where C<Foo> is the name of your module. You do not need a separate
+F<Config.pm> file, because CPAN itself will handle installing
+the prerequisites of your module, so Bugzilla doesn't have to
+worry about it.
+
+=head3 Using a module distributed on CPAN
+
+There is a file named F<data/extensions/additional> in Bugzilla.
+This is a plain-text file. Each line is the name of a module,
+like C<Bugzilla::Extension::Foo>. In addition to the extensions
+in the F<extensions/> directory, each module listed in this file
+will be loaded as a Bugzilla Extension whenever Bugzilla loads or
+uses extensions.
+
 =head1 ADDITIONAL CONSTANTS
 
 In addition to C<NAME>, there are some other constants you might
index 819da24dd6ecf865fadc51af95ccdd41124a42d4..12c0bc2221625d6d33c5abd0d4e57b31fe460826 100644 (file)
@@ -198,6 +198,7 @@ sub FILESYSTEM {
     my %create_dirs = (
         $datadir                => $ws_dir_full_control,
         "$datadir/mining"       => $ws_dir_readable,
+        "$datadir/extensions"   => $ws_dir_readable,
         $attachdir              => $ws_dir_writeable,
         $extensionsdir          => $ws_dir_readable,
         graphs                  => $ws_dir_writeable,
@@ -208,7 +209,10 @@ sub FILESYSTEM {
 
     # The name of each file, pointing at its default permissions and
     # default contents.
-    my %create_files = ();
+    my %create_files = (
+        "$datadir/extensions/additional" => { perms    => $ws_readable, 
+                                              contents => '' },
+    );
 
     # Each standard stylesheet has an associated custom stylesheet that
     # we create. Also, we create placeholders for standard stylesheets
index 107f91a9bf22b4fca6bff15e63709af55de1f12b..c60e32afe1d7a0a03ca30e73c2fe5da9e871db75 100644 (file)
@@ -130,7 +130,16 @@ sub extension_code_files {
         trick_taint($_) foreach @load_files;
         push(@files, \@load_files);
     }
-    return \@files;
+
+    my @additional;
+    my $datadir = bz_locations()->{'datadir'};
+    my $addl_file = "$datadir/extensions/additional";
+    if (-e $addl_file) {
+        open(my $fh, '<', $addl_file) || die "$addl_file: $!";
+        @additional = map { trim($_) } <$fh>;
+        close($fh);
+    }
+    return (\@files, \@additional);
 }
 
 # Used by _get_extension_requirements in Bugzilla::Install::Requirements.
@@ -150,8 +159,8 @@ sub extension_requirement_packages {
     $packages = [];
     my %package_map;
     
-    my $extension_files = extension_code_files('requirements only');
-    foreach my $file_set (@$extension_files) {
+    my ($file_sets, $extra_packages) = extension_code_files('requirements only');
+    foreach my $file_set (@$file_sets) {
         my $file = shift @$file_set;
         my $name = require $file;
         if ($name =~ /^\d+$/) {
@@ -162,6 +171,11 @@ sub extension_requirement_packages {
         $package_map{$file} = $package;
         push(@$packages, $package);
     }
+    foreach my $package (@$extra_packages) {
+        eval("require $package") || die $@;
+        push(@$packages, $package);
+    }
+
     _cache()->{extension_requirement_packages} = $packages;
     # Used by Bugzilla::Extension->load if it's called after this method
     # (which only happens during checksetup.pl, currently).
@@ -495,6 +509,15 @@ sub trick_taint {
     return (defined($_[0]));
 }
 
+sub trim {
+    my ($str) = @_;
+    if ($str) {
+      $str =~ s/^\s+//g;
+      $str =~ s/\s+$//g;
+    }
+    return $str;
+}
+
 __END__
 
 =head1 NAME