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