Commit c718e205 authored by Alex Vandiver's avatar Alex Vandiver
Browse files

Version 0.08 releng

parent 6e24b379
0.08 Wed Jun 11 16:30:17 EDT 2014
* Compatibility with RT 4.2
* Skip setting date if it is already the current value
0.07 Fri Jun 29 15:21:19 PDT 2012
* Fix accidentally committed local paths in Test.pm
......
......@@ -9,7 +9,7 @@ configure_requires:
ExtUtils::MakeMaker: 6.59
distribution_type: module
dynamic_config: 1
generated_by: 'Module::Install version 1.06'
generated_by: 'Module::Install version 1.08'
license: gpl2
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
......@@ -25,4 +25,4 @@ requires:
perl: 5.8.0
resources:
license: http://opensource.org/licenses/gpl-2.0.php
version: 0.07
version: '0.08'
......@@ -4,16 +4,33 @@ NAME
DESCRIPTION
RT extension to implement automated due dates using service levels.
INSTALL
perl Makefile.PL
make
make install
make initdb (for the first time only)
Base configuration
In RT 3.8 and later, you must enable the plugin by adding
RT::Extension::SLA to your @Plugins line (or create one) like:
INSTALLATION
"perl Makefile.PL"
"make"
"make install"
May need root permissions
Set(@Plugins,(qw(RT::Extension::SLA)));
"make initdb"
Only run this the first time you install this module.
If you run this twice, you may end up with duplicate data in your
database.
If you are upgrading this module, check for upgrading instructions
in case changes need to be made to your database.
Edit your /opt/rt4/etc/RT_SiteConfig.pm
If you are using RT 4.2 or greater, add this line:
Plugin('RT::Extension::SLA');
For RT 3.8 and 4.0, add this line:
Set(@Plugins, qw(RT::Extension::SLA));
or add "RT::Extension::SLA" to your existing @Plugins line.
Restart your webserver
UPGRADING
From versions prior to 0.06
......@@ -342,7 +359,7 @@ AUTHOR
Ruslan Zakirov <ruz@bestpractical.com>
COPYRIGHT
This extension is Copyright (C) 2007-2009 Best Practical Solutions, LLC.
This extension is Copyright (C) 2007-2014 Best Practical Solutions, LLC.
It is freely redistributable under the terms of version 2 of the GNU
GPL.
......
......@@ -8,7 +8,7 @@ use ExtUtils::MakeMaker ();
use vars qw{$VERSION};
BEGIN {
$VERSION = '1.06';
$VERSION = '1.08';
}
# special map on pre-defined feature sets
......
......@@ -31,7 +31,7 @@ BEGIN {
# This is not enforced yet, but will be some time in the next few
# releases once we can make sure it won't clash with custom
# Module::Install extensions.
$VERSION = '1.06';
$VERSION = '1.08';
# Storage for the pseudo-singleton
$MAIN = undef;
......
......@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
$VERSION = '1.06';
$VERSION = '1.08';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
......
......@@ -4,7 +4,7 @@ package Module::Install::Base;
use strict 'vars';
use vars qw{$VERSION};
BEGIN {
$VERSION = '1.06';
$VERSION = '1.08';
}
# Suspend handler for "redefined" warnings
......
......@@ -8,7 +8,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
$VERSION = '1.06';
$VERSION = '1.08';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
......
......@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
$VERSION = '1.06';
$VERSION = '1.08';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
......
......@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
$VERSION = '1.06';
$VERSION = '1.08';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
......
......@@ -8,7 +8,7 @@ use Fcntl qw/:flock :seek/;
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
$VERSION = '1.06';
$VERSION = '1.08';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
......
......@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
$VERSION = '1.06';
$VERSION = '1.08';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
......
......@@ -8,13 +8,13 @@ no warnings 'once';
use Module::Install::Base;
use base 'Module::Install::Base';
our $VERSION = '0.29';
our $VERSION = '0.34';
use FindBin;
use File::Glob ();
use File::Basename ();
my @DIRS = qw(etc lib html bin sbin po var);
my @DIRS = qw(etc lib html static bin sbin po var);
my @INDEX_DIRS = qw(lib bin sbin);
sub RTx {
......@@ -62,10 +62,11 @@ sub RTx {
unshift @INC, "$RT::LocalPath/lib" if $RT::LocalPath;
unshift @INC, $lib_path;
$RT::LocalVarPath ||= $RT::VarPath;
$RT::LocalPoPath ||= $RT::LocalLexiconPath;
$RT::LocalHtmlPath ||= $RT::MasonComponentRoot;
$RT::LocalLibPath ||= "$RT::LocalPath/lib";
$RT::LocalVarPath ||= $RT::VarPath;
$RT::LocalPoPath ||= $RT::LocalLexiconPath;
$RT::LocalHtmlPath ||= $RT::MasonComponentRoot;
$RT::LocalStaticPath ||= $RT::StaticPath;
$RT::LocalLibPath ||= "$RT::LocalPath/lib";
my $with_subdirs = $ENV{WITH_SUBDIRS};
@ARGV = grep { /WITH_SUBDIRS=(.*)/ ? ( ( $with_subdirs = $1 ), 0 ) : 1 }
......@@ -87,6 +88,11 @@ sub RTx {
."Upgrade to RT 3.8.1 or newer.\n" if $RT::VERSION =~ /^3\.8\.0/;
$path{$_} = $RT::LocalPluginPath . "/$original_name/$_"
foreach @DIRS;
# Copy RT 4.2.0 static files into NoAuth; insufficient for
# images, but good enough for css and js.
$path{static} = "$path{html}/NoAuth/"
unless $RT::StaticPath;
} else {
foreach ( @DIRS ) {
no strict 'refs';
......@@ -129,23 +135,15 @@ install ::
my %has_etc;
if ( File::Glob::bsd_glob("$FindBin::Bin/etc/schema.*") ) {
# got schema, load factory module
$has_etc{schema}++;
$self->load('RTxFactory');
$self->postamble(<< ".");
factory ::
\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Minc::Module::Install -e"RTxFactory(qw($RTx $name))"
dropdb ::
\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Minc::Module::Install -e"RTxFactory(qw($RTx $name drop))"
.
}
if ( File::Glob::bsd_glob("$FindBin::Bin/etc/acl.*") ) {
$has_etc{acl}++;
}
if ( -e 'etc/initialdata' ) { $has_etc{initialdata}++; }
if ( grep { /\d+\.\d+\.\d+.*$/ } glob('etc/upgrade/*.*.*') ) {
$has_etc{upgrade}++;
}
$self->postamble("$postamble\n");
unless ( $subdirs{'lib'} ) {
......@@ -164,68 +162,69 @@ dropdb ::
print "For first-time installation, type 'make initdb'.\n";
my $initdb = '';
$initdb .= <<"." if $has_etc{schema};
\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Minc::Module::Install -e"RTxInitDB(qw(schema))"
\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Minc::Module::Install -e"RTxInitDB(qw(schema \$(NAME) \$(VERSION)))"
.
$initdb .= <<"." if $has_etc{acl};
\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Minc::Module::Install -e"RTxInitDB(qw(acl))"
\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Minc::Module::Install -e"RTxInitDB(qw(acl \$(NAME) \$(VERSION)))"
.
$initdb .= <<"." if $has_etc{initialdata};
\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Minc::Module::Install -e"RTxInitDB(qw(insert))"
\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Minc::Module::Install -e"RTxInitDB(qw(insert \$(NAME) \$(VERSION)))"
.
$self->postamble("initdb ::\n$initdb\n");
$self->postamble("initialize-database ::\n$initdb\n");
if ($has_etc{upgrade}) {
print "To upgrade from a previous version of this extension, use 'make upgrade-database'\n";
my $upgradedb = qq|\t\$(NOECHO) \$(PERL) -Ilib -I"$local_lib_path" -I"$lib_path" -Minc::Module::Install -e"RTxInitDB(qw(upgrade \$(NAME) \$(VERSION)))"\n|;
$self->postamble("upgrade-database ::\n$upgradedb\n");
$self->postamble("upgradedb ::\n$upgradedb\n");
}
}
}
sub RTxInit {
unshift @INC, substr( delete( $INC{'RT.pm'} ), 0, -5 ) if $INC{'RT.pm'};
require RT;
RT::LoadConfig();
RT::ConnectToDatabase();
die "Cannot load RT" unless $RT::Handle and $RT::DatabaseType;
}
# stolen from RT::Handle so we work on 3.6 (cmp_versions came in with 3.8)
{ my %word = (
a => -4,
alpha => -4,
b => -3,
beta => -3,
pre => -2,
rc => -1,
head => 9999,
);
sub cmp_version($$) {
my ($a, $b) = (@_);
my @a = grep defined, map { /^[0-9]+$/? $_ : /^[a-zA-Z]+$/? $word{$_}|| -10 : undef }
split /([^0-9]+)/, $a;
my @b = grep defined, map { /^[0-9]+$/? $_ : /^[a-zA-Z]+$/? $word{$_}|| -10 : undef }
split /([^0-9]+)/, $b;
@a > @b
? push @b, (0) x (@a-@b)
: push @a, (0) x (@b-@a);
for ( my $i = 0; $i < @a; $i++ ) {
return $a[$i] <=> $b[$i] if $a[$i] <=> $b[$i];
}
return 0;
}}
sub requires_rt {
my ($self,$version) = @_;
# if we're exactly the same version as what we want, silently return
return if ($version eq $RT::VERSION);
my @sorted = sort cmp_version $version,$RT::VERSION;
_load_rt_handle();
my @sorted = sort RT::Handle::cmp_version $version,$RT::VERSION;
if ($sorted[-1] eq $version) {
# should we die?
warn "\nWarning: prerequisite RT $version not found. Your installed version of RT ($RT::VERSION) is too old.\n\n";
die "\nWarning: prerequisite RT $version not found. Your installed version of RT ($RT::VERSION) is too old.\n\n";
}
}
sub rt_too_new {
my ($self,$version,$msg) = @_;
$msg ||= "Your version %s is too new, this extension requires a release of RT older than %s\n";
_load_rt_handle();
my @sorted = sort RT::Handle::cmp_version $version,$RT::VERSION;
if ($sorted[0] eq $version) {
die sprintf($msg,$RT::VERSION,$version);
}
}
# RT::Handle runs FinalizeDatabaseType which calls RT->Config->Get
# On 3.8, this dies. On 4.0/4.2 ->Config transparently runs LoadConfig.
# LoadConfig requires being able to read RT_SiteConfig.pm (root) so we'd
# like to avoid pushing that on users.
# Fake up just enough Config to let FinalizeDatabaseType finish, and
# anyone later calling LoadConfig will overwrite our shenanigans.
sub _load_rt_handle {
unless ($RT::Config) {
require RT::Config;
$RT::Config = RT::Config->new;
RT->Config->Set('DatabaseType','mysql');
}
require RT::Handle;
}
1;
__END__
#line 348
#line 367
......@@ -6,7 +6,7 @@ use strict;
use File::Basename ();
sub RTxInitDB {
my ($self, $action) = @_;
my ($self, $action, $name, $version) = @_;
unshift @INC, substr(delete($INC{'RT.pm'}), 0, -5) if $INC{'RT.pm'};
......@@ -23,6 +23,8 @@ sub RTxInitDB {
RT::LoadConfig();
require RT::System;
my $lib_path = File::Basename::dirname($INC{'RT.pm'});
my @args = ("-Ilib");
push @args, "-I$RT::LocalPath/lib" if $RT::LocalPath;
......@@ -30,454 +32,22 @@ sub RTxInitDB {
"-I$lib_path",
"$RT::SbinPath/rt-setup-database",
"--action" => $action,
"--datadir" => "etc",
($action eq 'upgrade' ? () : ("--datadir" => "etc")),
(($action eq 'insert') ? ("--datafile" => "etc/initialdata") : ()),
"--dba" => $RT::DatabaseUser,
"--prompt-for-dba-password" => ''
"--dba" => $RT::DatabaseAdmin || $RT::DatabaseUser,
"--prompt-for-dba-password" => '',
(RT::System->can('AddUpgradeHistory') ? ("--package" => $name, "--ext-version" => $version) : ()),
);
print "$^X @args\n";
(system($^X, @args) == 0) or die "...returned with error: $?\n";
}
sub RTxFactory {
my ($self, $RTx, $name, $drop) = @_;
my $namespace = "$RTx\::$name";
$self->RTxInit;
my $dbh = $RT::Handle->dbh;
# get all tables out of database
my @tables = $dbh->tables;
my ( %tablemap, %typemap, %modulemap );
my $driver = $RT::DatabaseType;
my $CollectionBaseclass = 'RT::SearchBuilder';
my $RecordBaseclass = 'RT::Record';
my $LicenseBlock = << '.';
# BEGIN LICENSE BLOCK
#
# END LICENSE BLOCK
.
my $Attribution = << '.';
# Autogenerated by Module::Intall::RTx::Factory
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
# !! DO NOT EDIT THIS FILE !!
#
use strict;
.
my $RecordInit = '';
@tables = map { do { {
my $table = $_;
$table =~ s/.*\.//g;
$table =~ s/\W//g;
$table =~ s/^\Q$name\E_//i or next;
$table ne 'sessions' or next;
$table = ucfirst(lc($table));
$table =~ s/$_/\u$_/ for qw(field group custom member value);
$table =~ s/(?<=Scrip)$_/\u$_/ for qw(action condition);
$table =~ s/$_/\U$_/ for qw(Acl);
$table = $name . '_' . $table;
$tablemap{$table} = $table;
$modulemap{$table} = $table;
if ( $table =~ /^(.*)s$/ ) {
$tablemap{$1} = $table;
$modulemap{$1} = $1;
}
$table;
} } } @tables;
$tablemap{'CreatedBy'} = 'User';
$tablemap{'UpdatedBy'} = 'User';
$typemap{'id'} = 'ro';
$typemap{'Creator'} = 'auto';
$typemap{'Created'} = 'auto';
$typemap{'Updated'} = 'auto';
$typemap{'UpdatedBy'} = 'auto';
$typemap{'LastUpdated'} = 'auto';
$typemap{'LastUpdatedBy'} = 'auto';
$typemap{lc($_)} = $typemap{$_} for keys %typemap;
foreach my $table (@tables) {
if ($drop) {
$dbh->do("DROP TABLE $table");
$dbh->do("DROP sequence ${table}_id_seq") if $driver eq 'Pg';
$dbh->do("DROP sequence ${table}_seq") if $driver eq 'Oracle';
next;
}
my $tablesingle = $table;
$tablesingle =~ s/^\Q$name\E_//i;
$tablesingle =~ s/s$//;
my $tableplural = $tablesingle . "s";
if ( $tablesingle eq 'ACL' ) {
$tablesingle = "ACE";
$tableplural = "ACL";
}
my %requirements;
my $CollectionClassName = $namespace . "::" . $tableplural;
my $RecordClassName = $namespace . "::" . $tablesingle;
my $path = $namespace;
$path =~ s/::/\//g;
my $RecordClassPath = $path . "/" . $tablesingle . ".pm";
my $CollectionClassPath = $path . "/" . $tableplural . ".pm";
#create a collection class
my $CreateInParams;
my $CreateOutParams;
my $ClassAccessible = "";
my $FieldsPod = "";
my $CreatePod = "";
my $CreateSub = "";
my %fields;
my $sth = $dbh->prepare("DESCRIBE $table");
if ( $driver eq 'Pg' ) {
$sth = $dbh->prepare(<<".");
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
a.attnotnull, a.atthasdef, a.attnum
FROM pg_class c, pg_attribute a
WHERE c.relname ILIKE '$table'
AND a.attnum > 0
AND a.attrelid = c.oid
ORDER BY a.attnum
.
}
elsif ( $driver eq 'mysql' ) {
$sth = $dbh->prepare("DESCRIBE $table");
}
else {
die "$driver is currently unsupported";
}
$sth->execute;
while ( my $row = $sth->fetchrow_hashref() ) {
my ( $field, $type, $default );
if ( $driver eq 'Pg' ) {
$field = $row->{'attname'};
$type = $row->{'format_type'};
$default = $row->{'atthasdef'};
if ( $default != 0 ) {
my $tth = $dbh->prepare(<<".");
SELECT substring(d.adsrc for 128)
FROM pg_attrdef d, pg_class c
WHERE c.relname = 'acct'
AND c.oid = d.adrelid
AND d.adnum = $row->{'attnum'}
.
$tth->execute();
my @default = $tth->fetchrow_array;
$default = $default[0];
}
}
elsif ( $driver eq 'mysql' ) {
$field = $row->{'Field'};
$type = $row->{'Type'};
$default = $row->{'Default'};
}
$fields{$field} = 1;
#generate the 'accessible' datastructure
if ( $typemap{$field} eq 'auto' ) {
$ClassAccessible .= " $field =>
{read => 1, auto => 1,";
}
elsif ( $typemap{$field} eq 'ro' ) {
$ClassAccessible .= " $field =>
{read => 1,";
}
else {
$ClassAccessible .= " $field =>
{read => 1, write => 1,";
}
$ClassAccessible .= " type => '$type', default => '$default'},\n";
#generate pod for the accessible fields
$FieldsPod .= $self->_pod(<<".");
^head2 $field
Returns the current value of $field.
(In the database, $field is stored as $type.)
.
unless ( $typemap{$field} eq 'auto' || $typemap{$field} eq 'ro' ) {
$FieldsPod .= $self->_pod(<<".");
^head2 Set$field VALUE
Set $field to VALUE.
Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
(In the database, $field will be stored as a $type.)
.
}
$FieldsPod .= $self->_pod(<<".");
^cut
.
if ( $modulemap{$field} ) {
$FieldsPod .= $self->_pod(<<".");
^head2 ${field}Obj
Returns the $modulemap{$field} Object which has the id returned by $field
^cut
sub ${field}Obj {
my \$self = shift;
my \$$field = ${namespace}::$modulemap{$field}->new(\$self->CurrentUser);
\$$field->Load(\$self->__Value('$field'));
return(\$$field);
}
.
$requirements{ $tablemap{$field} } =
"use ${namespace}::$modulemap{$field};";
}
unless ( $typemap{$field} eq 'auto' || $field eq 'id' ) {
#generate create statement
$CreateInParams .= " $field => '$default',\n";
$CreateOutParams .=
" $field => \$args{'$field'},\n";
#gerenate pod for the create statement
$CreatePod .= " $type '$field'";
$CreatePod .= " defaults to '$default'" if ($default);
$CreatePod .= ".\n";
}