[Rt-commit] rt branch, 4.4/dependencies, created. rt-4.4.0-249-g04aa1b6

Alex Vandiver alexmv at bestpractical.com
Sun Jun 5 16:16:14 EDT 2016


The branch, 4.4/dependencies has been created
        at  04aa1b6d6a235da95caf28ab6bec32bede7b67a1 (commit)

- Log -----------------------------------------------------------------
commit c34edacb1859563684001e4c90b344b5490917f6
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 00:29:52 2016 -0700

    Remove duplicate Encode dependency
    
    This duplicate dependency was added (sorted incorrectly) in a
    mis-merge, in 72db35fb.

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 326686c..d445377 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -246,7 +246,6 @@ Mail::Mailer 1.57
 MIME::Entity 5.504
 Module::Refresh 0.03
 Module::Versions::Report 1.05
-Encode 2.64
 Net::CIDR
 Net::IP
 Plack 1.0002

commit 0c3a3106a9b8529376178dc82a4edd5d76d1bf3e
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 00:33:27 2016 -0700

    Sort LWP::Simple correctly
    
    The rest of the list is ASCII-betical, case insensitive.

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index d445377..479c6e9 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -235,12 +235,12 @@ HTTP::Message 6.0
 IPC::Run3
 JavaScript::Minifier::XS
 JSON
-LWP::Simple
 List::MoreUtils
 Locale::Maketext 1.06
 Locale::Maketext::Fuzzy 0.11
 Locale::Maketext::Lexicon 0.32
 Log::Dispatch 2.30
+LWP::Simple
 Mail::Header 2.12
 Mail::Mailer 1.57
 MIME::Entity 5.504

commit bbb5c536f120379aec680b80b2c7fdf399af848a
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 00:38:00 2016 -0700

    Fold in core dependencies that cannot be disabled
    
    Since the GetOpt options are not specified as booleans, they cannot
    express any value except true.  They thhus cannot ever be disabled, so
    their existance as command-line arguments, and separate depdency
    stanzas, is pointless.
    
    Merge their dependencies into the CORE list, but leave the options as
    valid (but explictly no-ops) for backwards compatibility.

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 479c6e9..b41f9d9 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -71,11 +71,8 @@ GetOptions(
     'with-DEVELOPER',
 
     'with-GPG',
-    'with-ICAL',
     'with-GRAPHVIZ',
     'with-GD',
-    'with-DASHBOARDS',
-    'with-USERLOGO',
     'with-HTML-DOC',
     'with-EXTERNALAUTH',
 
@@ -84,6 +81,9 @@ GetOptions(
     'list-deps',
     'siteinstall!',
     'help|h',
+
+    # No-ops, for back-compat
+    'with-ICAL', 'with-DASHBOARDS', 'with-USERLOGO',
 );
 
 if ( $args{help} ) {
@@ -100,11 +100,8 @@ my %default = (
     'with-DEVELOPER'  => @RT_DEVELOPER@,
     'with-GPG'        => @RT_GPG_DEPS@,
     'with-SMIME'      => @RT_SMIME_DEPS@,
-    'with-ICAL'       => 1,
     'with-GRAPHVIZ'   => @RT_GRAPHVIZ@,
     'with-GD'         => @RT_GD@,
-    'with-DASHBOARDS' => 1,
-    'with-USERLOGO'   => 1,
     'with-HTML-DOC'   => @RT_DEVELOPER@,
     'with-EXTERNALAUTH' => @RT_EXTERNALAUTH@,
     'with-S3'         => (uc(q{@ATTACHMENT_STORE@}) eq 'S3'),
@@ -198,10 +195,12 @@ CGI::Cookie 1.20
 CGI::Emulate::PSGI
 CGI::PSGI 0.12
 Class::Accessor::Fast
+Convert::Color
 Crypt::Eksblowfish
 CSS::Minifier::XS
 CSS::Squish 0.06
 Data::GUID
+Data::ICal
 Data::Page::Pageset
 Date::Extract 0.02
 Date::Manip
@@ -244,6 +243,7 @@ LWP::Simple
 Mail::Header 2.12
 Mail::Mailer 1.57
 MIME::Entity 5.504
+MIME::Types
 Module::Refresh 0.03
 Module::Versions::Report 1.05
 Net::CIDR
@@ -269,6 +269,8 @@ Time::HiRes
 Time::ParseDate
 Tree::Simple 1.04
 UNIVERSAL::require
+URI 1.59
+URI::QueryParam
 XML::RSS 1.05
 .
 set_dep( CORE => 'Symbol::Global::Name' => 0.05 ) if $] >= 5.019003;
@@ -356,16 +358,6 @@ File::Which
 String::ShellQuote
 .
 
-$deps{'ICAL'} = [ text_to_hash( << '.') ];
-Data::ICal
-.
-
-$deps{'DASHBOARDS'} = [ text_to_hash( << '.') ];
-MIME::Types
-URI 1.59
-URI::QueryParam
-.
-
 $deps{'GRAPHVIZ'} = [ text_to_hash( << '.') ];
 GraphViz
 IPC::Run 0.90
@@ -377,10 +369,6 @@ GD::Graph 1.47
 GD::Text
 .
 
-$deps{'USERLOGO'} = [ text_to_hash( << '.') ];
-Convert::Color
-.
-
 $deps{'HTML-DOC'} = [ text_to_hash( <<'.') ];
 HTML::Entities
 Pod::Simple 3.24

commit e9ed2a8ffb0dfd6964cfa4bde31a7beb0108b495
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 00:52:44 2016 -0700

    Fold in --with-html-doc into developer dependencies
    
    While this removes a valid argument which could be being passed to
    rt-test-dependencies, it definitionally affects only developers.

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index b41f9d9..7c27d87 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -73,7 +73,6 @@ GetOptions(
     'with-GPG',
     'with-GRAPHVIZ',
     'with-GD',
-    'with-HTML-DOC',
     'with-EXTERNALAUTH',
 
     'with-S3', 'with-DROPBOX',
@@ -102,7 +101,6 @@ my %default = (
     'with-SMIME'      => @RT_SMIME_DEPS@,
     'with-GRAPHVIZ'   => @RT_GRAPHVIZ@,
     'with-GD'         => @RT_GD@,
-    'with-HTML-DOC'   => @RT_DEVELOPER@,
     'with-EXTERNALAUTH' => @RT_EXTERNALAUTH@,
     'with-S3'         => (uc(q{@ATTACHMENT_STORE@}) eq 'S3'),
     'with-DROPBOX'    => (uc(q{@ATTACHMENT_STORE@}) eq 'DROPBOX'),
@@ -299,10 +297,12 @@ $deps{'DEVELOPER'} = [ text_to_hash( << '.') ];
 Email::Abstract
 File::Find
 File::Which
+HTML::Entities
 Locale::PO
 Log::Dispatch::Perl
 Mojo::DOM
 Plack::Middleware::Test::StashWarnings 0.08
+Pod::Simple 3.24
 Set::Tiny
 String::ShellQuote 0 # needed for gnupg-incoming.t
 Test::Builder 0.90 # needed for is_passing
@@ -369,11 +369,6 @@ GD::Graph 1.47
 GD::Text
 .
 
-$deps{'HTML-DOC'} = [ text_to_hash( <<'.') ];
-HTML::Entities
-Pod::Simple 3.24
-.
-
 $deps{'EXTERNALAUTH'} = [ text_to_hash( <<'.') ];
 Net::SSLeay
 Net::LDAP

commit 5520a80b9a2cf01f46bb912951b3da348d31cd84
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 00:55:08 2016 -0700

    Only add the externalauth test dependency for developers
    
    There is no need to add the externalauth testing dependency if
    developer mode has not been enabled.

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 7c27d87..f4016f2 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -107,6 +107,8 @@ my %default = (
 );
 $args{$_} = $default{$_} foreach grep !exists $args{$_}, keys %default;
 
+$args{'with-EXTERNALAUTH-TESTS'} = $args{'with-EXTERNALAUTH'} && $args{'with-DEVELOPER'};
+
 {
   my $section;
   my %always_show_sections = (
@@ -372,6 +374,9 @@ GD::Text
 $deps{'EXTERNALAUTH'} = [ text_to_hash( <<'.') ];
 Net::SSLeay
 Net::LDAP
+.
+
+$deps{'EXTERNALAUTH-TESTS'} = [ text_to_hash( <<'.') ];
 Net::LDAP::Server::Test
 .
 

commit 6e40017914afbddf227dff6073c989b59761d2a7
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 00:56:51 2016 -0700

    Remove the last vestiges of --download
    
    9b277db9 missed removing this stanza in its purging of --download

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index f4016f2..fd3bca7 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -394,11 +394,6 @@ my %AVOID = (
     'DateTime::Locale' => [qw(1.00 1.01)]
 );
 
-if ($args{'download'}) {
-    download_mods();
-}
-
-
 check_perl_version();
 
 check_users();

commit 63e7b521f012f4f59e4288cef35598b58aab4a06
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 01:26:31 2016 -0700

    Improve documentation

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index fd3bca7..4ed8a74 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -622,65 +622,96 @@ rt-test-dependencies - test rt's dependencies
 
 =head1 DESCRIPTION
 
-by default, C<rt-test-dependencies> determines whether you have installed all
-the perl modules RT needs to run.
+By default, C<rt-test-dependencies> determines whether you have
+installed all the perl modules RT needs to run.
 
-the "RT_FIX_DEPS_CMD" environment variable, if set, will be used instead of
-the standard CPAN shell by --install to install any required modules.  it will
-be called with the module name, or, if "RT_FIX_DEPS_CMD" contains a "%s", will
-replace the "%s" with the module name before calling the program.
+With B<--install>, it attempts to install any missing dependencies.
+If the C<RT_FIX_DEPS_CMD> environment variable is set, it will be used
+instead of the standard CPAN shell to install any required modules.
+The command will be called with the module to install -- or, if
+C<RT_FIX_DEPS_CMD> contains a C<%s>, will replace the C<%s> with the
+module name before calling the program.
 
 =head1 OPTIONS
 
+=head2 General options
+
 =over
 
-=item install
+=item B<--install>
+
+Attempt to install missing modules
 
-    install missing modules
+=item B<--verbose> or B<-v>
 
-=item verbose
+List the status of all dependencies, rather than just the missing ones.
 
-list the status of all dependencies, rather than just the missing ones.
+=item B<--siteinstall> / B<--no-siteinstall>
 
--v is equal to --verbose
+By default, RT detects if you are running a version of Perl prior to
+5.11, which has been patched by your distribution to alter the search
+order for modules.  In such cases, C<--install> attempts to install
+modules into the right place such that they cannot be accidentally
+downgraded by the distribution.  Use B<--siteinstall> to force this
+behavior, or B<--no-siteinstall> to prohibit it.  These options have
+no effect when used with Perl 5.11 or above.
+
+=back
 
-=item specify dependencies
+=head2 Configuration options
 
 =over
 
-=item --with-mysql
+=item B<--with-mysql>
 
-database interface for mysql
+=item B<--with-pg>
 
-=item --with-pg
+=item B<--with-oracle>
 
-database interface for postgresql
+=item B<--with-sqlite>
 
-=item --with-oracle
+These configure which backend database to add depenencies for.
 
-database interface for oracle
 
-=item --with-sqlite
+=item B<--with-fastcgi>
 
-database interface and driver for sqlite (unsupported)
+=item B<--with-modperl1>
 
-=item --with-fastcgi
+=item B<--with-modperl2>
 
-libraries needed to support the fastcgi handler
+These configure which interface between the webserver and RT to add
+dependencies for.
 
-=item --with-modperl1
 
-libraries needed to support the modperl 1 handler
+=item B<--with-developer>
 
-=item --with-modperl2
+Add dependencies needed to develop RT and run its tests.
 
-libraries needed to support the modperl 2 handler
 
-=item --with-developer
+=item B<--with-gpg>
 
-tools needed for RT development
+Add dependencies for GPG encryption and decryption of email.
 
-=back
+=item B<--with-graphviz>
+
+Add dependencies for visualizing dependencies between tickets.
+
+=item B<--with-gd>
+
+Add dependencies for creating charts and graphs from search results.
+
+=item B<--with-externalauth>
+
+Add dependencies to integrating with LDAP and other external
+authentication sources.
+
+=item B<--with-s3>
+
+Add dependencies for storing large attachments in Amazon S3.
+
+=item B<--with-dropbox>
+
+Add dependencies for storing large attachments in Dropbox.
 
 =back
 

commit f96565476273d307b0c429c671699f90c93df224
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 01:31:52 2016 -0700

    Move functions down

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 4ed8a74..d5fcc5e 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -109,83 +109,6 @@ $args{$_} = $default{$_} foreach grep !exists $args{$_}, keys %default;
 
 $args{'with-EXTERNALAUTH-TESTS'} = $args{'with-EXTERNALAUTH'} && $args{'with-DEVELOPER'};
 
-{
-  my $section;
-  my %always_show_sections = (
-    perl => 1,
-    users => 1,
-  );
-
-  sub section {
-    my $s = shift;
-    $section = $s;
-    print "$s:\n" unless $args{'list-deps'};
-  }
-
-  sub print_found {
-    my $msg = shift;
-    my $test = shift;
-    my $extra = shift;
-
-    unless ( $args{'list-deps'} ) {
-        if ( $args{'v'} or not $test or $always_show_sections{$section} ) {
-            print "\t$msg ...";
-            print $test ? "found" : "MISSING";
-            print "\n";
-        }
-
-        print "\t\t$extra\n" if defined $extra;
-    }
-  }
-}
-
-sub conclude {
-    my %missing_by_type = @_;
-
-    unless ( $args{'list-deps'} ) {
-        unless ( keys %missing_by_type ) {
-            print "\nAll dependencies have been found.\n";
-            return;
-        }
-
-        print "\nSOME DEPENDENCIES WERE MISSING.\n";
-
-        for my $type ( keys %missing_by_type ) {
-            my $missing = $missing_by_type{$type};
-
-            print "$type missing dependencies:\n";
-            for my $name ( keys %$missing ) {
-                my $module  = $missing->{$name};
-                my $version = $module->{version};
-                my $error = $module->{error};
-                print_found( $name . ( $version && !$error ? " >= $version" : "" ),
-                    0, $module->{error} );
-            }
-        }
-
-        print "\nPerl library path for @PERL@:\n";
-        print "    $_\n" for @INC;
-
-        exit 1;
-    }
-}
-
-sub text_to_hash {
-    my %hash;
-    for my $line ( split /\n/, $_[0] ) {
-        my($key, $value) = $line =~ /(\S+)\s*(\S*)/;
-        $value ||= '';
-        $hash{$key} = $value;
-    }
-
-    return %hash;
-}
-sub set_dep {
-    my ($name, $module, $version) = @_;
-    my %list = @{$deps{$name}};
-    $list{$module} = ($version || '');
-    $deps{$name} = [ %list ];
-}
 
 $deps{'CORE'} = [ text_to_hash( << '.') ];
 Apache::Session 1.53
@@ -438,6 +361,84 @@ else {
     conclude(%Missing_By_Type);
 }
 
+{
+  my $section;
+  my %always_show_sections = (
+    perl => 1,
+    users => 1,
+  );
+
+  sub section {
+    my $s = shift;
+    $section = $s;
+    print "$s:\n" unless $args{'list-deps'};
+  }
+
+  sub print_found {
+    my $msg = shift;
+    my $test = shift;
+    my $extra = shift;
+
+    unless ( $args{'list-deps'} ) {
+        if ( $args{'v'} or not $test or $always_show_sections{$section} ) {
+            print "\t$msg ...";
+            print $test ? "found" : "MISSING";
+            print "\n";
+        }
+
+        print "\t\t$extra\n" if defined $extra;
+    }
+  }
+}
+
+sub conclude {
+    my %missing_by_type = @_;
+
+    unless ( $args{'list-deps'} ) {
+        unless ( keys %missing_by_type ) {
+            print "\nAll dependencies have been found.\n";
+            return;
+        }
+
+        print "\nSOME DEPENDENCIES WERE MISSING.\n";
+
+        for my $type ( keys %missing_by_type ) {
+            my $missing = $missing_by_type{$type};
+
+            print "$type missing dependencies:\n";
+            for my $name ( keys %$missing ) {
+                my $module  = $missing->{$name};
+                my $version = $module->{version};
+                my $error = $module->{error};
+                print_found( $name . ( $version && !$error ? " >= $version" : "" ),
+                    0, $module->{error} );
+            }
+        }
+
+        print "\nPerl library path for @PERL@:\n";
+        print "    $_\n" for @INC;
+
+        exit 1;
+    }
+}
+
+sub text_to_hash {
+    my %hash;
+    for my $line ( split /\n/, $_[0] ) {
+        my($key, $value) = $line =~ /(\S+)\s*(\S*)/;
+        $value ||= '';
+        $hash{$key} = $value;
+    }
+
+    return %hash;
+}
+sub set_dep {
+    my ($name, $module, $version) = @_;
+    my %list = @{$deps{$name}};
+    $list{$module} = ($version || '');
+    $deps{$name} = [ %list ];
+}
+
 sub test_deps {
     my @deps = @_;
 

commit 8f787650da063092024e7c72b18b90ecfb874120
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 01:37:58 2016 -0700

    perltidy

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index d5fcc5e..5685377 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -93,22 +93,22 @@ if ( $args{help} ) {
 
 # Set up defaults
 my %default = (
-    'with-CORE'       => 1,
-    'with-CLI'        => 1,
-    'with-MAILGATE'   => 1,
-    'with-DEVELOPER'  => @RT_DEVELOPER@,
-    'with-GPG'        => @RT_GPG_DEPS@,
-    'with-SMIME'      => @RT_SMIME_DEPS@,
-    'with-GRAPHVIZ'   => @RT_GRAPHVIZ@,
-    'with-GD'         => @RT_GD@,
+    'with-CORE'         => 1,
+    'with-CLI'          => 1,
+    'with-MAILGATE'     => 1,
+    'with-DEVELOPER'    => @RT_DEVELOPER@,
+    'with-GPG'          => @RT_GPG_DEPS@,
+    'with-SMIME'        => @RT_SMIME_DEPS@,
+    'with-GRAPHVIZ'     => @RT_GRAPHVIZ@,
+    'with-GD'           => @RT_GD@,
     'with-EXTERNALAUTH' => @RT_EXTERNALAUTH@,
-    'with-S3'         => (uc(q{@ATTACHMENT_STORE@}) eq 'S3'),
-    'with-DROPBOX'    => (uc(q{@ATTACHMENT_STORE@}) eq 'DROPBOX'),
+    'with-S3'           => (uc(q{@ATTACHMENT_STORE@}) eq 'S3'),
+    'with-DROPBOX'      => (uc(q{@ATTACHMENT_STORE@}) eq 'DROPBOX'),
 );
-$args{$_} = $default{$_} foreach grep !exists $args{$_}, keys %default;
-
-$args{'with-EXTERNALAUTH-TESTS'} = $args{'with-EXTERNALAUTH'} && $args{'with-DEVELOPER'};
+$args{$_} = $default{$_} foreach grep {!exists $args{$_}} keys %default;
 
+$args{'with-EXTERNALAUTH-TESTS'}
+    = $args{'with-EXTERNALAUTH'} && $args{'with-DEVELOPER'};
 
 $deps{'CORE'} = [ text_to_hash( << '.') ];
 Apache::Session 1.53
@@ -197,7 +197,7 @@ URI::QueryParam
 XML::RSS 1.05
 .
 set_dep( CORE => 'Symbol::Global::Name' => 0.05 ) if $] >= 5.019003;
-set_dep( CORE => CGI => 4.00 )                    if $] > 5.019003;
+set_dep( CORE => CGI => 4.00 ) if $] > 5.019003;
 
 $deps{'MAILGATE'} = [ text_to_hash( << '.') ];
 Crypt::SSLeay
@@ -312,9 +312,9 @@ File::Dropbox
 .
 
 my %AVOID = (
-    'DBD::Oracle' => [qw(1.23)],
+    'DBD::Oracle'       => [qw(1.23)],
     'Devel::StackTrace' => [qw(1.28 1.29)],
-    'DateTime::Locale' => [qw(1.00 1.01)]
+    'DateTime::Locale'  => [qw(1.00 1.01)]
 );
 
 check_perl_version();
@@ -322,8 +322,8 @@ check_perl_version();
 check_users();
 
 my %Missing_By_Type = ();
-foreach my $type (sort grep $args{$_}, keys %args) {
-    next unless ($type =~ /^with-(.*?)$/) and $deps{$1};
+foreach my $type ( sort grep {$args{$_}} keys %args ) {
+    next unless ( $type =~ /^with-(.*?)$/ ) and $deps{$1};
 
     $type = $1;
     section("$type dependencies");
@@ -334,8 +334,8 @@ foreach my $type (sort grep $args{$_}, keys %args) {
     my %missing = test_deps(@deps);
 
     if ( $args{'install'} ) {
-        for my $module (keys %missing) {
-            resolve_dep($module, $missing{$module}{version});
+        for my $module ( keys %missing ) {
+            resolve_dep( $module, $missing{$module}{version} );
             my $m = $module . '.pm';
             $m =~ s!::!/!g;
             if ( delete $INC{$m} ) {
@@ -347,7 +347,7 @@ foreach my $type (sort grep $args{$_}, keys %args) {
                 }
             }
             delete $missing{$module}
-                if test_dep($module, $missing{$module}{version}, $AVOID{$module});
+                if test_dep( $module, $missing{$module}{version}, $AVOID{$module} );
         }
     }
 
@@ -355,40 +355,40 @@ foreach my $type (sort grep $args{$_}, keys %args) {
 }
 
 if ( $args{'install'} && keys %Missing_By_Type ) {
-    exec($script_path, @orig_argv, '--no-install');
-}
-else {
+    exec( $script_path, @orig_argv, '--no-install' );
+} else {
     conclude(%Missing_By_Type);
 }
 
 {
-  my $section;
-  my %always_show_sections = (
-    perl => 1,
-    users => 1,
-  );
-
-  sub section {
-    my $s = shift;
-    $section = $s;
-    print "$s:\n" unless $args{'list-deps'};
-  }
-
-  sub print_found {
-    my $msg = shift;
-    my $test = shift;
-    my $extra = shift;
+    my $section;
+    my %always_show_sections = (
+        perl  => 1,
+        users => 1,
+    );
+
+    sub section {
+        my $s = shift;
+        $section = $s;
+        print "$s:\n" unless $args{'list-deps'};
+    }
 
-    unless ( $args{'list-deps'} ) {
-        if ( $args{'v'} or not $test or $always_show_sections{$section} ) {
-            print "\t$msg ...";
-            print $test ? "found" : "MISSING";
-            print "\n";
-        }
+    sub print_found {
+        my $msg   = shift;
+        my $test  = shift;
+        my $extra = shift;
+
+        unless ( $args{'list-deps'} ) {
+            if ( $args{'v'} or not $test or $always_show_sections{$section} )
+            {
+                print "\t$msg ...";
+                print $test ? "found" : "MISSING";
+                print "\n";
+            }
 
-        print "\t\t$extra\n" if defined $extra;
+            print "\t\t$extra\n" if defined $extra;
+        }
     }
-  }
 }
 
 sub conclude {
@@ -409,8 +409,9 @@ sub conclude {
             for my $name ( keys %$missing ) {
                 my $module  = $missing->{$name};
                 my $version = $module->{version};
-                my $error = $module->{error};
-                print_found( $name . ( $version && !$error ? " >= $version" : "" ),
+                my $error   = $module->{error};
+                print_found(
+                    $name . ( $version && !$error ? " >= $version" : "" ),
                     0, $module->{error} );
             }
         }
@@ -425,46 +426,47 @@ sub conclude {
 sub text_to_hash {
     my %hash;
     for my $line ( split /\n/, $_[0] ) {
-        my($key, $value) = $line =~ /(\S+)\s*(\S*)/;
+        my ( $key, $value ) = $line =~ /(\S+)\s*(\S*)/;
         $value ||= '';
         $hash{$key} = $value;
     }
 
     return %hash;
 }
+
 sub set_dep {
-    my ($name, $module, $version) = @_;
-    my %list = @{$deps{$name}};
-    $list{$module} = ($version || '');
-    $deps{$name} = [ %list ];
+    my ( $name, $module, $version ) = @_;
+    my %list = @{ $deps{$name} };
+    $list{$module} = ( $version || '' );
+    $deps{$name} = [%list];
 }
 
 sub test_deps {
     my @deps = @_;
 
     my %missing;
-    while(@deps) {
-        my $module = shift @deps;
+    while (@deps) {
+        my $module  = shift @deps;
         my $version = shift @deps;
-        my($test, $error) = test_dep($module, $version, $AVOID{$module});
-        my $msg = $module . ($version && !$error ? " >= $version" : '');
-        print_found($msg, $test, $error);
+        my ( $test, $error ) = test_dep( $module, $version, $AVOID{$module} );
+        my $msg = $module . ( $version && !$error ? " >= $version" : '' );
+        print_found( $msg, $test, $error );
 
-        $missing{$module} = { version => $version, error => $error } unless $test;
+        $missing{$module} = { version => $version, error => $error }
+            unless $test;
     }
 
     return %missing;
 }
 
 sub test_dep {
-    my $module = shift;
+    my $module  = shift;
     my $version = shift;
-    my $avoid = shift;
+    my $avoid   = shift;
 
     if ( $args{'list-deps'} ) {
-        print $module, ': ', $version || 0, "\n"; 
-    }
-    else {
+        print $module, ': ', $version || 0, "\n";
+    } else {
         no warnings 'deprecated';
         eval "{ local \$ENV{__WARN__}; use $module $version () }";
         if ( my $error = $@ ) {
@@ -476,16 +478,20 @@ sub test_dep {
 
             my $path = $module;
             $path =~ s{::}{/}g;
-            undef $error if defined $error and $error =~ /^Can't locate $path\.pm in \@INC/;
+            undef $error
+                if defined $error
+                and $error =~ /^Can't locate $path\.pm in \@INC/;
 
             return ( 0, $error );
         }
-        
-        if ( $avoid ) {
+
+        if ($avoid) {
             my $version = $module->VERSION;
-            if ( grep $version eq $_, @$avoid ) {
+            if ( grep {$version eq $_} @$avoid ) {
                 return 0 unless wantarray;
-                return (0, "It's known that there are problems with RT and version '$version' of '$module' module. If it's the latest available version of the module then you have to downgrade manually.");
+                return ( 0,
+                    "It's known that there are problems with RT and version '$version' of '$module' module. If it's the latest available version of the module then you have to downgrade manually."
+                );
             }
         }
 
@@ -494,18 +500,23 @@ sub test_dep {
 }
 
 sub resolve_dep {
-    my $module = shift;
+    my $module  = shift;
     my $version = shift;
 
-    unless (defined $args{siteinstall}) {
+    unless ( defined $args{siteinstall} ) {
         require Config;
         my %uniq;
-        my @order = grep {($_ eq $Config::Config{sitelibexp}
-                        or $_ eq $Config::Config{privlibexp})
-                        and not $uniq{$_}++} @INC;
-        if ($] < 5.011 and @order == 2
-                and $order[0] eq $Config::Config{sitelibexp}
-                and $order[1] eq $Config::Config{privlibexp}) {
+        my @order = grep {
+            (          $_ eq $Config::Config{sitelibexp}
+                    or $_ eq $Config::Config{privlibexp}
+                )
+                and not $uniq{$_}++
+        } @INC;
+        if (    $] < 5.011
+            and @order == 2
+            and $order[0] eq $Config::Config{sitelibexp}
+            and $order[1] eq $Config::Config{privlibexp} )
+        {
 
             print "\n";
             print "Patched perl, with site_perl before core in \@INC, detected.\n";
@@ -521,16 +532,17 @@ sub resolve_dep {
     print "\nInstall module $module\n";
 
     my $ext = $ENV{'RT_FIX_DEPS_CMD'} || $ENV{'PERL_PREFER_CPAN_CLIENT'};
-    unless( $ext ) {
+    unless ($ext) {
         my $configured = 1;
         {
             local @INC = @INC;
             if ( $ENV{'HOME'} ) {
                 unshift @INC, "$ENV{'HOME'}/.cpan";
             }
-            $configured = eval { require CPAN::MyConfig } || eval { require CPAN::Config };
+            $configured = eval { require CPAN::MyConfig }
+                || eval { require CPAN::Config };
         }
-        unless ( $configured ) {
+        unless ($configured) {
             print <<END;
 You haven't configured the CPAN shell yet.
 Please run `@PERL@ -MCPAN -e shell` to configure it.
@@ -577,8 +589,8 @@ END
         exit(1);
     }
 
-    if( $ext =~ /\%s/) {
-        $ext =~ s/\%s/$module/g; # sprintf( $ext, $module );
+    if ( $ext =~ /\%s/ ) {
+        $ext =~ s/\%s/$module/g;    # sprintf( $ext, $module );
     } else {
         $ext .= " $module";
     }
@@ -587,24 +599,29 @@ END
 }
 
 sub check_perl_version {
-  section("perl");
-  eval {require 5.010_001};
-  if ($@) {
-    print_found("5.10.1", 0, sprintf("RT requires Perl v5.10.1 or newer. Your current Perl is v%vd", $^V));
-    exit(1);
-  } else {
-    print_found( sprintf(">=5.10.1(%vd)", $^V), 1 );
-  }
+    section("perl");
+    eval { require 5.010_001 };
+    if ($@) {
+        print_found(
+            "5.10.1", 0,
+            sprintf(
+                "RT requires Perl v5.10.1 or newer. Your current Perl is v%vd",
+                $^V )
+        );
+        exit(1);
+    } else {
+        print_found( sprintf( ">=5.10.1(%vd)", $^V ), 1 );
+    }
 }
 
 sub check_users {
-  section("users");
-  print_found("rt group (@RTGROUP@)",      defined getgrnam("@RTGROUP@"));
-  print_found("bin owner (@BIN_OWNER@)",   defined getpwnam("@BIN_OWNER@"));
-  print_found("libs owner (@LIBS_OWNER@)", defined getpwnam("@LIBS_OWNER@"));
-  print_found("libs group (@LIBS_GROUP@)", defined getgrnam("@LIBS_GROUP@"));
-  print_found("web owner (@WEB_USER@)",    defined getpwnam("@WEB_USER@"));
-  print_found("web group (@WEB_GROUP@)",   defined getgrnam("@WEB_GROUP@"));
+    section("users");
+    print_found( "rt group (@RTGROUP@)",      defined getgrnam("@RTGROUP@") );
+    print_found( "bin owner (@BIN_OWNER@)",   defined getpwnam("@BIN_OWNER@") );
+    print_found( "libs owner (@LIBS_OWNER@)", defined getpwnam("@LIBS_OWNER@") );
+    print_found( "libs group (@LIBS_GROUP@)", defined getgrnam("@LIBS_GROUP@") );
+    print_found( "web owner (@WEB_USER@)",    defined getpwnam("@WEB_USER@") );
+    print_found( "web group (@WEB_GROUP@)",   defined getgrnam("@WEB_GROUP@") );
 }
 
 1;

commit 5186ca27205c6a5905c779db2ea0099172490f0b
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 01:43:19 2016 -0700

    Make --verbose a no-op; it is always passed by the makefile

diff --git a/Makefile.in b/Makefile.in
index 4ca9d0a..4efc2ee 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -266,12 +266,12 @@ upgrade: testdeps config-install dirs files-install fixperms upgrade-instruct
 
 my_with_web_handlers= $(shell $(PERL) -e 'print join " ", map "--with-$$_", grep defined && length, split /,/, "$(WEB_HANDLER)"')
 testdeps:
-	$(PERL) ./sbin/rt-test-dependencies --verbose --with-$(DB_TYPE) $(my_with_web_handlers)
+	$(PERL) ./sbin/rt-test-dependencies --with-$(DB_TYPE) $(my_with_web_handlers)
 
 depends: fixdeps
 
 fixdeps:
-	$(PERL) ./sbin/rt-test-dependencies --verbose --install --with-$(DB_TYPE) $(my_with_web_handlers)
+	$(PERL) ./sbin/rt-test-dependencies --install --with-$(DB_TYPE) $(my_with_web_handlers)
 
 #}}}
 
diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 5685377..333342c 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -63,7 +63,7 @@ my @orig_argv = @ARGV;
 my $script_path = abs_path($0);
 
 GetOptions(
-    \%args,                               'v|verbose',
+    \%args,
     'install!',
     'with-MYSQL', 'with-PG', 'with-SQLITE', 'with-ORACLE',
     'with-FASTCGI', 'with-MODPERL1', 'with-MODPERL2', 'with-STANDALONE',
@@ -82,7 +82,7 @@ GetOptions(
     'help|h',
 
     # No-ops, for back-compat
-    'with-ICAL', 'with-DASHBOARDS', 'with-USERLOGO',
+    'v|verbose', 'with-ICAL', 'with-DASHBOARDS', 'with-USERLOGO',
 );
 
 if ( $args{help} ) {
@@ -360,34 +360,22 @@ if ( $args{'install'} && keys %Missing_By_Type ) {
     conclude(%Missing_By_Type);
 }
 
-{
-    my $section;
-    my %always_show_sections = (
-        perl  => 1,
-        users => 1,
-    );
-
-    sub section {
-        my $s = shift;
-        $section = $s;
-        print "$s:\n" unless $args{'list-deps'};
-    }
+sub section {
+    my $s = shift;
+    print "$s:\n" unless $args{'list-deps'};
+}
 
-    sub print_found {
-        my $msg   = shift;
-        my $test  = shift;
-        my $extra = shift;
-
-        unless ( $args{'list-deps'} ) {
-            if ( $args{'v'} or not $test or $always_show_sections{$section} )
-            {
-                print "\t$msg ...";
-                print $test ? "found" : "MISSING";
-                print "\n";
-            }
+sub print_found {
+    my $msg   = shift;
+    my $test  = shift;
+    my $extra = shift;
 
-            print "\t\t$extra\n" if defined $extra;
-        }
+    unless ( $args{'list-deps'} ) {
+        print "\t$msg ...";
+        print $test ? "found" : "MISSING";
+        print "\n";
+
+        print "\t\t$extra\n" if defined $extra;
     }
 }
 
@@ -660,10 +648,6 @@ module name before calling the program.
 
 Attempt to install missing modules
 
-=item B<--verbose> or B<-v>
-
-List the status of all dependencies, rather than just the missing ones.
-
 =item B<--siteinstall> / B<--no-siteinstall>
 
 By default, RT detects if you are running a version of Perl prior to

commit c226d8dbd8efae7632fd3553241f7470414886f6
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 02:17:47 2016 -0700

    Remove --list-deps; it is undocumented and unuseful
    
    When it was added in 8190e316, it was "to make _require.yml" Such a
    file is not part of any modern or known toolchain.

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 333342c..f448319 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -77,7 +77,6 @@ GetOptions(
 
     'with-S3', 'with-DROPBOX',
 
-    'list-deps',
     'siteinstall!',
     'help|h',
 
@@ -362,7 +361,7 @@ if ( $args{'install'} && keys %Missing_By_Type ) {
 
 sub section {
     my $s = shift;
-    print "$s:\n" unless $args{'list-deps'};
+    print "$s:\n";
 }
 
 sub print_found {
@@ -370,45 +369,41 @@ sub print_found {
     my $test  = shift;
     my $extra = shift;
 
-    unless ( $args{'list-deps'} ) {
-        print "\t$msg ...";
-        print $test ? "found" : "MISSING";
-        print "\n";
+    print "\t$msg ...";
+    print $test ? "found" : "MISSING";
+    print "\n";
 
-        print "\t\t$extra\n" if defined $extra;
-    }
+    print "\t\t$extra\n" if defined $extra;
 }
 
 sub conclude {
     my %missing_by_type = @_;
 
-    unless ( $args{'list-deps'} ) {
-        unless ( keys %missing_by_type ) {
-            print "\nAll dependencies have been found.\n";
-            return;
-        }
+    unless ( keys %missing_by_type ) {
+        print "\nAll dependencies have been found.\n";
+        return;
+    }
 
-        print "\nSOME DEPENDENCIES WERE MISSING.\n";
+    print "\nSOME DEPENDENCIES WERE MISSING.\n";
 
-        for my $type ( keys %missing_by_type ) {
-            my $missing = $missing_by_type{$type};
+    for my $type ( keys %missing_by_type ) {
+        my $missing = $missing_by_type{$type};
 
-            print "$type missing dependencies:\n";
-            for my $name ( keys %$missing ) {
-                my $module  = $missing->{$name};
-                my $version = $module->{version};
-                my $error   = $module->{error};
-                print_found(
-                    $name . ( $version && !$error ? " >= $version" : "" ),
-                    0, $module->{error} );
-            }
+        print "$type missing dependencies:\n";
+        for my $name ( keys %$missing ) {
+            my $module  = $missing->{$name};
+            my $version = $module->{version};
+            my $error   = $module->{error};
+            print_found(
+                $name . ( $version && !$error ? " >= $version" : "" ),
+                0, $module->{error} );
         }
+    }
 
-        print "\nPerl library path for @PERL@:\n";
-        print "    $_\n" for @INC;
+    print "\nPerl library path for @PERL@:\n";
+    print "    $_\n" for @INC;
 
-        exit 1;
-    }
+    exit 1;
 }
 
 sub text_to_hash {
@@ -452,39 +447,35 @@ sub test_dep {
     my $version = shift;
     my $avoid   = shift;
 
-    if ( $args{'list-deps'} ) {
-        print $module, ': ', $version || 0, "\n";
-    } else {
-        no warnings 'deprecated';
-        eval "{ local \$ENV{__WARN__}; use $module $version () }";
-        if ( my $error = $@ ) {
-            return 0 unless wantarray;
+    no warnings 'deprecated';
+    eval "{ local \$ENV{__WARN__}; use $module $version () }";
+    if ( my $error = $@ ) {
+        return 0 unless wantarray;
 
-            $error =~ s/\n(.*)$//s;
-            $error =~ s/at \(eval \d+\) line \d+\.$//;
-            undef $error if $error =~ /this is only/;
+        $error =~ s/\n(.*)$//s;
+        $error =~ s/at \(eval \d+\) line \d+\.$//;
+        undef $error if $error =~ /this is only/;
 
-            my $path = $module;
-            $path =~ s{::}{/}g;
-            undef $error
-                if defined $error
-                and $error =~ /^Can't locate $path\.pm in \@INC/;
+        my $path = $module;
+        $path =~ s{::}{/}g;
+        undef $error
+            if defined $error
+            and $error =~ /^Can't locate $path\.pm in \@INC/;
 
-            return ( 0, $error );
-        }
+        return ( 0, $error );
+    }
 
-        if ($avoid) {
-            my $version = $module->VERSION;
-            if ( grep {$version eq $_} @$avoid ) {
-                return 0 unless wantarray;
-                return ( 0,
-                    "It's known that there are problems with RT and version '$version' of '$module' module. If it's the latest available version of the module then you have to downgrade manually."
-                );
-            }
+    if ($avoid) {
+        my $version = $module->VERSION;
+        if ( grep {$version eq $_} @$avoid ) {
+            return 0 unless wantarray;
+            return ( 0,
+                "It's known that there are problems with RT and version '$version' of '$module' module. If it's the latest available version of the module then you have to downgrade manually."
+            );
         }
-
-        return 1;
     }
+
+    return 1;
 }
 
 sub resolve_dep {

commit 20bcd6048910f4be1fc114f83661d64a96c9d52a
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 02:45:56 2016 -0700

    Refactor, reword, and reorder CPAN checking
    
    Start by suggesting that the user try installing the appropriate
    system package that would provide CPAN; if this is possible, this is a
    one-command method of making `make fixdeps` simply work.
    
    Keep "use a different tool" as the next option, but provide explicit
    instructions on how to do so for cpanm; the previous example simply
    reused `perl -MCPAN -e"install %s"` as its installation tool, which is
    unlikely to work, since the whole error arises from `require CPAN`
    failing.
    
    Remove the suggestion of "configure CPAN" because it is the
    compile-time loading of the CPAN module which is failing; as such,
    `perl -MCPAN -e shell` cannot work, since (as above) we have just
    ascertained that their perl cannot load CPAN.pm
    
    Leave the bottom two options as-is, although the likelihood of the
    user being able to install CPAN by hand, or being willing to download
    every module by hand, is exceedingly low.

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index f448319..ed8b5d7 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -478,6 +478,62 @@ sub test_dep {
     return 1;
 }
 
+sub check_cpan {
+    unless ( eval {require CPAN; 1} ) {
+        print <<END;
+Failed to load CPAN module.
+
+-------- Error ---------
+$@
+------------------------
+
+When we tried to start installing RT's perl dependencies, we were
+unable to load the CPAN client. This module is usually distributed
+with Perl. This usually indicates that your vendor has shipped an
+unconfigured or incorrectly configured CPAN client.  The error above
+may (or may not) give you a hint about what went wrong.
+
+You have several choices about how to install dependencies in
+this situation:
+
+1) Install the package from your vendor that provides the 'CPAN' perl
+   module, then re-run this command.  The package is likely named
+   `perl-CPAN` or similar.
+
+2) Use a different tool to install CPAN dependencies; set the
+   RT_FIX_DEPS_CMD environment to that tool and re-run this command.
+   For instance, using the standalone `cpanm` tool:
+
+       curl -L -o cpanm https://cpanmin.us/
+       chmod +x cpanm
+       RT_FIX_DEPS_CMD=./cpanm make fixdeps
+
+3) Try to update the CPAN client. Download it from:
+   http://search.cpan.org/dist/CPAN , install it, and try again.
+
+4) Install each dependency manually by downloading them one by one from
+   http://search.cpan.org
+
+END
+        exit(1);
+    }
+
+    local @INC = @INC;
+    if ( $ENV{'HOME'} ) {
+        unshift @INC, "$ENV{'HOME'}/.cpan";
+    }
+    my $configured = eval { require CPAN::MyConfig }
+        || eval { require CPAN::Config };
+    unless ($configured) {
+        print <<END;
+You haven't configured the CPAN shell yet.
+Please run `@PERL@ -MCPAN -e shell` to configure it.
+END
+        exit(1);
+    }
+}
+
+
 sub resolve_dep {
     my $module  = shift;
     my $version = shift;
@@ -512,22 +568,7 @@ sub resolve_dep {
 
     my $ext = $ENV{'RT_FIX_DEPS_CMD'} || $ENV{'PERL_PREFER_CPAN_CLIENT'};
     unless ($ext) {
-        my $configured = 1;
-        {
-            local @INC = @INC;
-            if ( $ENV{'HOME'} ) {
-                unshift @INC, "$ENV{'HOME'}/.cpan";
-            }
-            $configured = eval { require CPAN::MyConfig }
-                || eval { require CPAN::Config };
-        }
-        unless ($configured) {
-            print <<END;
-You haven't configured the CPAN shell yet.
-Please run `@PERL@ -MCPAN -e shell` to configure it.
-END
-            exit(1);
-        }
+        check_cpan();
 
         my $installdirs = $CPAN::Config->{makepl_arg} ||= "";
         $installdirs =~ s/(\bINSTALLDIRS=\S+|$)/ INSTALLDIRS=site/
@@ -536,36 +577,6 @@ END
 
         my $rv = eval { require CPAN; CPAN::Shell->install($module) };
         return $rv unless $@;
-
-        print <<END;
-Failed to load module CPAN.
-
--------- Error ---------
-$@
-------------------------
-
-When we tried to start installing RT's perl dependencies, 
-we were unable to load the CPAN client. This module is usually distributed
-with Perl. This usually indicates that your vendor has shipped an unconfigured
-or incorrectly configured CPAN client.
-The error above may (or may not) give you a hint about what went wrong
-
-You have several choices about how to install dependencies in 
-this situatation:
-
-1) use a different tool to install dependencies by running setting the following
-   shell environment variable and rerunning this tool:
-    RT_FIX_DEPS_CMD='@PERL@ -MCPAN -e"install %s"'
-2) Attempt to configure CPAN by running:
-   `@PERL@ -MCPAN -e shell` program from shell.
-   If this fails, you may have to manually upgrade CPAN (see below)
-3) Try to update the CPAN client. Download it from:
-   http://search.cpan.org/dist/CPAN and try again
-4) Install each dependency manually by downloading them one by one from
-   http://search.cpan.org
-
-END
-        exit(1);
     }
 
     if ( $ext =~ /\%s/ ) {

commit 21af0746f289e8ea75ad99aa301704983a9ed680
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 14:21:56 2016 -0700

    Store dependencies in cpanfile
    
    Previously, dependencies were stored in a complicated hash for unclear
    reasons, and traversed in random order.  Additionally, the
    specification of them included unwieldy boilerplate and here-docs.
    
    Switch to storing the depdendency list in a `cpanfile`, and load it by
    stubbing the small number of functions to produce a useful
    datastructure.  This switches the format to the more expressive '>='
    and '!=' syntax used in META.yaml[1] files, condensing the "AVOID"
    list away.
    
    Because at least one of the database "features" is always required,
    installing directly via `cpanm --install-deps .` is not suggested or
    documented at this time.  Using the `cpanfile` format, however, opens
    the door to using `carton` and similar toolchains to manage
    dependencies.
    
    [1] https://metacpan.org/pod/CPAN::Meta::Spec#Version-Ranges

diff --git a/Makefile.in b/Makefile.in
index 4efc2ee..a57c073 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -169,6 +169,7 @@ ETC_FILES		=	acl.Pg \
 				schema.Oracle \
 				schema.mysql \
 				schema.SQLite \
+				cpanfile \
 				initialdata
 
 
diff --git a/etc/cpanfile b/etc/cpanfile
new file mode 100644
index 0000000..2208fbb
--- /dev/null
+++ b/etc/cpanfile
@@ -0,0 +1,207 @@
+# Core dependencies
+requires 'Apache::Session', '>= 1.53';
+requires 'Business::Hours';
+requires 'CGI', ($] >= 5.019003 ? '>= 4.00' : '>= 3.38');
+requires 'CGI::Cookie', '>= 1.20';
+requires 'CGI::Emulate::PSGI';
+requires 'CGI::PSGI', '>= 0.12';
+requires 'Class::Accessor::Fast';
+requires 'Convert::Color';
+requires 'Crypt::Eksblowfish';
+requires 'CSS::Minifier::XS';
+requires 'CSS::Squish', '>= 0.06';
+requires 'Data::GUID';
+requires 'Data::ICal';
+requires 'Data::Page::Pageset';
+requires 'Date::Extract', '>= 0.02';
+requires 'Date::Manip';
+requires 'DateTime', '>= 0.44';
+requires 'DateTime::Format::Natural', '>= 0.67';
+requires 'DateTime::Locale', '>= 0.40, != 1.00, != 1.01';
+requires 'DBI', '>= 1.37';
+requires 'DBIx::SearchBuilder', '>= 1.65';
+requires 'Devel::GlobalDestruction';
+requires 'Devel::StackTrace', '>= 1.19, != 1.28, != 1.29';
+requires 'Digest::base';
+requires 'Digest::MD5', '>= 2.27';
+requires 'Digest::SHA';
+requires 'Email::Address', '>= 1.897';
+requires 'Email::Address::List', '>= 0.02';
+requires 'Encode', '>= 2.64';
+requires 'Errno';
+requires 'File::Glob';
+requires 'File::ShareDir';
+requires 'File::Spec', '>= 0.8';
+requires 'File::Temp', '>= 0.19';
+requires 'HTML::Entities';
+requires 'HTML::FormatText::WithLinks', '>= 0.14';
+requires 'HTML::FormatText::WithLinks::AndTables', '>= 0.06';
+requires 'HTML::Mason', '>= 1.43';
+requires 'HTML::Mason::PSGIHandler', '>= 0.52';
+requires 'HTML::Quoted';
+requires 'HTML::RewriteAttributes', '>= 0.05';
+requires 'HTML::Scrubber', '>= 0.08';
+requires 'HTTP::Message', '>= 6.0';
+requires 'IPC::Run3';
+requires 'JavaScript::Minifier::XS';
+requires 'JSON';
+requires 'List::MoreUtils';
+requires 'Locale::Maketext', '>= 1.06';
+requires 'Locale::Maketext::Fuzzy', '>= 0.11';
+requires 'Locale::Maketext::Lexicon', '>= 0.32';
+requires 'Log::Dispatch', '>= 2.30';
+requires 'LWP::Simple';
+requires 'Mail::Header', '>= 2.12';
+requires 'Mail::Mailer', '>= 1.57';
+requires 'MIME::Entity', '>= 5.504';
+requires 'MIME::Types';
+requires 'Module::Refresh', '>= 0.03';
+requires 'Module::Versions::Report', '>= 1.05';
+requires 'Net::CIDR';
+requires 'Net::IP';
+requires 'Plack', '>= 1.0002';
+requires 'Plack::Handler::Starlet';
+requires 'Pod::Select';
+requires 'Regexp::Common';
+requires 'Regexp::Common::net::CIDR';
+requires 'Regexp::IPv6';
+requires 'Role::Basic', '>= 0.12';
+requires 'Scalar::Util';
+requires 'Scope::Upper';
+requires 'Storable', '>= 2.08';
+requires 'Symbol::Global::Name', ($] >= 5.019003 ? '>= 0.05' : '>= 0.04');
+requires 'Sys::Syslog', '>= 0.16';
+requires 'Text::Password::Pronounceable';
+requires 'Text::Quoted', '>= 2.07';
+requires 'Text::Template', '>= 1.44';
+requires 'Text::WikiFormat', '>= 0.76';
+requires 'Text::Wrapper';
+requires 'Time::HiRes';
+requires 'Time::ParseDate';
+requires 'Tree::Simple', '>= 1.04';
+requires 'UNIVERSAL::require';
+requires 'URI', '>= 1.59';
+requires 'URI::QueryParam';
+requires 'XML::RSS', '>= 1.05';
+
+# Mailgate
+requires 'Crypt::SSLeay';
+requires 'Getopt::Long';
+requires 'LWP::Protocol::https';
+requires 'LWP::UserAgent', '>= 6.0';
+requires 'Mozilla::CA';
+requires 'Net::SSL';
+requires 'Pod::Usage';
+
+# CLI
+requires 'Getopt::Long', '>= 2.24';
+requires 'HTTP::Request::Common';
+requires 'LWP';
+requires 'Term::ReadKey';
+requires 'Term::ReadLine';
+requires 'Text::ParseWords';
+
+
+on 'develop' => sub {
+    requires 'Email::Abstract';
+    requires 'File::Find';
+    requires 'File::Which';
+    requires 'HTML::Entities';
+    requires 'Locale::PO';
+    requires 'Log::Dispatch::Perl';
+    requires 'Mojo::DOM';
+    requires 'Plack::Middleware::Test::StashWarnings', '>= 0.08';
+    requires 'Pod::Simple', '>= 3.24';
+    requires 'Set::Tiny';
+    requires 'String::ShellQuote';
+    requires 'Test::Builder', '>= 0.90';
+    requires 'Test::Deep';
+    requires 'Test::Email';
+    requires 'Test::Expect', '>= 0.31';
+    requires 'Test::LongString';
+    requires 'Test::MockTime';
+    requires 'Test::NoWarnings';
+    requires 'Test::Pod';
+    requires 'Test::Warn';
+    requires 'Test::WWW::Mechanize', '>= 1.30';
+    requires 'Test::WWW::Mechanize::PSGI';
+    requires 'WWW::Mechanize', '>= 1.52';
+    requires 'XML::Simple';
+};
+
+
+# Deployment options
+feature 'standalone' => sub {};
+
+feature 'fastcgi' => sub {
+    requires 'FCGI', '>= 0.74';
+    requires 'FCGI::ProcManager';
+};
+
+feature 'modperl1' => sub {
+    requires 'Apache::Request';
+};
+
+feature 'modperl2' => sub {};
+
+
+# Database options
+feature 'mysql' => sub {
+    requires 'DBD::mysql', '>= 2.1018';
+};
+
+feature 'oracle' => sub {
+    requires 'DBD::Oracle != 1.23';
+};
+
+feature 'pg' => sub {
+    requires 'DBIx::SearchBuilder', '>= 1.66';
+    requires 'DBD::Pg', '>= 1.43';
+};
+
+feature 'sqlite' => sub {
+    requires 'DBD::SQLite', '>= 1.00';
+};
+
+
+# Optional features
+feature 'gpg' => sub {
+    requires 'File::Which';
+    requires 'GnuPG::Interface';
+    requires 'PerlIO::eol';
+};
+
+feature 'smime' => sub {
+    requires 'Crypt::X509';
+    requires 'File::Which';
+    requires 'String::ShellQuote';
+};
+
+feature 'graphviz' => sub {
+    requires 'GraphViz';
+    requires 'IPC::Run', '>= 0.90';
+};
+
+feature 'gd' => sub {
+    requires 'GD';
+    requires 'GD::Graph', '>= 1.47';
+    requires 'GD::Text';
+};
+
+feature 'externalauth' => sub {
+    requires 'Net::SSLeay';
+    requires 'Net::LDAP';
+    on 'develop' => sub {
+        requires 'Net::LDAP::Server::Test';
+    };
+};
+
+
+# External attachment storage
+feature 's3' => sub {
+    requires 'Amazon::S3';
+};
+
+feature 'dropbox' => sub {
+    requires 'File::Dropbox';
+};
diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index ed8b5d7..afd9726 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -46,22 +46,19 @@
 # those contributions and any derivatives thereof.
 #
 # END BPS TAGGED BLOCK }}}
-#
-# This is just a basic script that checks to make sure that all
-# the modules needed by RT before you can install it.
-#
 
 use strict;
 use warnings;
-no warnings qw(numeric redefine);
+
 use Getopt::Long;
+
 use Cwd qw(abs_path);
-my %args;
-my %deps;
+use File::Spec;
 my @orig_argv = @ARGV;
 # Save our path because installers or tests can change cwd
 my $script_path = abs_path($0);
 
+my %args;
 GetOptions(
     \%args,
     'install!',
@@ -109,232 +106,28 @@ $args{$_} = $default{$_} foreach grep {!exists $args{$_}} keys %default;
 $args{'with-EXTERNALAUTH-TESTS'}
     = $args{'with-EXTERNALAUTH'} && $args{'with-DEVELOPER'};
 
-$deps{'CORE'} = [ text_to_hash( << '.') ];
-Apache::Session 1.53
-Business::Hours
-CGI 3.38
-CGI::Cookie 1.20
-CGI::Emulate::PSGI
-CGI::PSGI 0.12
-Class::Accessor::Fast
-Convert::Color
-Crypt::Eksblowfish
-CSS::Minifier::XS
-CSS::Squish 0.06
-Data::GUID
-Data::ICal
-Data::Page::Pageset
-Date::Extract 0.02
-Date::Manip
-DateTime 0.44
-DateTime::Format::Natural 0.67
-DateTime::Locale 0.40
-DBI 1.37
-DBIx::SearchBuilder 1.65
-Devel::GlobalDestruction
-Devel::StackTrace 1.19
-Digest::base
-Digest::MD5 2.27
-Digest::SHA
-Email::Address 1.897
-Email::Address::List 0.02
-Encode 2.64
-Errno
-File::Glob
-File::ShareDir
-File::Spec 0.8
-File::Temp 0.19
-HTML::Entities
-HTML::FormatText::WithLinks 0.14
-HTML::FormatText::WithLinks::AndTables 0.06
-HTML::Mason 1.43
-HTML::Mason::PSGIHandler 0.52
-HTML::Quoted
-HTML::RewriteAttributes 0.05
-HTML::Scrubber 0.08
-HTTP::Message 6.0
-IPC::Run3
-JavaScript::Minifier::XS
-JSON
-List::MoreUtils
-Locale::Maketext 1.06
-Locale::Maketext::Fuzzy 0.11
-Locale::Maketext::Lexicon 0.32
-Log::Dispatch 2.30
-LWP::Simple
-Mail::Header 2.12
-Mail::Mailer 1.57
-MIME::Entity 5.504
-MIME::Types
-Module::Refresh 0.03
-Module::Versions::Report 1.05
-Net::CIDR
-Net::IP
-Plack 1.0002
-Plack::Handler::Starlet
-Pod::Select
-Regexp::Common
-Regexp::Common::net::CIDR
-Regexp::IPv6
-Role::Basic 0.12
-Scalar::Util
-Scope::Upper
-Storable 2.08
-Symbol::Global::Name 0.04
-Sys::Syslog 0.16
-Text::Password::Pronounceable
-Text::Quoted 2.07
-Text::Template 1.44
-Text::WikiFormat 0.76
-Text::Wrapper
-Time::HiRes
-Time::ParseDate
-Tree::Simple 1.04
-UNIVERSAL::require
-URI 1.59
-URI::QueryParam
-XML::RSS 1.05
-.
-set_dep( CORE => 'Symbol::Global::Name' => 0.05 ) if $] >= 5.019003;
-set_dep( CORE => CGI => 4.00 ) if $] > 5.019003;
-
-$deps{'MAILGATE'} = [ text_to_hash( << '.') ];
-Crypt::SSLeay
-Getopt::Long
-LWP::Protocol::https
-LWP::UserAgent 6.0
-Mozilla::CA
-Net::SSL
-Pod::Usage
-.
-
-$deps{'CLI'} = [ text_to_hash( << '.') ];
-Getopt::Long 2.24
-HTTP::Request::Common
-LWP
-Term::ReadKey
-Term::ReadLine
-Text::ParseWords
-.
-
-$deps{'DEVELOPER'} = [ text_to_hash( << '.') ];
-Email::Abstract
-File::Find
-File::Which
-HTML::Entities
-Locale::PO
-Log::Dispatch::Perl
-Mojo::DOM
-Plack::Middleware::Test::StashWarnings 0.08
-Pod::Simple 3.24
-Set::Tiny
-String::ShellQuote 0 # needed for gnupg-incoming.t
-Test::Builder 0.90 # needed for is_passing
-Test::Deep 0 # needed for shredder tests
-Test::Email
-Test::Expect 0.31
-Test::LongString
-Test::MockTime
-Test::NoWarnings
-Test::Pod
-Test::Warn
-Test::WWW::Mechanize 1.30
-Test::WWW::Mechanize::PSGI
-WWW::Mechanize 1.52
-XML::Simple
-.
-
-$deps{'FASTCGI'} = [ text_to_hash( << '.') ];
-FCGI 0.74
-FCGI::ProcManager
-.
-
-$deps{'MODPERL1'} = [ text_to_hash( << '.') ];
-Apache::Request
-.
-
-$deps{'MYSQL'} = [ text_to_hash( << '.') ];
-DBD::mysql 2.1018
-.
-
-$deps{'ORACLE'} = [ text_to_hash( << '.') ];
-DBD::Oracle
-.
-
-$deps{'PG'} = [ text_to_hash( << '.') ];
-DBIx::SearchBuilder 1.66
-DBD::Pg 1.43
-.
-
-$deps{'SQLITE'} = [ text_to_hash( << '.') ];
-DBD::SQLite 1.00
-.
-
-$deps{'GPG'} = [ text_to_hash( << '.') ];
-File::Which
-GnuPG::Interface
-PerlIO::eol
-.
-
-$deps{'SMIME'} = [ text_to_hash( << '.') ];
-Crypt::X509
-File::Which
-String::ShellQuote
-.
-
-$deps{'GRAPHVIZ'} = [ text_to_hash( << '.') ];
-GraphViz
-IPC::Run 0.90
-.
-
-$deps{'GD'} = [ text_to_hash( << '.') ];
-GD
-GD::Graph 1.47
-GD::Text
-.
-
-$deps{'EXTERNALAUTH'} = [ text_to_hash( <<'.') ];
-Net::SSLeay
-Net::LDAP
-.
-
-$deps{'EXTERNALAUTH-TESTS'} = [ text_to_hash( <<'.') ];
-Net::LDAP::Server::Test
-.
-
-$deps{'S3'} = [ text_to_hash( <<'.') ];
-Amazon::S3
-.
-
-$deps{'DROPBOX'} = [ text_to_hash( <<'.') ];
-File::Dropbox
-.
-
-my %AVOID = (
-    'DBD::Oracle'       => [qw(1.23)],
-    'Devel::StackTrace' => [qw(1.28 1.29)],
-    'DateTime::Locale'  => [qw(1.00 1.01)]
-);
-
+my %deps = read_deps();
 check_perl_version();
 
 check_users();
 
-my %Missing_By_Type = ();
-foreach my $type ( sort grep {$args{$_}} keys %args ) {
-    next unless ( $type =~ /^with-(.*?)$/ ) and $deps{$1};
+test_deps();
 
-    $type = $1;
-    section("$type dependencies");
+if ($args{'install'}) {
+    my $missing = 0;
+    for my $type ( sort keys %deps ) {
+        for my $module (sort keys %{$deps{$type}}) {
+            # Recheck if the dependency is now satisfied, either
+            # because it was pulled in as part of some other install,
+            # or if it was failing to load because of bad deps.
+            next if test_dep( $module, $deps{$type}{$module} );
 
-    my @missing;
-    my @deps = @{ $deps{$type} };
+            resolve_dep( $module );
 
-    my %missing = test_deps(@deps);
-
-    if ( $args{'install'} ) {
-        for my $module ( keys %missing ) {
-            resolve_dep( $module, $missing{$module}{version} );
+            # Delete the module and reload it; if it was previously
+            # installed and got upgraded, this means the new version
+            # will get loaded if some later module goes looking for it
+            # as a prereq.
             my $m = $module . '.pm';
             $m =~ s!::!/!g;
             if ( delete $INC{$m} ) {
@@ -345,19 +138,17 @@ foreach my $type ( sort grep {$args{$_}} keys %args ) {
                     delete $symtab->{$symbol};
                 }
             }
-            delete $missing{$module}
-                if test_dep( $module, $missing{$module}{version}, $AVOID{$module} );
+
+            # Recheck, to catch install failures and the like
+            $missing++ unless test_dep( $module, $deps{$type}{$module} );
         }
     }
-
-    $Missing_By_Type{$type} = \%missing if keys %missing;
+    exec( $script_path, @orig_argv, '--no-install' ) if $missing;
 }
 
-if ( $args{'install'} && keys %Missing_By_Type ) {
-    exec( $script_path, @orig_argv, '--no-install' );
-} else {
-    conclude(%Missing_By_Type);
-}
+conclude();
+exit 0;
+
 
 sub section {
     my $s = shift;
@@ -377,26 +168,21 @@ sub print_found {
 }
 
 sub conclude {
-    my %missing_by_type = @_;
-
-    unless ( keys %missing_by_type ) {
+    unless ( keys %deps ) {
         print "\nAll dependencies have been found.\n";
         return;
     }
 
     print "\nSOME DEPENDENCIES WERE MISSING.\n";
 
-    for my $type ( keys %missing_by_type ) {
-        my $missing = $missing_by_type{$type};
-
+    foreach my $type ( sort keys %deps ) {
         print "$type missing dependencies:\n";
-        for my $name ( keys %$missing ) {
-            my $module  = $missing->{$name};
-            my $version = $module->{version};
-            my $error   = $module->{error};
-            print_found(
-                $name . ( $version && !$error ? " >= $version" : "" ),
-                0, $module->{error} );
+        for my $module (sort keys %{$deps{$type}}) {
+            my $spec = $deps{$type}{$module};
+            my ($ok, $error) = test_dep( $module, $spec );
+            next if $ok;
+            my $msg = $module . ( $spec  && !$error ? " $spec" : "" );
+            print_found( $msg, $ok, $error );
         }
     }
 
@@ -406,73 +192,87 @@ sub conclude {
     exit 1;
 }
 
-sub text_to_hash {
-    my %hash;
-    for my $line ( split /\n/, $_[0] ) {
-        my ( $key, $value ) = $line =~ /(\S+)\s*(\S*)/;
-        $value ||= '';
-        $hash{$key} = $value;
-    }
-
-    return %hash;
-}
-
-sub set_dep {
-    my ( $name, $module, $version ) = @_;
-    my %list = @{ $deps{$name} };
-    $list{$module} = ( $version || '' );
-    $deps{$name} = [%list];
+sub read_deps {
+    my %deps;
+
+    # 'local' would be cleaner, but you can't localize lexicals. :/
+    my @section = ('CORE');
+
+    no warnings 'once';
+    local *requires = sub {
+        $deps{$section[-1]}{$_[0]} = $_[1];
+    };
+    local *on = sub {
+        return unless $_[0] eq 'develop' and $args{'with-DEVELOPER'};
+        push @section, 'DEVELOPER';
+        $_[1]->();
+        pop @section;
+    };
+    local *feature = sub {
+        return unless $args{"with-".uc($_[0])};
+        push @section, uc( $_[0] );
+        $_[-1]->();
+        pop @section;
+    };
+
+    my ($vol, $dir, $path) = File::Spec->splitpath( $script_path );
+    my $ret = do "$dir/../etc/cpanfile";
+    die "Failed to load cpanfile: @{[$@ || $!]}" if not defined $ret and ($@ or $!);
+
+    return %deps;
 }
 
 sub test_deps {
-    my @deps = @_;
-
-    my %missing;
-    while (@deps) {
-        my $module  = shift @deps;
-        my $version = shift @deps;
-        my ( $test, $error ) = test_dep( $module, $version, $AVOID{$module} );
-        my $msg = $module . ( $version && !$error ? " >= $version" : '' );
-        print_found( $msg, $test, $error );
-
-        $missing{$module} = { version => $version, error => $error }
-            unless $test;
+    foreach my $type ( sort keys %deps ) {
+        section("$type dependencies");
+
+        for my $module (sort keys %{$deps{$type}}) {
+            my $spec = $deps{$type}{$module};
+            my ($ok, $error) = test_dep( $module, $spec );
+            my $msg = $module . ( $spec  && !$error ? " $spec" : "" );
+            print_found( $msg, $ok, $error );
+            delete $deps{$type}{$module} if $ok;
+        }
+        delete $deps{$type} if not keys %{$deps{$type}};
+        print "\n";
     }
-
-    return %missing;
 }
 
 sub test_dep {
-    my $module  = shift;
-    my $version = shift;
-    my $avoid   = shift;
+    my ($module, $version_spec) = @_;
+    my @spec_parts = split /\s*,\s*/, defined $version_spec ? $version_spec : '';
+    my @req = grep {defined} map {/>=\s*(\S+)/ ? $1 : undef} @spec_parts;
+    my @avoid = grep {defined} map {/!=\s*(\S+)/ ? $1 : undef} @spec_parts;
+    @req = ('') unless @req;
 
     no warnings 'deprecated';
-    eval "{ local \$ENV{__WARN__}; use $module $version () }";
-    if ( my $error = $@ ) {
-        return 0 unless wantarray;
+    for my $version (@req) {
+        eval "{ local \$ENV{__WARN__}; use $module $version () }";
+        if ( my $error = $@ ) {
+            return 0 unless wantarray;
 
-        $error =~ s/\n(.*)$//s;
-        $error =~ s/at \(eval \d+\) line \d+\.$//;
-        undef $error if $error =~ /this is only/;
+            $error =~ s/\n(.*)$//s;
+            $error =~ s/at \(eval \d+\) line \d+\.$//;
+            undef $error if $error =~ /this is only/;
 
-        my $path = $module;
-        $path =~ s{::}{/}g;
-        undef $error
-            if defined $error
-            and $error =~ /^Can't locate $path\.pm in \@INC/;
+            my $path = $module;
+            $path =~ s{::}{/}g;
+            undef $error
+                if defined $error
+                and $error =~ /^Can't locate $path\.pm in \@INC/;
 
-        return ( 0, $error );
+            return ( 0, $error );
+        }
     }
 
-    if ($avoid) {
-        my $version = $module->VERSION;
-        if ( grep {$version eq $_} @$avoid ) {
-            return 0 unless wantarray;
-            return ( 0,
-                "It's known that there are problems with RT and version '$version' of '$module' module. If it's the latest available version of the module then you have to downgrade manually."
-            );
-        }
+    return 1 unless @avoid;
+
+    my $version = $module->VERSION;
+    if ( grep {$version eq $_} @avoid ) {
+        return 0 unless wantarray;
+        return ( 0,
+                 "It's known that there are problems with RT and version '$version' of '$module' module. If it's the latest available version of the module then you have to downgrade manually."
+             );
     }
 
     return 1;
@@ -536,7 +336,6 @@ END
 
 sub resolve_dep {
     my $module  = shift;
-    my $version = shift;
 
     unless ( defined $args{siteinstall} ) {
         require Config;

commit 70a1598efa2c12d145fc1b865a013ab0871c2bf8
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sun Jun 5 11:39:26 2016 -0700

    Move perl version into cpanfile

diff --git a/etc/cpanfile b/etc/cpanfile
index 2208fbb..0d6402c 100644
--- a/etc/cpanfile
+++ b/etc/cpanfile
@@ -1,3 +1,5 @@
+requires 'perl', '5.10.1';
+
 # Core dependencies
 requires 'Apache::Session', '>= 1.53';
 requires 'Business::Hours';
diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index afd9726..0913f51 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -389,17 +389,18 @@ sub resolve_dep {
 
 sub check_perl_version {
     section("perl");
-    eval { require 5.010_001 };
+    my $require = delete $deps{CORE}{perl};
+    eval "require $require";
     if ($@) {
         print_found(
-            "5.10.1", 0,
+            $require, 0,
             sprintf(
-                "RT requires Perl v5.10.1 or newer. Your current Perl is v%vd",
+                "RT requires Perl v$require or newer. Your current Perl is v%vd",
                 $^V )
         );
         exit(1);
     } else {
-        print_found( sprintf( ">=5.10.1(%vd)", $^V ), 1 );
+        print_found( sprintf( ">=%s(%vd)", $require, $^V ), 1 );
     }
 }
 

commit d8aa18070f12d1b28c7721d9101aa13ce4c2784c
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sun Jun 5 11:34:41 2016 -0700

    Rename print_found to row
    
    This pairs better with "section", and removes ambiguity about if it
    can be called when a resource was _not_ found.

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 0913f51..ffd820e 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -155,7 +155,7 @@ sub section {
     print "$s:\n";
 }
 
-sub print_found {
+sub row {
     my $msg   = shift;
     my $test  = shift;
     my $extra = shift;
@@ -182,7 +182,7 @@ sub conclude {
             my ($ok, $error) = test_dep( $module, $spec );
             next if $ok;
             my $msg = $module . ( $spec  && !$error ? " $spec" : "" );
-            print_found( $msg, $ok, $error );
+            row( $msg, $ok, $error );
         }
     }
 
@@ -230,7 +230,7 @@ sub test_deps {
             my $spec = $deps{$type}{$module};
             my ($ok, $error) = test_dep( $module, $spec );
             my $msg = $module . ( $spec  && !$error ? " $spec" : "" );
-            print_found( $msg, $ok, $error );
+            row( $msg, $ok, $error );
             delete $deps{$type}{$module} if $ok;
         }
         delete $deps{$type} if not keys %{$deps{$type}};
@@ -392,7 +392,7 @@ sub check_perl_version {
     my $require = delete $deps{CORE}{perl};
     eval "require $require";
     if ($@) {
-        print_found(
+        row(
             $require, 0,
             sprintf(
                 "RT requires Perl v$require or newer. Your current Perl is v%vd",
@@ -400,18 +400,18 @@ sub check_perl_version {
         );
         exit(1);
     } else {
-        print_found( sprintf( ">=%s(%vd)", $require, $^V ), 1 );
+        row( sprintf( ">=%s(%vd)", $require, $^V ), 1 );
     }
 }
 
 sub check_users {
     section("users");
-    print_found( "rt group (@RTGROUP@)",      defined getgrnam("@RTGROUP@") );
-    print_found( "bin owner (@BIN_OWNER@)",   defined getpwnam("@BIN_OWNER@") );
-    print_found( "libs owner (@LIBS_OWNER@)", defined getpwnam("@LIBS_OWNER@") );
-    print_found( "libs group (@LIBS_GROUP@)", defined getgrnam("@LIBS_GROUP@") );
-    print_found( "web owner (@WEB_USER@)",    defined getpwnam("@WEB_USER@") );
-    print_found( "web group (@WEB_GROUP@)",   defined getgrnam("@WEB_GROUP@") );
+    row( "rt group (@RTGROUP@)",      defined getgrnam("@RTGROUP@") );
+    row( "bin owner (@BIN_OWNER@)",   defined getpwnam("@BIN_OWNER@") );
+    row( "libs owner (@LIBS_OWNER@)", defined getpwnam("@LIBS_OWNER@") );
+    row( "libs group (@LIBS_GROUP@)", defined getgrnam("@LIBS_GROUP@") );
+    row( "web owner (@WEB_USER@)",    defined getpwnam("@WEB_USER@") );
+    row( "web group (@WEB_GROUP@)",   defined getgrnam("@WEB_GROUP@") );
 }
 
 1;

commit 23da3288aa4d503eeebfec29fe0529b6e8bdd896
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sun Jun 5 11:39:16 2016 -0700

    Improve horizontal and vertical spacing of output

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index ffd820e..dcc40c7 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -160,23 +160,27 @@ sub row {
     my $test  = shift;
     my $extra = shift;
 
-    print "\t$msg ...";
-    print $test ? "found" : "MISSING";
-    print "\n";
+    my $dots = "." x (55 - (length $msg));
 
-    print "\t\t$extra\n" if defined $extra;
+    if ($test) {
+        print "    $msg $dots ok\n";
+    } else {
+        print "    $msg $dots MISSING\n";
+        print "        $extra\n" if $extra;
+    }
 }
 
 sub conclude {
+    print "\n", "-" x 75, "\n\n";
     unless ( keys %deps ) {
-        print "\nAll dependencies have been found.\n";
+        print "All dependencies found.\n\n";
         return;
     }
 
-    print "\nSOME DEPENDENCIES WERE MISSING.\n";
+    print "SOME DEPENDENCIES WERE MISSING:\n\n";
 
     foreach my $type ( sort keys %deps ) {
-        print "$type missing dependencies:\n";
+        section("$type dependencies");
         for my $module (sort keys %{$deps{$type}}) {
             my $spec = $deps{$type}{$module};
             my ($ok, $error) = test_dep( $module, $spec );
@@ -184,9 +188,10 @@ sub conclude {
             my $msg = $module . ( $spec  && !$error ? " $spec" : "" );
             row( $msg, $ok, $error );
         }
+        print "\n";
     }
 
-    print "\nPerl library path for @PERL@:\n";
+    print "Perl library path for @PERL@:\n";
     print "    $_\n" for @INC;
 
     exit 1;
@@ -402,6 +407,7 @@ sub check_perl_version {
     } else {
         row( sprintf( ">=%s(%vd)", $require, $^V ), 1 );
     }
+    print "\n";
 }
 
 sub check_users {
@@ -412,6 +418,7 @@ sub check_users {
     row( "libs group (@LIBS_GROUP@)", defined getgrnam("@LIBS_GROUP@") );
     row( "web owner (@WEB_USER@)",    defined getpwnam("@WEB_USER@") );
     row( "web group (@WEB_GROUP@)",   defined getgrnam("@WEB_GROUP@") );
+    print "\n";
 }
 
 1;

commit 104e0deb5a28be4783756e255bd9fbfd509f9a48
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 15:22:26 2016 -0700

    Show current version of module, when relevant

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index dcc40c7..8485802 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -158,14 +158,17 @@ sub section {
 sub row {
     my $msg   = shift;
     my $test  = shift;
+    my $have  = shift;
     my $extra = shift;
 
     my $dots = "." x (55 - (length $msg));
 
     if ($test) {
-        print "    $msg $dots ok\n";
+        $have = $have ? "ok ($have)" : "ok";
+        print "    $msg $dots $have\n";
     } else {
-        print "    $msg $dots MISSING\n";
+        $have = $have ? "MISSING (have $have)" : "MISSING";
+        print "    $msg $dots $have\n";
         print "        $extra\n" if $extra;
     }
 }
@@ -186,7 +189,8 @@ sub conclude {
             my ($ok, $error) = test_dep( $module, $spec );
             next if $ok;
             my $msg = $module . ( $spec  && !$error ? " $spec" : "" );
-            row( $msg, $ok, $error );
+            my $v = $spec && eval { local $SIG{__WARN__}; $module->VERSION };
+            row( $msg, $ok, $v, $error );
         }
         print "\n";
     }
@@ -235,7 +239,8 @@ sub test_deps {
             my $spec = $deps{$type}{$module};
             my ($ok, $error) = test_dep( $module, $spec );
             my $msg = $module . ( $spec  && !$error ? " $spec" : "" );
-            row( $msg, $ok, $error );
+            my $v = $spec && eval { local $SIG{__WARN__}; $module->VERSION };
+            row( $msg, $ok, $v, $error );
             delete $deps{$type}{$module} if $ok;
         }
         delete $deps{$type} if not keys %{$deps{$type}};

commit fde23e8f9002979aeaa299d93550bf5df04ee556
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sun Jun 5 11:45:17 2016 -0700

    Use "current value" for perl check as well

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 8485802..0923a50 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -402,15 +402,10 @@ sub check_perl_version {
     my $require = delete $deps{CORE}{perl};
     eval "require $require";
     if ($@) {
-        row(
-            $require, 0,
-            sprintf(
-                "RT requires Perl v$require or newer. Your current Perl is v%vd",
-                $^V )
-        );
+        row( $require, 0,  sprintf("%vd", $^V ) );
         exit(1);
     } else {
-        row( sprintf( ">=%s(%vd)", $require, $^V ), 1 );
+        row( $require, 1, sprintf( "%vd", $^V ) );
     }
     print "\n";
 }

commit 411a0a4420f05800717599e9817ea6d7a08495c4
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sun Jun 5 11:46:17 2016 -0700

    Use "current value" for user / group display

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 0923a50..8a06014 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -412,12 +412,22 @@ sub check_perl_version {
 
 sub check_users {
     section("users");
-    row( "rt group (@RTGROUP@)",      defined getgrnam("@RTGROUP@") );
-    row( "bin owner (@BIN_OWNER@)",   defined getpwnam("@BIN_OWNER@") );
-    row( "libs owner (@LIBS_OWNER@)", defined getpwnam("@LIBS_OWNER@") );
-    row( "libs group (@LIBS_GROUP@)", defined getgrnam("@LIBS_GROUP@") );
-    row( "web owner (@WEB_USER@)",    defined getpwnam("@WEB_USER@") );
-    row( "web group (@WEB_GROUP@)",   defined getgrnam("@WEB_GROUP@") );
+
+    my $line = sub {
+        my ($type, $func, $name, $value) = @_;
+        my $id = $func->($value);
+        my $return_type = substr($type,0,1)."id";
+        row("$name $type ($value)", defined $id, defined $id ? "$return_type $id" : undef);
+    };
+    my $group = sub { $line->("group", sub {getgrnam($_[0])}, @_) };
+    my $user  = sub { $line->("user",  sub {getpwnam($_[0])}, @_) };
+
+    $group->( rt   => "@RTGROUP@" );
+    $user->(  bin  => "@BIN_OWNER@" );
+    $user->(  libs => "@LIBS_OWNER@" );
+    $group->( libs => "@LIBS_GROUP@" );
+    $user->(  web  => "@WEB_USER@" );
+    $group->( web  => "@WEB_GROUP@" );
     print "\n";
 }
 

commit 456de3f6b9f4476d51373d8406166703b3bc23a3
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sun Jun 5 11:46:41 2016 -0700

    Rename, since it checks groups as well as users

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 8a06014..9fe523b 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -109,7 +109,7 @@ $args{'with-EXTERNALAUTH-TESTS'}
 my %deps = read_deps();
 check_perl_version();
 
-check_users();
+check_users_groups();
 
 test_deps();
 
@@ -410,8 +410,8 @@ sub check_perl_version {
     print "\n";
 }
 
-sub check_users {
-    section("users");
+sub check_users_groups {
+    section("users / groups");
 
     my $line = sub {
         my ($type, $func, $name, $value) = @_;

commit 3521180a81ec4d022b3931605c3c12ca62c33143
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sun Jun 5 11:46:58 2016 -0700

    Fail-fast if the users or groups do not check out
    
    Any failures of this information are not re-summarized after modules
    are checked, which may cause it to be lost in the scrollback.
    Additionally, failures of this did not cause a failing exit code.
    
    Like the perl version check, abort immediately if there are any
    failures in this section.

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 9fe523b..66fda61 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -413,9 +413,11 @@ sub check_perl_version {
 sub check_users_groups {
     section("users / groups");
 
+    my $fails = 0;
     my $line = sub {
         my ($type, $func, $name, $value) = @_;
         my $id = $func->($value);
+        $fails++ unless defined $id;
         my $return_type = substr($type,0,1)."id";
         row("$name $type ($value)", defined $id, defined $id ? "$return_type $id" : undef);
     };
@@ -429,6 +431,7 @@ sub check_users_groups {
     $user->(  web  => "@WEB_USER@" );
     $group->( web  => "@WEB_GROUP@" );
     print "\n";
+    exit 1 if $fails;
 }
 
 1;

commit ec7dd4303f58269d7cc5999ee62303018f2a7554
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sat Jun 4 14:24:36 2016 -0700

    Show output with colors when run from a terminal

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 66fda61..f4b00db 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -150,9 +150,15 @@ conclude();
 exit 0;
 
 
+sub grey         { return -t STDOUT ? "\x1b[1;30m$_[0]\x1b[0m" : $_[0]; }
+sub bright_blue  { return -t STDOUT ? "\x1b[1;34m$_[0]\x1b[0m" : $_[0]; }
+sub green        { return -t STDOUT ? "\x1b[32m$_[0]\x1b[0m" : $_[0];   }
+sub bright_green { return -t STDOUT ? "\x1b[1;32m$_[0]\x1b[0m" : $_[0]; }
+sub bright_red   { return -t STDOUT ? "\x1b[1;31m$_[0]\x1b[0m" : $_[0]; }
+
 sub section {
     my $s = shift;
-    print "$s:\n";
+    print bright_blue("$s:\n");
 }
 
 sub row {
@@ -161,26 +167,26 @@ sub row {
     my $have  = shift;
     my $extra = shift;
 
-    my $dots = "." x (55 - (length $msg));
+    my $dots = grey("." x (55 - (length $msg)));
 
     if ($test) {
-        $have = $have ? "ok ($have)" : "ok";
+        $have = green($have ? "ok ($have)" : "ok");
         print "    $msg $dots $have\n";
     } else {
-        $have = $have ? "MISSING (have $have)" : "MISSING";
+        $have = bright_red($have ? "MISSING (have $have)" : "MISSING");
         print "    $msg $dots $have\n";
-        print "        $extra\n" if $extra;
+        print "        ". bright_red($extra) . "\n" if $extra;
     }
 }
 
 sub conclude {
     print "\n", "-" x 75, "\n\n";
     unless ( keys %deps ) {
-        print "All dependencies found.\n\n";
+        print bright_green("All dependencies found.\n\n");
         return;
     }
 
-    print "SOME DEPENDENCIES WERE MISSING:\n\n";
+    print bright_red("SOME DEPENDENCIES WERE MISSING:\n\n");
 
     foreach my $type ( sort keys %deps ) {
         section("$type dependencies");

commit 04aa1b6d6a235da95caf28ab6bec32bede7b67a1
Author: Alex Vandiver <alex at chmrr.net>
Date:   Sun Jun 5 12:50:40 2016 -0700

    Move database and deployment defaults into rt-test-dependencies
    
    rt-test-dependencies is rewritten with most, but not all, of its
    arguments set to their configure-time values.  However, it requires
    that users pass in the appropriate values for their database and
    deployment method -- the two most key configuration settings.  Running
    rt-test-dependencies directly (instead of via `make testdeps`) can
    thus lead to a false belief that all dependencies are satisfied,
    because deployment and database dependencies are not being checked.
    
    Move the dependency and deployment defaulting into
    rt-test-dependencies, from the Makefile.  In case rt-test-dependencies
    is being called with an explicit database or deployment type, these
    defaults are only set if no explicit setting is observed on the
    command line.

diff --git a/Makefile.in b/Makefile.in
index a57c073..75190c0 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -265,14 +265,13 @@ upgrade-instruct:
 
 upgrade: testdeps config-install dirs files-install fixperms upgrade-instruct
 
-my_with_web_handlers= $(shell $(PERL) -e 'print join " ", map "--with-$$_", grep defined && length, split /,/, "$(WEB_HANDLER)"')
 testdeps:
-	$(PERL) ./sbin/rt-test-dependencies --with-$(DB_TYPE) $(my_with_web_handlers)
+	$(PERL) ./sbin/rt-test-dependencies
 
 depends: fixdeps
 
 fixdeps:
-	$(PERL) ./sbin/rt-test-dependencies --install --with-$(DB_TYPE) $(my_with_web_handlers)
+	$(PERL) ./sbin/rt-test-dependencies --install
 
 #}}}
 
diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index f4b00db..2ed3355 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -101,6 +101,13 @@ my %default = (
     'with-S3'           => (uc(q{@ATTACHMENT_STORE@}) eq 'S3'),
     'with-DROPBOX'      => (uc(q{@ATTACHMENT_STORE@}) eq 'DROPBOX'),
 );
+
+$default{"with-".uc("@DB_TYPE@")} = 1 unless grep {$args{"with-$_"}} qw/MYSQL PG SQLITE ORACLE/;
+unless (grep {$args{"with-$_"}} qw/FASTCGI MODPERL1 MODPERL2 STANDALONE/) {
+    $default{"with-".uc($_)} = 1 for grep {defined && length} split /,/, "@WEB_HANDLER@"
+}
+
+
 $args{$_} = $default{$_} foreach grep {!exists $args{$_}} keys %default;
 
 $args{'with-EXTERNALAUTH-TESTS'}

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


More information about the rt-commit mailing list