[Bps-public-commit] RT-Extension-CommandByMail branch master updated. 3.01-8-g4afefe8

BPS Git Server git at git.bestpractical.com
Tue Dec 26 20:03:40 UTC 2023


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "RT-Extension-CommandByMail".

The branch, master has been updated
       via  4afefe852423d3874277a0d2403ff6ba8ba108da (commit)
       via  b271e53db4d8d4468a981fe1dfb3e0c6c937f65c (commit)
       via  e669929908a99b1710df53a6e8ef54a49d7a4d4d (commit)
       via  3555d86b4876674a08e42ce7caa95fbcf7da04ee (commit)
       via  76f6f68fc1be930e899dabc7faecc022cd9dedc1 (commit)
       via  ee0ae3d0175cb626dbf2d50e3984141f1734c9a4 (commit)
       via  67ae57a2f3f4db0e3bfa015e7ac7aed830164ef8 (commit)
       via  e9a90c41f8d4142ea4abdc0700c381aad9d64b4f (commit)
      from  702177074a7d60404bbecb2db8febf2c7be3f250 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 4afefe852423d3874277a0d2403ff6ba8ba108da
Merge: 7021770 b271e53
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Tue Dec 26 15:00:32 2023 -0500

    Merge branch 'add-custom-role-command'


commit b271e53db4d8d4468a981fe1dfb3e0c6c937f65c
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Tue Dec 26 14:59:48 2023 -0500

    Bump rt minimal version to 4.4 where custom roles were added

diff --git a/META.yml b/META.yml
index e97b2dd..b086058 100644
--- a/META.yml
+++ b/META.yml
@@ -31,4 +31,4 @@ resources:
   repository: https://github.com/bestpractical/rt-extension-commandbymail
 version: '3.01'
 x_module_install_rtx_version: '0.43'
-x_requires_rt: 4.0.0
+x_requires_rt: 4.4.0
diff --git a/Makefile.PL b/Makefile.PL
index 8bd1a56..979ed05 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -5,6 +5,7 @@ RTx ('RT-Extension-CommandByMail');
 no_index package => "RT::Extension::CommandByMail::Test";
 build_requires('Test::More');
 build_requires('IPC::Open2');
+requires_rt('4.4.0');
 
 repository('https://github.com/bestpractical/rt-extension-commandbymail');
 
diff --git a/README b/README
index c396158..593c4eb 100644
--- a/README
+++ b/README
@@ -2,7 +2,7 @@ NAME
     RT::Extension::CommandByMail - Change ticket metadata via email
 
 RT VERSION
-    Works with RT 4.0, 4.2, 4.4, 5.0
+    Works with RT 4.4, 5.0
 
 SYNOPSIS
         (Send email with content that looks like the following.)
diff --git a/lib/RT/Extension/CommandByMail.pm b/lib/RT/Extension/CommandByMail.pm
index 7734ae7..ee71696 100644
--- a/lib/RT/Extension/CommandByMail.pm
+++ b/lib/RT/Extension/CommandByMail.pm
@@ -19,7 +19,7 @@ RT::Extension::CommandByMail - Change ticket metadata via email
 
 =head1 RT VERSION
 
-Works with RT 4.0, 4.2, 4.4, 5.0
+Works with RT 4.4, 5.0
 
 =head1 SYNOPSIS
 

commit e669929908a99b1710df53a6e8ef54a49d7a4d4d
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Tue Dec 26 11:37:23 2023 -0500

    Update tests to catch the new "User ... not found" warning

diff --git a/xt/update.t b/xt/update.t
index 77c9d40..36781a5 100644
--- a/xt/update.t
+++ b/xt/update.t
@@ -2,6 +2,7 @@ use strict;
 use warnings;
 
 use RT::Extension::CommandByMail::Test tests => undef;
+use Test::Warn;
 my $test = 'RT::Extension::CommandByMail::Test';
 
 my $test_ticket_id;
@@ -156,9 +157,10 @@ END
 
 
 diag("set watchers on update") if $ENV{'TEST_VERBOSE'};
-foreach my $field ( qw(Requestor Cc AdminCc) ) {
-    my $value = 'test at localhost';
-    my $text = <<END;
+warning_like {
+    foreach my $field (qw(Requestor Cc AdminCc)) {
+        my $value = 'test at localhost';
+        my $text  = <<END;
 Subject: [$RT::rtname #$test_ticket_id] test
 From: root\@localhost
 
@@ -166,14 +168,15 @@ $field: $value
 
 test
 END
-    my (undef, $id) = $test->send_via_mailgate( $text );
-    is($id, $test_ticket_id, "updated ticket");
-    my $obj = RT::Ticket->new( $RT::SystemUser );
-    $obj->Load( $id );
-    is($obj->id, $id, "loaded ticket");
-    my $method = $field .'Addresses';
-    is($obj->$method(), $value, 'set '. $field );
-}
+        my ( undef, $id ) = $test->send_via_mailgate($text);
+        is( $id, $test_ticket_id, "updated ticket" );
+        my $obj = RT::Ticket->new($RT::SystemUser);
+        $obj->Load($id);
+        is( $obj->id, $id, "loaded ticket" );
+        my $method = $field . 'Addresses';
+        is( $obj->$method(), $value, 'set ' . $field );
+    }
+} qr/User 'test\@localhost' not found/;
 
 
 diag("add requestor on update") if $ENV{'TEST_VERBOSE'};

commit 3555d86b4876674a08e42ce7caa95fbcf7da04ee
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date:   Fri Dec 22 17:03:41 2023 -0300

    Update POD with group support for Watchers commands

diff --git a/lib/RT/Extension/CommandByMail.pm b/lib/RT/Extension/CommandByMail.pm
index 63a40aa..7734ae7 100644
--- a/lib/RT/Extension/CommandByMail.pm
+++ b/lib/RT/Extension/CommandByMail.pm
@@ -208,6 +208,8 @@ can be used several times and/or with C<Add> and C<Del> prefixes,
 for example C<Requestor> comand set requestor(s) and the current
 requestors would be deleted, but C<AddRequestor> command adds
 to the current list.
+For groups, you must prefix the group name with C<group:>. For example,
+C<AddAdminCc: group:MyGroupname>.
 
     Requestor: <address> Set requestor(s) using the email address
     AddRequestor: <address> Add new requestor using the email address

commit 76f6f68fc1be930e899dabc7faecc022cd9dedc1
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date:   Fri Dec 22 16:58:35 2023 -0300

    Add full group support to Watchers commands
    
    Previously, the Watchers commands such as AddRequestor, DelCc, etc. would
    only work mainly with users.
    
    We now add full group support to these commands when updating the ticket.

diff --git a/lib/RT/Extension/CommandByMail.pm b/lib/RT/Extension/CommandByMail.pm
index 29bb1e3..63a40aa 100644
--- a/lib/RT/Extension/CommandByMail.pm
+++ b/lib/RT/Extension/CommandByMail.pm
@@ -486,23 +486,66 @@ sub ProcessCommands {
             $results{ $attribute }->{value} = $cmds{ lc $attribute };
         }
 
+
+        # Parses core WATCHERS and Custom Roles related commands
+        # First, add custom roles from this queue to the list of
+        # attributes we are going to parse
+        $custom_roles->LimitToObjectId( $queue->id );
+        my %custom_role_grouptype_to_name;
+        while ( my $custom_role = $custom_roles->Next ) {
+            $custom_role_grouptype_to_name{ $custom_role->GroupType }
+                = $custom_role->Name;
+            push @WATCHER_ATTRIBUTES, $custom_role->GroupType;
+        }
+        # Then, parse the commands
         foreach my $type ( @WATCHER_ATTRIBUTES ) {
-            my %tmp = _ParseAdditiveCommand( \%cmds, 1, $type );
+            my $command_suffix = $type;
+            $command_suffix = "CustomRole{". $custom_role_grouptype_to_name{ $type } ."}"
+                if $type =~ /^RT::CustomRole-/;
+            my %tmp = _ParseAdditiveCommand( \%cmds, 1, $command_suffix );
             next unless keys %tmp;
 
-            $tmp{'Default'} = [ do {
-                my $method = $type;
-                $method .= 's' if $type eq 'Requestor';
-                $args{'Ticket'}->$method->MemberEmailAddresses;
-            } ];
+            # Convert values to ID so we can better compare with the existing
+            # values when we are updating
+            # %tmp can be originally something like
+            #   ( 'Add' => [ 'user1 at example.com', 'group:group1', 'nonexistantuser at example.com' ] )
+            # after _ParseAdditiveCommand, found objects will be converted to
+            # PrincipalId's, so it will be turned into something like the following:
+            #   ( 'Add' => [ 1, 2, 'nonexistantuser at example' ] )
+            _ReplaceUserAndGroupById( \%tmp );
+
+            my $role_group;
+            if ( $type eq 'Requestor' )
+            {
+                $role_group = $ticket_as_user->Requestors;
+            }
+            elsif ( $type =~ /^RT::CustomRole-/ )
+            {
+                $role_group = $ticket_as_user->RoleGroup($type);
+            }
+            else
+            {
+                # AdminCc, Cc
+                $role_group = $ticket_as_user->$type;
+            }
+
+            my $members = $role_group->MembersObj( Recursively => 0 );
+
+            my @res;
+            while ( my $member = $members->Next ) {
+                push @res, $member->MemberId;
+            }
+
+            $tmp{'Default'} = [ @res ];
             my ($add, $del) = _CompileAdditiveForUpdate( %tmp );
+
             foreach my $text ( @$del ) {
-                my $user = RT::User->new($RT::SystemUser);
-                $user->LoadByEmail($text) if $text =~ /\@/;
-                $user->Load($text) unless $user->id;
+                # if we are removing a watcher, it is already has a user
+                # in the system, so emails will not be useful here
+                next if $text =~ /\@/;
                 my ( $val, $msg ) = $ticket_as_user->DeleteWatcher(
                     Type  => $type,
-                    PrincipalId => $user->PrincipalId,
+                    PrincipalId => $text,
                 );
                 push @{ $results{ 'Del'. $type } }, {
                     value   => $text,
@@ -511,15 +554,9 @@ sub ProcessCommands {
                 };
             }
             foreach my $text ( @$add ) {
-                my $user = RT::User->new($RT::SystemUser);
-                $user->LoadByEmail($text) if $text =~ /\@/;
-                $user->Load($text) unless $user->id;
                 my ( $val, $msg ) = $ticket_as_user->AddWatcher(
                     Type  => $type,
-                    $user->id
-                        ? (PrincipalId => $user->PrincipalId)
-                        : (Email => $text)
-                    ,
+                    $text =~ /\D/ ? (Email => $text) : (PrincipalId => $text),
                 );
                 push @{ $results{ 'Add'. $type } }, {
                     value   => $text,
@@ -644,59 +681,6 @@ sub ProcessCommands {
             }
         }
 
-        $custom_roles->LimitToObjectId( $queue->id );
-        while ( my $custom_role = $custom_roles->Next ) {
-            my %tmp = _ParseAdditiveCommand( \%cmds, 0, "CustomRole{". $custom_role->Name ."}" );
-            next unless keys %tmp;
-
-            # Convert values to ID so we can better compare with the existing
-            # values when we are updating
-            # %tmp can be originally something like
-            #   ( 'Add' => [ 'user1 at example.com', 'group:group1', 'nonexistantuser at example.com' ] )
-            # after _ParseAdditiveCommand, found objects will be converted to
-            # PrincipalId's, so it will be turned into something like the following:
-            #   ( 'Add' => [ 1, 2, 'nonexistantuser at example' ] )
-            _ReplaceUserAndGroupById( \%tmp );
-
-            my $role_group = $ticket_as_user->RoleGroup($custom_role->GroupType);
-            my $custom_role_members = $role_group->MembersObj( Recursively => 0 );
-
-            my @res;
-            while ( my $member = $custom_role_members->Next ) {
-                push @res, $member->MemberId;
-            }
-
-            $tmp{'Default'} = [ @res ];
-            my ($add, $del) = _CompileAdditiveForUpdate( %tmp );
-
-            foreach my $text ( @$del ) {
-                # if we are removing a watcher, it is already has a user
-                # in the system, so emails will not be useful here
-                next if $text =~ /\@/;
-                my ( $val, $msg ) = $ticket_as_user->DeleteWatcher(
-                    Type  => $custom_role->GroupType,
-                    PrincipalId => $text,
-                );
-                push @{ $results{ 'Del'. "CustomRole{". $custom_role->Name ."}" } }, {
-                    value   => $text,
-                    result  => $val,
-                    message => $msg
-                };
-            }
-            foreach my $text ( @$add ) {
-                my ( $val, $msg ) = $ticket_as_user->AddWatcher(
-                    Type  => $custom_role->GroupType,
-                    $text =~ /\D/ ? (Email => $text) : (PrincipalId => $text),
-                );
-                push @{ $results{ 'Add'. "CustomRole{". $custom_role->Name ."}" } }, {
-                    value   => $text,
-                    result  => $val,
-                    message => $msg
-                };
-
-            }
-        }
-
         foreach my $attribute (grep $_ eq 'Status', @REGULAR_ATTRIBUTES) {
             next unless defined $cmds{ lc $attribute };
             next if $ticket_as_user->$attribute() eq $cmds{ lc $attribute };

commit ee0ae3d0175cb626dbf2d50e3984141f1734c9a4
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date:   Fri Dec 22 16:58:28 2023 -0300

    Update POD with Custom Role support

diff --git a/README b/README
index 9d178f3..c396158 100644
--- a/README
+++ b/README
@@ -154,10 +154,12 @@ DESCRIPTION
         TimeLeft: <minutes>
 
    Watchers
-    Manage watchers: requestors, ccs and admin ccs. This commands can be
+    Manage watchers: requestors, ccs and admin ccs. These commands can be
     used several times and/or with Add and Del prefixes, for example
     Requestor comand set requestor(s) and the current requestors would be
-    deleted, but AddRequestor command adds to the current list.
+    deleted, but AddRequestor command adds to the current list. For groups,
+    you must prefix the group name with group:. For example, AddAdminCc:
+    group:MyGroupname.
 
         Requestor: <address> Set requestor(s) using the email address
         AddRequestor: <address> Add new requestor using the email address
@@ -169,6 +171,20 @@ DESCRIPTION
         AddAdminCc: <address> Add new AdminCc watcher using the email address
         DelAdminCc: <address> Remove email address as AdminCc watcher
 
+   Custom Roles
+    Manage custom roles of the ticket. These commands can be used several
+    times and/or with Add and Del prefixes. If you have a Custom Role called
+    Customer for example, you can pass the command CustomRole.{Customer} to
+    set the members of that role. You can pass either a username or an email
+    address. For groups, you must prefix the group name with group:. For
+    example, CustomRole.{Customer}: group:MyGroupname.
+
+            CustomRole.{Customer}: set the members of the Customer Custom Role
+            AddCustomRole.{Customer}: add members to the Customer Custom Role
+            DelCustomRole.{Customer}: remove members from the Customer Custom Role
+
+    Replace Customer with the name of your Custom Role.
+
    Links
     Manage links. These commands are also could be used several times in one
     message.
diff --git a/lib/RT/Extension/CommandByMail.pm b/lib/RT/Extension/CommandByMail.pm
index dc5ad47..29bb1e3 100644
--- a/lib/RT/Extension/CommandByMail.pm
+++ b/lib/RT/Extension/CommandByMail.pm
@@ -203,7 +203,7 @@ value.
 
 =head3 Watchers
 
-Manage watchers: requestors, ccs and admin ccs. This commands
+Manage watchers: requestors, ccs and admin ccs. These commands
 can be used several times and/or with C<Add> and C<Del> prefixes,
 for example C<Requestor> comand set requestor(s) and the current
 requestors would be deleted, but C<AddRequestor> command adds
@@ -219,6 +219,22 @@ to the current list.
     AddAdminCc: <address> Add new AdminCc watcher using the email address
     DelAdminCc: <address> Remove email address as AdminCc watcher
 
+=head3 Custom Roles
+
+Manage custom roles of the ticket.
+These commands can be used several times and/or with C<Add> and C<Del>
+prefixes. If you have a Custom Role called C<Customer> for example, you can
+pass the command C<CustomRole.{Customer}> to set the members of that role.
+You can pass either a username or an email address.
+For groups, you must prefix the group name with C<group:>. For example,
+C<CustomRole.{Customer}: group:MyGroupname>.
+
+        CustomRole.{Customer}: set the members of the Customer Custom Role
+        AddCustomRole.{Customer}: add members to the Customer Custom Role
+        DelCustomRole.{Customer}: remove members from the Customer Custom Role
+
+Replace C<Customer> with the name of your Custom Role.
+
 =head3 Links
 
 Manage links. These commands are also could be used several times in one

commit 67ae57a2f3f4db0e3bfa015e7ac7aed830164ef8
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date:   Fri Dec 22 10:15:12 2023 -0300

    Add Custom Role update support
    
    Add new commands that allows do update ticket custom roles:
    - CustomRole
    - AddCustomRole
    - DelCustomRole
    
    Also update minimal version of RT to 5.0.4 since it's required for
    one of the new code blocks.

diff --git a/lib/RT/Extension/CommandByMail.pm b/lib/RT/Extension/CommandByMail.pm
index 88111f5..dc5ad47 100644
--- a/lib/RT/Extension/CommandByMail.pm
+++ b/lib/RT/Extension/CommandByMail.pm
@@ -420,6 +420,14 @@ sub ProcessCommands {
 
     my $transaction;
 
+    # Prepare Custom Roles. We will restrict also later to the ticket
+    # queue or to the creation queue according to the operation we are
+    # doing (create / update)
+    my $custom_roles = RT::CustomRoles->new( $args{'CurrentUser'} );
+    if ( RT::Handle::cmp_version($RT::VERSION, '5.0.4') >= 0 ) {
+        $custom_roles->LimitToLookupType( 'RT::Queue-RT::Ticket' );
+    }
+
     # If we're updating.
     if ( $args{'Ticket'}->id ) {
         $ticket_as_user->Load( $args{'Ticket'}->id );
@@ -620,6 +628,59 @@ sub ProcessCommands {
             }
         }
 
+        $custom_roles->LimitToObjectId( $queue->id );
+        while ( my $custom_role = $custom_roles->Next ) {
+            my %tmp = _ParseAdditiveCommand( \%cmds, 0, "CustomRole{". $custom_role->Name ."}" );
+            next unless keys %tmp;
+
+            # Convert values to ID so we can better compare with the existing
+            # values when we are updating
+            # %tmp can be originally something like
+            #   ( 'Add' => [ 'user1 at example.com', 'group:group1', 'nonexistantuser at example.com' ] )
+            # after _ParseAdditiveCommand, found objects will be converted to
+            # PrincipalId's, so it will be turned into something like the following:
+            #   ( 'Add' => [ 1, 2, 'nonexistantuser at example' ] )
+            _ReplaceUserAndGroupById( \%tmp );
+
+            my $role_group = $ticket_as_user->RoleGroup($custom_role->GroupType);
+            my $custom_role_members = $role_group->MembersObj( Recursively => 0 );
+
+            my @res;
+            while ( my $member = $custom_role_members->Next ) {
+                push @res, $member->MemberId;
+            }
+
+            $tmp{'Default'} = [ @res ];
+            my ($add, $del) = _CompileAdditiveForUpdate( %tmp );
+
+            foreach my $text ( @$del ) {
+                # if we are removing a watcher, it is already has a user
+                # in the system, so emails will not be useful here
+                next if $text =~ /\@/;
+                my ( $val, $msg ) = $ticket_as_user->DeleteWatcher(
+                    Type  => $custom_role->GroupType,
+                    PrincipalId => $text,
+                );
+                push @{ $results{ 'Del'. "CustomRole{". $custom_role->Name ."}" } }, {
+                    value   => $text,
+                    result  => $val,
+                    message => $msg
+                };
+            }
+            foreach my $text ( @$add ) {
+                my ( $val, $msg ) = $ticket_as_user->AddWatcher(
+                    Type  => $custom_role->GroupType,
+                    $text =~ /\D/ ? (Email => $text) : (PrincipalId => $text),
+                );
+                push @{ $results{ 'Add'. "CustomRole{". $custom_role->Name ."}" } }, {
+                    value   => $text,
+                    result  => $val,
+                    message => $msg
+                };
+
+            }
+        }
+
         foreach my $attribute (grep $_ eq 'Status', @REGULAR_ATTRIBUTES) {
             next unless defined $cmds{ lc $attribute };
             next if $ticket_as_user->$attribute() eq $cmds{ lc $attribute };
@@ -681,6 +742,14 @@ sub ProcessCommands {
             $create_args{ 'CustomField-' . $cf->id } = [ _CompileAdditiveForCreate(%tmp) ];
         }
 
+        # Canonicalize custom roles
+        $custom_roles->LimitToObjectId( $queue->id );
+        while ( my $custom_role = $custom_roles->Next ) {
+            my %tmp = _ParseAdditiveCommand( \%cmds, 0, "CustomRole{". $custom_role->Name ."}" );
+            next unless keys %tmp;
+            $create_args{ $custom_role->GroupType } = [ _CompileAdditiveForCreate(%tmp) ];
+        }
+
         # Canonicalize watchers
         # First of all fetch default values
         foreach my $type ( @WATCHER_ATTRIBUTES ) {
@@ -771,6 +840,48 @@ sub ProcessCommands {
              Transaction => $transaction };
 }
 
+sub _ReplaceUserAndGroupById {
+    my $cmds = shift;
+
+    foreach my $key (keys %$cmds) {
+        my @values = @{ $cmds->{$key} };
+        next unless @values;
+
+        my @new_values;
+        # Check each value and see if it can be a user or a group
+        foreach my $value (@values) {
+            if ($value =~ /^group\:(.*)/) {
+                my $group_name = $1;
+                $group_name =~ s/^\s+|\s+$//g;
+
+                my $group = RT::Group->new(RT->SystemUser);
+                $group->LoadUserDefinedGroup($group_name);
+                if ($group->id) {
+                    push @new_values, $group->id;
+                    next;
+                } else {
+                    RT->Logger->error("Group '$1' not found");
+                    next;
+                }
+            }
+            my $user = RT::User->new(RT->SystemUser);
+            $user->LoadByEmail($value) if $value =~ /\@/;
+            $user->Load($value) unless $user->id;
+            if ($user->id) {
+                push @new_values, $user->id;
+                next;
+            } else {
+                RT->Logger->warning("User '$value' not found");
+                next unless $value =~ /\@/;
+            }
+            # If no user or group found, keep the original value in case
+            # it contains an email address
+            push @new_values, $value;
+        }
+        $cmds->{$key} = \@new_values;
+    }
+}
+
 sub _ParseAdditiveCommand {
     my ($cmds, $plural_forms, $base) = @_;
     my (%res);
@@ -871,6 +982,10 @@ sub _CanonicalizeCommand {
     # CustomField commands
     $key =~ s/^(add|del|)c(?:ustom)?-?f(?:ield)?\.?[({\[](.*)[)}\]]$/$1customfield{$2}/i;
     $key =~ s/^(?:transaction|txn)c(?:ustom)?-?f(?:ield)?\.?[({\[](.*)[)}\]]$/transactioncustomfield{$1}/i;
+
+    # CustomRole commands
+    $key =~ s/^(add|del|)c(?:ustom)?-?r(?:ole)?\.?[({\[](.*)[)}\]]$/$1customrole{$2}/i;
+
     return $key;
 }
 
@@ -878,6 +993,7 @@ sub _CheckCommand {
     my ($cmd, $val) = (lc shift, shift);
     return 1 if $cmd =~ /^(add|del|)customfield\{.*\}$/i;
     return 1 if $cmd =~ /^transactioncustomfield\{.*\}$/i;
+    return 1 if $cmd =~ /^(add|del|)customrole\{.*\}$/i;
     if ( grep $cmd eq lc $_, @REGULAR_ATTRIBUTES, @TIME_ATTRIBUTES, @DATE_ATTRIBUTES ) {
         return 1 unless ref $val;
         return (0, "Command '$cmd' doesn't support multiple values");

-----------------------------------------------------------------------

Summary of changes:
 META.yml                          |   6 +-
 Makefile.PL                       |   1 +
 README                            |  22 +++++-
 inc/Module/AutoInstall.pm         |   2 +-
 inc/Module/Install.pm             |   2 +-
 inc/Module/Install/AutoInstall.pm |   2 +-
 inc/Module/Install/Base.pm        |   2 +-
 inc/Module/Install/Can.pm         |   2 +-
 inc/Module/Install/Fetch.pm       |   2 +-
 inc/Module/Install/Include.pm     |   2 +-
 inc/Module/Install/Makefile.pm    |   2 +-
 inc/Module/Install/Metadata.pm    |  12 +--
 inc/Module/Install/RTx.pm         |   4 +-
 inc/Module/Install/Win32.pm       |   2 +-
 inc/Module/Install/WriteAll.pm    |   2 +-
 inc/YAML/Tiny.pm                  |   4 +-
 lib/RT/Extension/CommandByMail.pm | 156 +++++++++++++++++++++++++++++++++-----
 xt/update.t                       |  25 +++---
 18 files changed, 195 insertions(+), 55 deletions(-)


hooks/post-receive
-- 
RT-Extension-CommandByMail


More information about the Bps-public-commit mailing list