diff --git a/README b/README index a6be4f9..09926fe 100644 --- a/README +++ b/README @@ -20,14 +20,17 @@ DESCRIPTION This function arranges for the following directories to be installed, if they exist (assuming "RTx('RT-Extension-Example')"): - ./bin => $RT::LocalPluginPath/RT-Extension-Example/bin - ./etc => $RT::LocalPluginPath/RT-Extension-Example/etc - ./html => $RT::LocalPluginPath/RT-Extension-Example/html - ./lib => $RT::LocalPluginPath/RT-Extension-Example/lib - ./po => $RT::LocalPluginPath/RT-Extension-Example/po - ./sbin => $RT::LocalPluginPath/RT-Extension-Example/sbin - ./static => $RT::LocalPluginPath/RT-Extension-Example/static - ./var => $RT::LocalPluginPath/RT-Extension-Example/var + ./bin => $RT::LocalPluginPath/RT-Extension-Example/bin + ./etc => $RT::LocalPluginPath/RT-Extension-Example/etc + ./html => $RT::LocalPluginPath/RT-Extension-Example/html + ./lib => $RT::LocalPluginPath/RT-Extension-Example/lib + ./po => $RT::LocalPluginPath/RT-Extension-Example/po + ./sbin => $RT::LocalPluginPath/RT-Extension-Example/sbin + ./static => $RT::LocalPluginPath/RT-Extension-Example/static + ./var => $RT::LocalPluginPath/RT-Extension-Example/var + ./patches => If this directory/sub directory(s) contain one or more + p1 unified diffs they will be applied to the RT + installation. Invoked in your plugin as make patch Accepts an optional argument hashref after the extension name with two possible keys diff --git a/lib/Module/Install/RTx.pm b/lib/Module/Install/RTx.pm index 002eb7a..c21d6c3 100644 --- a/lib/Module/Install/RTx.pm +++ b/lib/Module/Install/RTx.pm @@ -139,6 +139,11 @@ install :: $has_etc{upgrade}++; } + my %has_patches; + if ( -d 'patches' ) { + $has_patches{patches}++; + } + $self->postamble("$postamble\n"); if ( $path{lib} ) { $self->makemaker_args( INSTALLSITELIB => $path{'lib'} ); @@ -181,6 +186,16 @@ install :: } } + if (%has_patches) { + print "For first-time installation, type 'make patch'.\n"; + my $patch = qq|\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Iinc -MModule::Install::RTx::Runtime -e"RTxPatch(qw(/usr/bin/patch apply ./patches))"\n|; + $self->postamble("patch ::\n$patch\n"); + + print "For patch removal, type 'make unpatch'.\n"; + my $unpatch = qq|\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Iinc -MModule::Install::RTx::Runtime -e"RTxPatch(qw(/usr/bin/patch remove ./patches))"\n|; + $self->postamble("unpatch ::\n$unpatch\n"); + } + } sub requires_rt { @@ -304,14 +319,17 @@ installing RT extensions: This function arranges for the following directories to be installed, if they exist (assuming C): - ./bin => $RT::LocalPluginPath/RT-Extension-Example/bin - ./etc => $RT::LocalPluginPath/RT-Extension-Example/etc - ./html => $RT::LocalPluginPath/RT-Extension-Example/html - ./lib => $RT::LocalPluginPath/RT-Extension-Example/lib - ./po => $RT::LocalPluginPath/RT-Extension-Example/po - ./sbin => $RT::LocalPluginPath/RT-Extension-Example/sbin - ./static => $RT::LocalPluginPath/RT-Extension-Example/static - ./var => $RT::LocalPluginPath/RT-Extension-Example/var + ./bin => $RT::LocalPluginPath/RT-Extension-Example/bin + ./etc => $RT::LocalPluginPath/RT-Extension-Example/etc + ./html => $RT::LocalPluginPath/RT-Extension-Example/html + ./lib => $RT::LocalPluginPath/RT-Extension-Example/lib + ./po => $RT::LocalPluginPath/RT-Extension-Example/po + ./sbin => $RT::LocalPluginPath/RT-Extension-Example/sbin + ./static => $RT::LocalPluginPath/RT-Extension-Example/static + ./var => $RT::LocalPluginPath/RT-Extension-Example/var + ./patches => If this directory/sub directory(s) contain one or more + p1 unified diffs they will be applied to the RT + installation. Invoked in your plugin as make patch Accepts an optional argument hashref after the extension name with two possible keys diff --git a/lib/Module/Install/RTx/Runtime.pm b/lib/Module/Install/RTx/Runtime.pm index 318e8c6..fd94a62 100644 --- a/lib/Module/Install/RTx/Runtime.pm +++ b/lib/Module/Install/RTx/Runtime.pm @@ -1,10 +1,111 @@ package Module::Install::RTx::Runtime; use base 'Exporter'; -our @EXPORT = qw/RTxDatabase RTxPlugin/; +our @EXPORT = qw/RTxDatabase RTxPatch RTxPlugin/; use strict; use File::Basename (); +use POSIX qw (WIFEXITED); +use File::Find; +use Carp; +use Cwd; + + +# Switch +my $dispatch ={ + '>' => \&_greater_than, + '<' => \&_less_than, + '-' => \&_in_range, + '=' => \&_equal, +}; + +sub _in_range { + my ($rt_ver, $dir) = @_; + + # Get our lower and upper versions + my ($start_ver, $end_ver) = $dir =~ m/([\d\.]+)-([\d\.]+)/xms; + + # Check if rt_ver is between range of version values + return 1 if &_greater_than($rt_ver, $start_ver) + and &_less_than($rt_ver, $end_ver); + return 1 if &_equal($rt_ver, $start_ver); + return 1 if &_equal($rt_ver, $end_ver); + return 0; +} + +sub _greater_than { + my ($rt_ver, $patch_ver) = @_; + + $patch_ver =~ s/\A>//xms; + $patch_ver = _convert_version($patch_ver); + $rt_ver = _convert_version($rt_ver); + + # Return TRUE if we are greater than the patch + return 1 if $rt_ver > $patch_ver; + return 0; +} + +sub _less_than { + my ($rt_ver, $patch_ver) = @_; + + $patch_ver =~ s/\A{'-'}($version, $dir) if $dir =~ m/[\d.]+.\d-\d.[\d.]+/xms; + # Check greater than + return $dispatch->{'>'}($version, $dir) if $dir =~ m/\A>[\d.]+\z/xms; + # Check less than + return $dispatch->{'<'}($version, $dir) if $dir =~ m/\A<[\d.]+\z/xms; + # Check if equal + return $dispatch->{'='}($version, $dir) if $dir =~ m/\A\d.\d+\z/xms; + + # If none of the above match then just apply the patch(s) regardless + return 1; +} sub _rt_runtime_load { require RT; @@ -54,6 +155,40 @@ sub RTxDatabase { (system($^X, @args) == 0) or die "...returned with error: $?\n"; } +sub RTxPatch { + my ($patch, $action, $dir) = @_; + my @cmd; + + _rt_runtime_load(); + + # Check to see if we are adding or removing a patch set + if ( $action =~ m/\Aapply\z/xms ) { + @cmd = ($patch, '-d', $RT::BasePath, '-p1', '-i'); + } + else { + @cmd = ($patch, '-R', '-d', $RT::BasePath, '-p1', '-i'); + } + + # Anonymous subroutine to apply all patches in a directory structure + my $patch_rt = sub { + + # Next entry if not a file + return unless -f $_; + + # Next entry if not approprate version of patch + return unless &_required_patch($File::Find::dir, $RT::VERSION); + + if ($_ =~ m/\.patch\z/xms) { + push @cmd, getcwd . "/$_"; + WIFEXITED(system(@cmd)) + or croak "Couldn't run: " . join(' ', @cmd) . "($?)\n"; + pop @cmd; + } + }; + + find {wanted => $patch_rt}, $dir; +} + sub RTxPlugin { my ($name) = @_; diff --git a/t/1-runtime.t b/t/1-runtime.t new file mode 100644 index 0000000..19aae6f --- /dev/null +++ b/t/1-runtime.t @@ -0,0 +1,94 @@ +#!/usr/bin/perl + +use Test::More; + +require Module::Install::RTx::Runtime; + +is ( Module::Install::RTx::Runtime::_convert_version('1'), '1', + 'is 1 converted to 1'); +is ( Module::Install::RTx::Runtime::_convert_version('1.0'), '1.0', + 'is 1.0 converted to 1.0'); +is ( Module::Install::RTx::Runtime::_convert_version('0.1'), '0.1', + 'is 0.1 converted to 0.1'); +is ( Module::Install::RTx::Runtime::_convert_version('0.0.1'), '0.001', + 'is 0.0.1 converted to 0.001'); +is ( Module::Install::RTx::Runtime::_convert_version('11'), '11', + 'is 11 converted to 11'); +is ( Module::Install::RTx::Runtime::_convert_version('11.0'), '11.0', + 'is 11.0 converted to 11.0'); +is ( Module::Install::RTx::Runtime::_convert_version('4.4.18'), '4.4018', + 'is 4.4.18 converted to 4.4018'); +is ( Module::Install::RTx::Runtime::_convert_version('4.40.18'), '4.40018', + 'is 4.40.18 converted to 4.40018'); +is ( Module::Install::RTx::Runtime::_convert_version('440.18'), '440.18', + 'is 440.18 converted to 440.18'); +is ( Module::Install::RTx::Runtime::_convert_version('4.4.1.8'), '4.40108', + 'is 4.4.1.8 converted to 4.40108'); + +is ( Module::Install::RTx::Runtime::_equal('1', '1'), 1, + '1 is equal to 1'); +is ( Module::Install::RTx::Runtime::_equal('0.1', '0.1'), 1, + '0.1 is equal to 0.1'); +is ( Module::Install::RTx::Runtime::_equal('11', '1.1'), 0, + '11 is not equal to 1.1'); +is ( Module::Install::RTx::Runtime::_equal('1.1', '11'), 0, + '1.1 is not equal to 11'); +is ( Module::Install::RTx::Runtime::_equal('1.1', '1.1'), 1, + '1.1 is equal to 1.1'); +is ( Module::Install::RTx::Runtime::_equal('1.1.1', '1.1.1'), 1, + '1.1.1 is equal to 1.1.1'); +is ( Module::Install::RTx::Runtime::_equal('1.11.1', '1.11.1'), 1, + '1.11.1 is equal to 1.11.1'); +is ( Module::Install::RTx::Runtime::_equal('1.1.1', '1.11'), 0, + '1.1.1 is not equal to 1.11'); +is ( Module::Install::RTx::Runtime::_equal('1.11.1', '1.111'), 0, + '1.11.1 is not equal to 1.111'); +is ( Module::Install::RTx::Runtime::_equal('1.11.1', '1111'), 0, + '1.11.1 is not equal to 1111'); + +is ( Module::Install::RTx::Runtime::_greater_than('2', '>1'), 1, + '2 is greater than 1' ); +is ( Module::Install::RTx::Runtime::_greater_than('1.1', '>1.1'), 0, + '1.1 is not greater than 1.1' ); +is ( Module::Install::RTx::Runtime::_greater_than('1.1', '>1'), 1, + '1.1 is greater than 1' ); +is ( Module::Install::RTx::Runtime::_greater_than('1.1', '>2'), 0, + '1.1 is not greater than 2' ); +is ( Module::Install::RTx::Runtime::_greater_than('1.1', '>11'), 0, + '1.1 is not greater than 11' ); +is ( Module::Install::RTx::Runtime::_greater_than('1.11', '>11.1'), 0, + '1.11 is not greater than 11.1' ); +is ( Module::Install::RTx::Runtime::_greater_than('111', '>11.1'), 1, + '111 is greater than 11.1' ); + +is ( Module::Install::RTx::Runtime::_less_than('2', '<1'), 0, + '2 is not less than 1' ); +is ( Module::Install::RTx::Runtime::_less_than('1.1', '<1.1'), 0, + '1.1 is not less than 1.1' ); +is ( Module::Install::RTx::Runtime::_less_than('1.1', '<1'), 0, + '1.1 is not less than 1' ); +is ( Module::Install::RTx::Runtime::_less_than('1.1', '<2'), 1, + '1.1 is less than 2' ); +is ( Module::Install::RTx::Runtime::_less_than('1.1', '<11'), 1, + '1.1 is less than 11' ); +is ( Module::Install::RTx::Runtime::_less_than('1.11', '<11.1'), 1, + '1.11 is less than 11.1' ); +is ( Module::Install::RTx::Runtime::_less_than('111', '<11.1'), 0, + '111 is not less than 11.1' ); + +is ( Module::Install::RTx::Runtime::_in_range('1.1', '1-1.5'), 1, + '1.1 is in range 1 and 1.5' ); +is ( Module::Install::RTx::Runtime::_in_range('0.1', '1-1.5'), 0, + '0.1 is not in range 1 and 1.5' ); +is ( Module::Install::RTx::Runtime::_in_range('2.1', '2-3'), 1, + '2.1 is in range 2 and 3' ); +is ( Module::Install::RTx::Runtime::_in_range('2', '2-3'), 1, + '2 is between 2 and 3' ); +is ( Module::Install::RTx::Runtime::_in_range('2.0', '2-3'), 1, + '2.0 is in range 2 and 3' ); +is ( Module::Install::RTx::Runtime::_in_range('2', '2-2'), 1, + '2 is in range 2 and 2' ); + +done_testing($number_of_tests); + +1;