From 57a717550df44ee91553da13c0a0529e7dc3cf60 Mon Sep 17 00:00:00 2001 From: Martin Wheldon Date: Mon, 14 Nov 2016 22:18:55 +0000 Subject: [PATCH 1/3] Add additional make target - make patch Updated to add the make patch target and the Runtime method to carry out the task. --- README | 19 +++++++++++-------- lib/Module/Install/RTx.pm | 30 ++++++++++++++++++++++-------- lib/Module/Install/RTx/Runtime.pm | 27 ++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 17 deletions(-) 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..3617120 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,12 @@ 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 ./patches))"\n|; + $self->postamble("patch ::\n$patch\n"); + } + } sub requires_rt { @@ -304,14 +315,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..3ee521b 100644 --- a/lib/Module/Install/RTx/Runtime.pm +++ b/lib/Module/Install/RTx/Runtime.pm @@ -1,10 +1,14 @@ 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; + sub _rt_runtime_load { require RT; @@ -54,6 +58,27 @@ sub RTxDatabase { (system($^X, @args) == 0) or die "...returned with error: $?\n"; } +sub RTxPatch { + my ($patch, $dir) = @_; + + _rt_runtime_load(); + + my $cmd = "$patch -d $RT::BasePath -p1 < "; + + # Anonymous subroutine to apply all patches in a directory structure + my $patch_rt = sub { + + return unless -f $_; + if ($_ =~ m/.patch/xms) { + WIFEXITED(system($cmd . $_)) + or croak "Couldn't run: $cmd $_ ($?)\n"; + } + }; + + find {wanted => $patch_rt}, $dir; + +} + sub RTxPlugin { my ($name) = @_; From 10892063737dddf6d3766ce35f6052d04a2ab171 Mon Sep 17 00:00:00 2001 From: Martin Wheldon Date: Fri, 18 Nov 2016 22:33:01 +0000 Subject: [PATCH 2/3] Updated make patch functionality Convert to use list style system call Fixed regex matching for files ending .patch Added functionality to apply patches to specific versions by organising patches into directories with following naming i.e: >4.2 - Apply to RT versions after 4.2 <4.4 - Apply to RT versions before 4.4 4.4.1 - Apply to RT 4.4.1 only 4.2-4.4 - Apply to RT versions between and including Directories containing patches that don't meet the above naming convention are applied to all RT versions Directory structures can be nested --- lib/Module/Install/RTx/Runtime.pm | 113 ++++++++++++++++++++++++++++-- t/1-runtime.t | 94 +++++++++++++++++++++++++ 2 files changed, 202 insertions(+), 5 deletions(-) create mode 100644 t/1-runtime.t diff --git a/lib/Module/Install/RTx/Runtime.pm b/lib/Module/Install/RTx/Runtime.pm index 3ee521b..23e2824 100644 --- a/lib/Module/Install/RTx/Runtime.pm +++ b/lib/Module/Install/RTx/Runtime.pm @@ -8,8 +8,105 @@ 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; @@ -63,20 +160,26 @@ sub RTxPatch { _rt_runtime_load(); - my $cmd = "$patch -d $RT::BasePath -p1 < "; + my @cmd = ($patch, '-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 $_; - if ($_ =~ m/.patch/xms) { - WIFEXITED(system($cmd . $_)) - or croak "Couldn't run: $cmd $_ ($?)\n"; + + # 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 { 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; From 9800ee475ea602894b11c96f060cf74f92708440 Mon Sep 17 00:00:00 2001 From: Martin Wheldon Date: Sun, 16 Apr 2017 22:21:30 +0100 Subject: [PATCH 3/3] Added unpatch make target. Enables the removal of patches in the same vane as uninstall --- lib/Module/Install/RTx.pm | 6 +++++- lib/Module/Install/RTx/Runtime.pm | 11 +++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/Module/Install/RTx.pm b/lib/Module/Install/RTx.pm index 3617120..c21d6c3 100644 --- a/lib/Module/Install/RTx.pm +++ b/lib/Module/Install/RTx.pm @@ -188,8 +188,12 @@ 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 ./patches))"\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"); } } diff --git a/lib/Module/Install/RTx/Runtime.pm b/lib/Module/Install/RTx/Runtime.pm index 23e2824..fd94a62 100644 --- a/lib/Module/Install/RTx/Runtime.pm +++ b/lib/Module/Install/RTx/Runtime.pm @@ -156,11 +156,18 @@ sub RTxDatabase { } sub RTxPatch { - my ($patch, $dir) = @_; + my ($patch, $action, $dir) = @_; + my @cmd; _rt_runtime_load(); - my @cmd = ($patch, '-d', $RT::BasePath, '-p1', '-i'); + # 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 {