File Coverage

blib/lib/Module/Install/RTx.pm
Criterion Covered Total %
statement 29 187 15.5
branch 0 88 0.0
condition 0 24 0.0
subroutine 10 15 66.6
pod 4 4 100.0
total 43 318 13.5


line stmt bran cond sub pod time code
1             package Module::Install::RTx;
2              
3 1     1   495 use 5.008;
  1         3  
4 1     1   5 use strict;
  1         1  
  1         19  
5 1     1   4 use warnings;
  1         2  
  1         23  
6 1     1   5 no warnings 'once';
  1         2  
  1         52  
7              
8 1     1   700 use Term::ANSIColor qw(:constants);
  1         8220  
  1         1072  
9 1     1   495 use Module::Install::Base;
  1         2  
  1         31  
10 1     1   6 use base 'Module::Install::Base';
  1         2  
  1         109  
11             our $VERSION = '0.42';
12              
13 1     1   525 use FindBin;
  1         1026  
  1         44  
14 1     1   7 use File::Glob ();
  1         2  
  1         13  
15 1     1   5 use File::Basename ();
  1         1  
  1         2471  
16              
17             my @DIRS = qw(etc lib html static bin sbin po var);
18             my @INDEX_DIRS = qw(lib bin sbin);
19              
20             sub RTx {
21 0     0 1   my ( $self, $name, $extra_args ) = @_;
22 0   0       $extra_args ||= {};
23              
24             # Set up names
25 0           my $fname = $name;
26 0           $fname =~ s!-!/!g;
27              
28 0 0         $self->name( $name )
29             unless $self->name;
30 0 0         $self->all_from( "lib/$fname.pm" )
31             unless $self->version;
32 0 0         $self->abstract("$name Extension")
33             unless $self->abstract;
34 0 0         unless ( $extra_args->{no_readme_generation} ) {
35 0           $self->readme_from( "lib/$fname.pm",
36             { options => [ quotes => "none" ] } );
37             }
38 0           $self->add_metadata("x_module_install_rtx_version", $VERSION );
39              
40 0           my $installdirs = $ENV{INSTALLDIRS};
41 0           for ( @ARGV ) {
42 0 0         if ( /INSTALLDIRS=(.*)/ ) {
43 0           $installdirs = $1;
44             }
45             }
46              
47             # Try to find RT.pm
48 0           my @prefixes = qw( /opt /usr/local /home /usr /sw /usr/share/request-tracker4);
49 0 0         $ENV{RTHOME} =~ s{/RT\.pm$}{} if defined $ENV{RTHOME};
50 0 0         $ENV{RTHOME} =~ s{/lib/?$}{} if defined $ENV{RTHOME};
51 0 0         my @try = $ENV{RTHOME} ? ($ENV{RTHOME}, "$ENV{RTHOME}/lib") : ();
52 0           while (1) {
53 0           my @look = @INC;
54 0 0         unshift @look, grep {defined and -d $_} @try;
  0            
55 0 0         push @look, grep {defined and -d $_}
56 0           map { ( "$_/rt5/lib", "$_/lib/rt5", "$_/rt4/lib", "$_/lib/rt4", "$_/lib" ) } @prefixes;
  0            
57 0 0         last if eval {local @INC = @look; require RT; $RT::LocalLibPath};
  0            
  0            
  0            
58              
59 0           warn
60             "Cannot find the location of RT.pm that defines \$RT::LocalPath in: @look\n";
61 0 0         my $given = $self->prompt("Path to directory containing your RT.pm:") or exit;
62 0           $given =~ s{/RT\.pm$}{};
63 0           $given =~ s{/lib/?$}{};
64 0           @try = ($given, "$given/lib");
65             }
66              
67 0           print "Using RT configuration from $INC{'RT.pm'}:\n";
68              
69 0           my $local_lib_path = $RT::LocalLibPath;
70 0           unshift @INC, $local_lib_path;
71 0           my $lib_path = File::Basename::dirname( $INC{'RT.pm'} );
72 0           unshift @INC, $lib_path;
73              
74             # Set a baseline minimum version
75 0 0         unless ( $extra_args->{deprecated_rt} ) {
76 0           $self->requires_rt('4.0.0');
77             }
78              
79 0           my $package = $name;
80 0           $package =~ s/-/::/g;
81 0 0         if ( $RT::CORED_PLUGINS{$package} ) {
82 0           my ($base_version) = $RT::VERSION =~ /(\d+\.\d+\.\d+)/;
83 0           die RED, <<"EOT";
84              
85             **** Error: Your installed version of RT ($RT::VERSION) already
86             contains this extension in core, so you don't need to
87             install it.
88              
89             Check https://docs.bestpractical.com/rt/$base_version/RT_Config.html
90             to configure it.
91              
92             EOT
93             }
94              
95             # Installation locations
96 0           my %path;
97             my $plugin_path;
98 0 0 0       if ( $installdirs && $installdirs eq 'vendor' ) {
99 0           $plugin_path = $RT::PluginPath;
100             } else {
101 0           $plugin_path = $RT::LocalPluginPath;
102             }
103             $path{$_} = $plugin_path . "/$name/$_"
104 0           foreach @DIRS;
105              
106             # Copy RT 4.2.0 static files into NoAuth; insufficient for
107             # images, but good enough for css and js.
108 0 0         $path{static} = "$path{html}/NoAuth/"
109             unless $RT::StaticPath;
110              
111             # Delete the ones we don't need
112 0           delete $path{$_} for grep {not -d "$FindBin::Bin/$_"} keys %path;
  0            
113              
114 0           my %index = map { $_ => 1 } @INDEX_DIRS;
  0            
115 0           $self->no_index( directory => $_ ) foreach grep !$index{$_}, @DIRS;
116              
117 0           my $args = join ', ', map "q($_)", map { ($_, "\$(DESTDIR)$path{$_}") }
  0            
118             sort keys %path;
119              
120 0           printf "%-10s => %s\n", $_, $path{$_} for sort keys %path;
121              
122 0 0         if ( my @dirs = map { ( -D => $_ ) } grep $path{$_}, qw(bin html sbin etc) ) {
  0            
123 0           my @po = map { ( -o => $_ ) }
  0            
124             grep -f,
125             File::Glob::bsd_glob("po/*.po");
126 0 0         $self->postamble(<< ".") if @po;
127             lexicons ::
128             \t\$(NOECHO) \$(PERL) -MLocale::Maketext::Extract::Run=xgettext -e \"xgettext(qw(@dirs @po))\"
129             .
130             }
131              
132 0           my $remove_files;
133 0 0         if( $extra_args->{'remove_files'} ){
134 0           $self->include('Module::Install::RTx::Remove');
135 0           our @remove_files;
136 0 0         eval { require "etc/upgrade/remove_files" }
  0            
137             or print "No remove file located, no files to remove\n";
138 0           $remove_files = join ",", map {"q(\$(DESTDIR)$plugin_path/$name/$_)"} @remove_files;
  0            
139             }
140              
141 0 0         $self->include('Module::Install::RTx::Runtime') if $self->admin;
142 0 0         $self->include_deps( 'YAML::Tiny', 0 ) if $self->admin;
143 0           my $postamble = << ".";
144             install ::
145             \t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Iinc -MModule::Install::RTx::Runtime -e"RTxPlugin()"
146             .
147              
148 0 0         if( $remove_files ){
149 0           $postamble .= << ".";
150             \t\$(NOECHO) \$(PERL) -MModule::Install::RTx::Remove -e \"RTxRemove([$remove_files])\"
151             .
152             }
153              
154 0           $postamble .= << ".";
155             \t\$(NOECHO) \$(PERL) -MExtUtils::Install -e \"install({$args})\"
156             .
157              
158 0 0 0       if ( $path{var} and -d $RT::MasonDataDir ) {
159 0           my ( $uid, $gid ) = ( stat($RT::MasonDataDir) )[ 4, 5 ];
160 0           $postamble .= << ".";
161             \t\$(NOECHO) chown -R $uid:$gid $path{var}
162             .
163             }
164              
165 0           my %has_etc;
166 0 0         if ( File::Glob::bsd_glob("$FindBin::Bin/etc/schema.*") ) {
167 0           $has_etc{schema}++;
168             }
169 0 0         if ( File::Glob::bsd_glob("$FindBin::Bin/etc/acl.*") ) {
170 0           $has_etc{acl}++;
171             }
172 0 0         if ( -e 'etc/initialdata' ) { $has_etc{initialdata}++; }
  0            
173 0 0         if ( grep { /\d+\.\d+\.\d+.*$/ } glob('etc/upgrade/*.*.*') ) {
  0            
174 0           $has_etc{upgrade}++;
175             }
176              
177 0           $self->postamble("$postamble\n");
178 0 0         if ( $path{lib} ) {
179 0           $self->makemaker_args( INSTALLSITELIB => $path{'lib'} );
180 0           $self->makemaker_args( INSTALLARCHLIB => $path{'lib'} );
181 0           $self->makemaker_args( INSTALLVENDORLIB => $path{'lib'} )
182             } else {
183 0           $self->makemaker_args( PM => { "" => "" }, );
184             }
185              
186 0           $self->makemaker_args( INSTALLSITEMAN1DIR => "$RT::LocalPath/man/man1" );
187 0           $self->makemaker_args( INSTALLSITEMAN3DIR => "$RT::LocalPath/man/man3" );
188 0           $self->makemaker_args( INSTALLSITEARCH => "$RT::LocalPath/man" );
189              
190             # INSTALLDIRS=vendor should install manpages into /usr/share/man.
191             # That is the default path in most distributions. Need input from
192             # Redhat, Centos etc.
193 0           $self->makemaker_args( INSTALLVENDORMAN1DIR => "/usr/share/man/man1" );
194 0           $self->makemaker_args( INSTALLVENDORMAN3DIR => "/usr/share/man/man3" );
195 0           $self->makemaker_args( INSTALLVENDORARCH => "/usr/share/man" );
196              
197 0 0         if (%has_etc) {
198 0           print "For first-time installation, type 'make initdb'.\n";
199 0           my $initdb = '';
200 0 0         $initdb .= <<"." if $has_etc{schema};
201             \t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Iinc -MModule::Install::RTx::Runtime -e"RTxDatabase(qw(schema \$(NAME) \$(VERSION)))"
202             .
203 0 0         $initdb .= <<"." if $has_etc{acl};
204             \t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Iinc -MModule::Install::RTx::Runtime -e"RTxDatabase(qw(acl \$(NAME) \$(VERSION)))"
205             .
206 0 0         $initdb .= <<"." if $has_etc{initialdata};
207             \t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Iinc -MModule::Install::RTx::Runtime -e"RTxDatabase(qw(insert \$(NAME) \$(VERSION)))"
208             .
209 0           $self->postamble("initdb ::\n$initdb\n");
210 0           $self->postamble("initialize-database ::\n$initdb\n");
211 0 0         if ($has_etc{upgrade}) {
212 0           print "To upgrade from a previous version of this extension, use 'make upgrade-database'\n";
213 0           my $upgradedb = qq|\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Iinc -MModule::Install::RTx::Runtime -e"RTxDatabase(qw(upgrade \$(NAME) \$(VERSION)))"\n|;
214 0           $self->postamble("upgrade-database ::\n$upgradedb\n");
215 0           $self->postamble("upgradedb ::\n$upgradedb\n");
216             }
217             }
218              
219             }
220              
221             sub requires_rt {
222 0     0 1   my ($self,$version) = @_;
223              
224 0           _load_rt_handle();
225              
226 0 0         if ($self->is_admin) {
227 0           $self->add_metadata("x_requires_rt", $version);
228 0           my @sorted = sort RT::Handle::cmp_version $version,'4.0.0';
229 0 0 0       $self->perl_version('5.008003') if $sorted[0] eq '4.0.0'
      0        
230             and (not $self->perl_version or '5.008003' > $self->perl_version);
231 0           @sorted = sort RT::Handle::cmp_version $version,'4.2.0';
232 0 0 0       $self->perl_version('5.010001') if $sorted[0] eq '4.2.0'
      0        
233             and (not $self->perl_version or '5.010001' > $self->perl_version);
234             }
235              
236             # if we're exactly the same version as what we want, silently return
237 0 0         return if ($version eq $RT::VERSION);
238              
239 0           my @sorted = sort RT::Handle::cmp_version $version,$RT::VERSION;
240              
241 0 0         if ($sorted[-1] eq $version) {
242 0           die RED, <<"EOT";
243              
244             **** Error: This extension requires RT $version. Your installed version
245             of RT ($RT::VERSION) is too old.
246              
247             EOT
248             }
249             }
250              
251             sub requires_rt_plugin {
252 0     0 1   my $self = shift;
253 0           my ( $plugin ) = @_;
254              
255 0 0         if ($self->is_admin) {
256 0   0       my $plugins = $self->Meta->{values}{"x_requires_rt_plugins"} || [];
257 0           push @{$plugins}, $plugin;
  0            
258 0           $self->add_metadata("x_requires_rt_plugins", $plugins);
259             }
260              
261 0           my $path = $plugin;
262 0           $path =~ s{\:\:}{-}g;
263 0           $path = "$RT::LocalPluginPath/$path/lib";
264 0 0         if ( -e $path ) {
265 0           unshift @INC, $path;
266             } else {
267 0           my $name = $self->name;
268 0           my $msg = <<"EOT";
269              
270             **** Warning: $name requires that the $plugin plugin be installed and
271             enabled; it does not appear to be installed.
272             EOT
273 0           warn RED, $msg, RESET, "\n";
274             }
275 0           $self->requires(@_);
276             }
277              
278             sub rt_too_new {
279 0     0 1   my ($self,$version,$msg) = @_;
280 0           my $name = $self->name;
281 0   0       $msg ||= <
282              
283             **** Warning: Your installed version of RT (%s) is too new; this extension
284             has not been tested on your version of RT and may not work as expected.
285             EOT
286 0 0         $self->add_metadata("x_rt_too_new", $version) if $self->is_admin;
287              
288 0           _load_rt_handle();
289 0           my @sorted = sort RT::Handle::cmp_version $version,$RT::VERSION;
290              
291 0 0         if ($sorted[0] eq $version) {
292 0           warn RED, sprintf($msg,$RT::VERSION), RESET, "\n";
293             }
294             }
295              
296             # RT::Handle runs FinalizeDatabaseType which calls RT->Config->Get
297             # On 3.8, this dies. On 4.0/4.2 ->Config transparently runs LoadConfig.
298             # LoadConfig requires being able to read RT_SiteConfig.pm (root) so we'd
299             # like to avoid pushing that on users.
300             # Fake up just enough Config to let FinalizeDatabaseType finish, and
301             # anyone later calling LoadConfig will overwrite our shenanigans.
302             sub _load_rt_handle {
303 0 0   0     unless ($RT::Config) {
304 0           require RT::Config;
305 0           $RT::Config = RT::Config->new;
306 0           RT->Config->Set('DatabaseType','mysql');
307             }
308 0           require RT::Handle;
309             }
310              
311             1;
312              
313             __END__