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