[smolder-commits] SF.net SVN: smolder:[861] trunk
Brought to you by:
michael_peters
From: <mic...@us...> - 2009-03-28 22:21:32
|
Revision: 861 http://smolder.svn.sourceforge.net/smolder/?rev=861&view=rev Author: michael_peters Date: 2009-03-28 22:21:22 +0000 (Sat, 28 Mar 2009) Log Message: ----------- removing MysQL and using SQLite completely Modified Paths: -------------- trunk/Build.PL trunk/lib/Smolder/Conf.pm trunk/lib/Smolder/Control/Admin/Developers.pm trunk/lib/Smolder/Control/Admin/Projects.pm trunk/lib/Smolder/Control/Developer/Projects.pm trunk/lib/Smolder/DB.pm trunk/lib/Smolder/Mech.pm trunk/lib/Smolder/Server.pm trunk/lib/Smolder/Upgrade.pm trunk/smolder.conf.example trunk/t/constraints.t Added Paths: ----------- trunk/sql/db_version.sql trunk/sql/developer.sql trunk/sql/preference.sql trunk/sql/project.sql trunk/sql/project_developer.sql trunk/sql/smoke_report.sql Removed Paths: ------------- trunk/docs/ops_install.pod trunk/docs/porting.pod trunk/lib/Smolder/DBPlatform/ trunk/lib/Smolder/DBPlatform.pm trunk/sql/insert.sql trunk/sql/mysql/ trunk/sql/sqlite/ trunk/t/mysql_iso_level.t trunk/upgrades/sql/mysql/ trunk/upgrades/sql/sqlite/ Modified: trunk/Build.PL =================================================================== --- trunk/Build.PL 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/Build.PL 2009-03-28 22:21:22 UTC (rev 861) @@ -59,6 +59,7 @@ install_path => { templates => catdir(dist_dir('Smolder'), 'templates'), htdocs => catdir(dist_dir('Smolder'), 'htdocs'), + sql => catdir(dist_dir('Smolder'), 'sql'), }, create_makefile_pl => 'traditional', create_readme => 1, Deleted: trunk/docs/ops_install.pod =================================================================== --- trunk/docs/ops_install.pod 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/docs/ops_install.pod 2009-03-28 22:21:22 UTC (rev 861) @@ -1,209 +0,0 @@ -=for comment -This POD file is used to generate INSTALL in distribution archives. - -=head1 Installing Smolder - -This document describes how to install Smolder on your system. - -=head2 Supported Platforms - -Smolder has been built and used on the following platforms: - -=over - -=item * Fedora 3-8 - -=item * FreeBSD 7.0 - -=back - -Smolder will likely compile fine on other similar platforms, but you'll -need to download the source distribution and build it yourself. See -L<"Building Smolder from Source">. - -=head2 Software Requirements - -Before you can install Smolder you'll need Perl version 5.6.1 or later -and MySQL version 4.0.13 or later. You can download Perl here: - - http://www.perl.com/download.csp - -And MySQL 4 can be found here: - - http://www.mysql.com/downloads/mysql-4.0.html - -Smolder may require additional software, depending on your operating -system. Be sure to read the platform-specific README (eg. -F<README.RH9>) included with Smolder. - -=head2 Choosing a Distribution - -When you download Smolder you must choose a distribution that matches -your operating system and version of Perl. If you don't know what -version of Perl you have, run this command on your command-line: - - perl -MConfig -e 'printf "perl%d.%d.%d-%s", - (map { ord($_) } split("", $^V, 3)), $Config{archname}' - -This will print something like: - - perl5.6.1-i686-linux - -Using this information, if you wanted to install Smolder 1.013 on Redhat -7.3 you would download: - - smolder-1.013-RH7_3-perl5.6.1-i686-linux.tar.gz - -Smolder also has a special source distribution with F<-src> instead of a -platform description (ex: F<smolder-1.013-src.tar.gz>). You can -download this release and attempt to build Smolder from source. Of -course, this may require porting work if Smolder doesn't support your -platform. - -=head2 Building Smolder from Source - -If you downloaded the source distribution (ex: -F<smolder-1.013-src.tar.gz>) then you'll need to build Smolder before you -can install it. If you've got a binary distribution, skip ahead to -L<"Installation">. - -First, untar the source tar-ball and enter the directory: - - tar zxvf smolder-1.013-src.tar.gz - cd smolder-1.013-src - -If there's a README file for your platform (ex: README.FreeBSD5), read -that now. It will tell you about software you'll need to install -before building Smolder. - -Now try building Smolder using the bin/smolder_build script: - - bin/smolder_build - -If Smolder complains that it doesn't know what platform to build for you -can pass it a platform name: - - bin/smolder_build RH9 - -If that works, you can now build a binary distribution for your -platform and proceed to the next step: - - bin/smolder_makedist - -If not, you'll have to do some porting work to get Smolder working on -your system. To learn more about porting Smolder, read this: - - docs/porting.pod - -=head2 Installation - -Once you've downloaded a Smolder binary distribution, or built one from -source, un-tar it and enter the directory created: - - tar zxvf smolder-1.013-RH7_3-perl5.6.1-i686-linux.tar.gz - cd smolder-1.013-RH7_3-perl5.6.1-i686-linux - -To install, run bin/smolder_install as root, providing options -describing how to setup Smolder: - - # ./bin/smolder_install \ - --HostName $HostName \ - --IPAddress $IPAddress \ - --DBUser $DBUser \ - --DBPass $DBPass \ - -These options are described below. - -=head2 Required Variables - -Before you install you must gather the following information. The -following variables should be replaced in example shell commands with -the appropriate values. - -=over 4 - -=item HostName - -Host name used for Smolder's main Apache virtual host (e.g., -"cms23.foo.com"). This is the master host which provides a list of -all configured Smolder instances. Often this is the hostname of the -machine itself, although systems with multiple Smolder installations -must choose different HostNames for each. - -=item IPAddress - -IP address used for the Smolder Apache server and FTP server. You'll -need to arrange DNS to point this IPAddress at HostName. - -=back - -=head2 Optional Variables - -Other variables may be required, depending on your installation needs: - -=over 4 - -=item DBPlatform - -This specifies which database platform this install of Smolder will use. -Smolder currently supports the following databases: MySQL and SQLite. -The default is SQLite. - -=item DBUser - -Name of MySQL database user which is used by this installation (e.g., -"smolderdb"). This user will be created if it does not exist. -This option is only needed if your C<DBPlatform> is set to "MySQL" - -=item DBPass - -MySQL user password which is used by this Smolder installation (e.g., -"xyzzy"). If the MySQL user already exists this must be the correct -password for the user. -This option is only needed if your C<DBPlatform> is set to "MySQL" - -=item AdminDBPass - -Defaults to "" (none). The password for the MySQL user "root" who is -assumed to exist, and to have full access to MySQL. If the "root" -user doesn't exist or has restricted access you must change your MySQL -configuration before installing Smolder. -This option is only needed if your C<DBPlatform> is set to "MySQL" - -=item InstallPath - -Defaults to "/usr/local/smolder". Directory into which Smolder should be -installed. - -=item User - -Defaults to "smolder". UNIX user for process ownership (Apache, etc.), -file ownership and install location. This user will be created if it -does not exist. - -=item Group - -Defaults to "smolder". UNIX group for process ownership (Apache, etc.), -file ownership and install location. This group will be created if it -does not exist. - -=item ApachePort - -Defaults to 80. Port on which the Apache server should run. - -=item SMTPHost - -Defaults to localhost (127.0.0.1). Address of SMTP mail server used -by Smolder for sending email alerts. - -=item FromAddress - -Email address used as the 'From' address on all outgoing emails - -=item FromBackup - -If you are installing Smolder from a previous backup, then specify that -here. Data and settings from the backup will be preserved in the new install. - -=back - Deleted: trunk/docs/porting.pod =================================================================== --- trunk/docs/porting.pod 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/docs/porting.pod 2009-03-28 22:21:22 UTC (rev 861) @@ -1,107 +0,0 @@ -=head1 Porting Smolder - -This document describes how to port Smolder to a new platform. You'll -need to port Smolder if you want to run Smolder on a platform which isn't -supported. See HREF[the installation instructions|ops_install.html] -for the list of supported platforms. - -=head2 Getting Started - -Every platform Smolder supports should have a directory inside the -F<platform/> directory. For example, Redhat 7.3 has -F<platform/Redhat7_3>. Create a directory for the new platform. - -Next, you'll need to create a file called Platform.pm which contains -at least the following: - - package PLATFORM_NAME::Platform; - use warnings; - use strict; - - use base 'Smolder::Platform'; - - 1; - -At this point you I<might> be done, particularly if your platform is -very similar to Fedora Linux (Smolder's home platform). To find out, -try to build Smolder: - - bin/smolder_build PLATFORM_NAME - -If that worked, build a distribution: - - bin/smolder_makedist - -Now you can take that distribution and install it as usual: - - tar zxvf smolder-...tar.gz - cd smolder-... - bin/smolder_install ... - -If that worked, try running the test suite: - - cd /path/to/smolder - make test - -If all tests pass, you're done! - -=head2 Solving Problems - -It's quite likely that one of the steps described above didn't work. -If so, it's time to write some code. - -=head3 Fixing the Build - -If Smolder failed to build, or test failures reveal that something -wasn't built right you need to make changes to your Platform.pm. One -possibility is to choose a base class from among the other supported -platforms. For example, when porting Smolder to Mandrake Linux it might -be reasonable to start with this: - - use base 'Redhat9::Platform'; - -In place of this line: - - use base 'Smolder::Platform'; - -Now your build process will mimic that of another platform. - -Failing that, you'll need to start overriding methods in -Smolder::Platform to adjust Smolder's build process. For example, let's -say Apache::DBI won't build on your platform without /usr/local/bin -first in the path. You could add an overridden build_perl_module() to -your Platform.pm: - - sub build_perl_module { - my ($pkg, %arg) = @_; - my $name = $arg{name}; - - if ($name =~ /Apache-DBI/) { - local $ENV{PATH} = "/usr/local/bin:$ENV{PATH}"; - return $pkg->SUPER::build_perl_module(%arg); - } - - return $pkg->SUPER::build_perl_module(%arg); - } - -See the L<Smolder::Platform> documentation for a description of all -available methods. - -=head3 Fixing Smolder - -Another possibility is that Smolder itself needs work to perform -correctly on your platform. This is particularly likely if you're -trying to add support for a new version of Perl or MySQL. - -=head2 Wrapping Up - -Each platform is allowed to have its own F<README> file. This file is -copied into binary distributions for that platform. For an example, -take a look at F<platform/Redhat7_3/README.Redhat7_3>. This file is a -good place to describe any platform-specific setup needed to get Smolder -working. - -When you're done porting Smolder, commit your work to SVN or send a -patch to the Smolder developer mailing-list. Remember to add the -platform to the supported platform list in F<docs/ops_install.pod>. - Modified: trunk/lib/Smolder/Conf.pm =================================================================== --- trunk/lib/Smolder/Conf.pm 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/lib/Smolder/Conf.pm 2009-03-28 22:21:22 UTC (rev 861) @@ -17,11 +17,6 @@ BEGIN { @VALID_DIRECTIVES = map { lc($_) } qw( Port - DBPlatform - DBHost - DBName - DBPass - DBUser FromAddress HostName LogFile @@ -31,11 +26,11 @@ TemplateDir DataDir HtdocsDir + SQLDir ); @REQUIRED_DIRECTIVES = qw( Port - DBPlatform FromAddress HostName Secret @@ -176,20 +171,6 @@ unless defined $CONF->get($dir); } - # let them know that MySQL is deprecated - if ($CONF->get('DBPlatform') eq 'MySQL') { - warn "MySQL is deprecated as a DBPlatform. Please upgrade to SQLite\n"; - - # and make sure they provide all the other DB* stuff we need for MySQL - unless ($CONF->get('DBName') - && $CONF->get('DBUser') - && $CONF->get('DBPass') - && $CONF->get('DBHost')) - { - _broked("MySQL needs DBUser, DBPass, DBHost and DBName all set in smolder.conf"); - } - } - # if we have a log file, does it exist and can we write to it? my $log_file = $CONF->get('LogFile'); if ($log_file) { @@ -225,6 +206,18 @@ return $class->get('HtdocsDir') || catdir(dist_dir('Smolder'), 'htdocs'); } +=head2 sql_dir + +The directory path for the raw SQL files for this install of Smolder + +=cut + +sub sql_dir { + my $class = shift; + return $class->get('SQLDir') || catdir(dist_dir('Smolder'), 'sql'); +} + + =head2 data_dir The directory path for data directory for this install of Smolder Modified: trunk/lib/Smolder/Control/Admin/Developers.pm =================================================================== --- trunk/lib/Smolder/Control/Admin/Developers.pm 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/lib/Smolder/Control/Admin/Developers.pm 2009-03-28 22:21:22 UTC (rev 861) @@ -6,9 +6,7 @@ use Smolder::DB::Developer; use Smolder::Email; use Smolder::Constraints qw(email unsigned_int length_max length_between bool unique_field_value); -use Smolder::DBPlatform; use Email::Valid; -my $DB_PLATFORM = Smolder::DBPlatform->load(); =head1 NAME @@ -156,7 +154,7 @@ if ($@) { # if it was a duplicate developer, then we can handle that - if ( $DB_PLATFORM->unique_failure_msg($@) ) { + if ( Smolder::Conf->unique_failure_msg($@) ) { return $self->edit( { err_unique_username => 1 } ); # else it's something else, so just throw it again @@ -239,7 +237,7 @@ if ($@) { # if it was a duplicate developer, then we can handle that - if ( $DB_PLATFORM->unique_failure_msg($@) ) { + if ( Smolder::Conf->unique_failure_msg($@) ) { return $self->add( { err_unique_username => 1 } ); # else it's something else, so just throw it again Modified: trunk/lib/Smolder/Control/Admin/Projects.pm =================================================================== --- trunk/lib/Smolder/Control/Admin/Projects.pm 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/lib/Smolder/Control/Admin/Projects.pm 2009-03-28 22:21:22 UTC (rev 861) @@ -3,6 +3,9 @@ use warnings; use base 'Smolder::Control'; use Data::FormValidator::Constraints::DateTime qw(to_datetime); +use Smolder::DB::Project; +use Smolder::DB::Developer; +use Smolder::DB::ProjectDeveloper; use Smolder::Constraints qw( length_max unsigned_int @@ -10,11 +13,6 @@ unique_field_value existing_field_value ); -use Smolder::DB::Project; -use Smolder::DB::Developer; -use Smolder::DB::ProjectDeveloper; -use Smolder::DBPlatform; -my $DB_PLATFORM = Smolder::DBPlatform->load(); =head1 NAME @@ -141,7 +139,7 @@ if ($@) { my $err = $@; $proj_pref->delete if $proj_pref; - die $err unless $DB_PLATFORM->unique_failure_msg($err); + die $err unless Smolder::DB->unique_failure_msg($err); } else { $self->add_message( msg => "Developer '" . $dev->username @@ -303,7 +301,7 @@ if ($@) { # if it was a duplicate project name, then we can handle that - if ( $DB_PLATFORM->unique_failure_msg($@) ) { + if ( Smolder::Conf->unique_failure_msg($@) ) { return $self->add( { err_unique_project_name => 1 } ); # else it's something else, so just throw it again Modified: trunk/lib/Smolder/Control/Developer/Projects.pm =================================================================== --- trunk/lib/Smolder/Control/Developer/Projects.pm 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/lib/Smolder/Control/Developer/Projects.pm 2009-03-28 22:21:22 UTC (rev 861) @@ -2,20 +2,14 @@ use base 'Smolder::Control'; use strict; use warnings; - -=head1 NAME - -Smolder::Control::Developer::Projects - -=head1 DESCRIPTION - -Controller module that deals with developer actions associated with projects. - -=cut - use CGI::Application::Plugin::Stream qw(stream_file); use Smolder::DB::Project; use Smolder::DB::SmokeReport; +use Smolder::Conf; +use Exception::Class; +use HTML::TagCloud; +use URI::Escape qw(uri_escape); +use Smolder::Control::Public::Auth; use Smolder::Constraints qw( enum_value length_max @@ -24,15 +18,17 @@ file_mtype smoke_report_tags ); -use Smolder::Conf; -use Smolder::DBPlatform; -use Exception::Class; -use HTML::TagCloud; -use URI::Escape qw(uri_escape); -use Smolder::Control::Public::Auth; -my $DB_PLATFORM = Smolder::DBPlatform->load(); +=head1 NAME +Smolder::Control::Developer::Projects + +=head1 DESCRIPTION + +Controller module that deals with developer actions associated with projects. + +=cut + # used to control public or registered developer functionality # to be overriden by subclasses if necessary sub public { return 0 }; Modified: trunk/lib/Smolder/DB.pm =================================================================== --- trunk/lib/Smolder/DB.pm 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/lib/Smolder/DB.pm 2009-03-28 22:21:22 UTC (rev 861) @@ -1,27 +1,28 @@ package Smolder::DB; use strict; use warnings; -use Smolder::DBPlatform; -use Smolder::Conf qw(DBName DBUser DBPass DBHost DBPlatform); - -our $DB_PLATFORM; - -BEGIN { - $DB_PLATFORM = Smolder::DBPlatform->load(); -} -use base $DB_PLATFORM->cdbi_class; +use Smolder::Conf; +use base 'Class::DBI::SQLite'; use DBI; use Class::DBI::Plugin::RetrieveAll; -use Smolder::DBPlatform; +use File::Spec::Functions qw(catfile); __PACKAGE__->connection( - $DB_PLATFORM->connection_options( - user => DBUser, - passwd => DBPass, - host => (DBHost || ''), - db_name => DBName, - ) + "dbi:SQLite:dbname=" . __PACKAGE__->db_file(), + '', '', + { + RaiseError => 1, + PrintError => 0, + Warn => 0, + PrintWarn => 0, + AutoCommit => 1, + FetchHashKeyName => 'NAME_lc', + ShowErrorStatement => 1, + ChopBlanks => 1, + RootClass => 'DBIx::ContextualFetch', + } ); + =head1 NAME @@ -105,10 +106,18 @@ =cut +# SQLite doesn't support enums, so we just have to maintain this table +my %ENUMS = ( + preference => { + email_type => [qw(full summary link)], + email_freq => [qw(on_new on_fail never)], + }, + project => { graph_start => [qw(project year month week day)], }, + smoke_report => { format => [qw(XML YAML)], }, +); sub enum_values { - my $self = shift; - my $db_platform = Smolder::DBPlatform->load(DBPlatform); - my ( $table, $column ); + my $self = shift; + my ($table, $column); if ( ref $self || $self ne __PACKAGE__ ) { $table = $self->table(); @@ -116,11 +125,7 @@ $table = shift; } $column = shift; - - return $db_platform->get_enum_values( - table => $table, - column => $column, - ); + return $ENUMS{$table}->{$column} || []; } =head2 column_values @@ -191,7 +196,7 @@ =head2 retrieve_all_sorted_by($column_name) This object methed is exported from L<Class::DBI::Plugin::RetrieveAll>. It takes -a name of the mysql data field that you wish to sort by. Otherwise it works +a name of the data field that you wish to sort by. Otherwise it works like a normal Class::DBI retrieve_all. Please see L<Class::DBI::Plugin::RetrieveAll> or more details. @@ -201,8 +206,196 @@ auto-sorted by the specified column. Please see L<Class::DBI::Plugin::RetrieveAll> for more details. + +=head2 db_file + +Returns the full path to the SQLite DB file. + =cut +sub db_file { + return catfile( Smolder::Conf->data_dir, "smolder.sqlite" ); +} + +=head2 run_sql_file + +Given the runs the SQL contained in the file against out SQLite DB + + Smolder::DB->run_sql_file('/usr/local/smolder/foo.sql'); + +=cut + +sub run_sql_file { + my ( $class, $file) = @_; + open( my $IN, $file ) or die "Could not open file '$file' for reading: $!"; + + require Smolder::DB; + my $dbh = Smolder::DB->db_Main(); + + my $sql = ''; + + # read each line + while ( my $line = <$IN> ) { + + # skip comments + next if ( $line =~ /^--/ ); + $sql .= $line; + + # if we have a ';' at the end of the line then it should + # be the end of the statement + if ( $line =~ /;\s*$/ ) { + $dbh->do($sql) + or die "Could not execute SQL '$sql': $!"; + $sql = ''; + } + } + + close($file); +} + +=head2 dump_database + +Given the filename of where to put the dump, this method will create the SQL necessary +to restore the database to it's present state including all schema creationg statements. + + Smolder::DB->dump_database('/usr/local/smolder/dump.sql'); + +=cut + +sub dump_database { + my ($class, $file) = @_; + # open the file we want to print to + open( my $OUT, '>', $file ) + or die "Could not open file '$file' for writing: $!"; + + # get the list of tables + require Smolder::DB; + my $dbh = Smolder::DB->db_Main(); + my $sth = $dbh->prepare( + q( + SELECT name FROM sqlite_master WHERE type = 'table' + AND name NOT LIKE 'sqlite_%' AND sql NOT NULL + ) + ); + $sth->execute(); + my ( @tables, $table ); + $sth->bind_col( 1, \$table ); + while ( $sth->fetch ) { + push( @tables, $table ); + } + $sth->finish(); + + # now get the SQL for each table and output it + foreach my $t (@tables) { + + # first the schema + $sth = $dbh->prepare( + q( + SELECT sql FROM sqlite_master + WHERE type = 'table' AND name = ? + ) + ); + $sth->execute($t); + my $sql; + $sth->bind_col( 1, \$sql ); + while ( $sth->fetch ) { + print $OUT "$sql;\n"; + } + $sth->finish(); + + # now the indexes + $sth = $dbh->prepare( + q( + SELECT sql FROM sqlite_master + WHERE type = 'index' AND tbl_name = ? + ) + ); + $sth->execute($t); + $sth->bind_col( 1, \$sql ); + while ( $sth->fetch ) { + print $OUT "$sql;\n" if ($sql); + } + $sth->finish(); + print $OUT "\n\n"; + + # now get all of the data in this table + $sth = $dbh->prepare(qq(SELECT * FROM $t)); + $sth->execute(); + while ( my $row = $sth->fetchrow_arrayref ) { + + # massage each value so we can create the SQL + my @values; + foreach my $value (@$row) { + + # NULLs + if ( !defined $value ) { + $value = 'NULL'; + + # escape and quote it + } else { + $value =~ s/"/\\"/g; + $value = qq("$value"); + } + push( @values, $value ); + } + + # create the SQL + my $sql = "INSERT INTO $t VALUES (" . join( ', ', @values ) . ");\n"; + print $OUT $sql; + } + + print $OUT "\n\n"; + } + close($OUT); +} + +=head2 create_database + +This method will create a brand new, completely empty database file for Smolder. + + Smolder::DB->create_database(); + +=cut + +sub create_database { + my $class = shift; + my $file = $class->db_file(); + + # create a new file by this name whether it exists or not + open( FH, ">$file" ) or die "Could not open file '$file' for writing: $!"; + close(FH) or die "Could not close file '$file': $!"; + + my $sql_dir = Smolder::Conf->sql_dir; + my @files = glob("$sql_dir/*.sql"); + foreach my $file (@files) { + eval { $class->run_sql_file($file) }; + die "Couldn't load SQL file $file! $@" if $@; + } + + # Set the db_version + my $version = $Smolder::VERSION; + my $dbh = $class->db_Main; + eval { $dbh->do("UPDATE db_version set db_version=$version") }; + die "Could not update db_version! $@" if $@; +} + +=head2 unique_failure_msg + +Given a DB failure message, will return true if the message was a failure due to a +failed UNIQUE contstraint, else will return false. + + eval { $class->create(%args) }; + if( $@ ) { + die unless Smolder::DB->unique_failure_msg($@); + } + +=cut + +sub unique_failure_msg { + my ( $class, $msg ) = @_; + return $msg =~ /not unique\(/i; +} + 1; __END__ @@ -215,7 +408,7 @@ =item L<Class::DBI> -=item L<Class::DBI::mysql> +=item L<Class::DBI::SQLite> =item L<Class::DBI::Plugin::RetrieveAll> Deleted: trunk/lib/Smolder/DBPlatform.pm =================================================================== --- trunk/lib/Smolder/DBPlatform.pm 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/lib/Smolder/DBPlatform.pm 2009-03-28 22:21:22 UTC (rev 861) @@ -1,307 +0,0 @@ -package Smolder::DBPlatform; -use strict; -use warnings; -use Carp qw(croak); - -use File::Spec::Functions qw(catdir catfile canonpath); - -# these are needed for Class::DBI to recognize the db handle properly -our %CONNECT_OPTIONS = ( - RaiseError => 1, - PrintError => 0, - Warn => 0, - PrintWarn => 0, - AutoCommit => 1, - FetchHashKeyName => 'NAME_lc', - ShowErrorStatement => 1, - ChopBlanks => 1, - RootClass => 'DBIx::ContextualFetch', -); - -=head1 NAME - -Smolder::DBPlatform - base class for Database platform build modules - -=head1 SYNOPSIS - - package Smolder::DBPlatform::MySQL; - use base 'Smolder::DBPlatform'; - -=head1 DESCRIPTION - -This module serves as a base class for the Database platform modules -which help to abstract away the database dependent constructs so -that Smolder can just operate without DB specific knowledge. -See F<docs/db_abstraction.pod> for more details on how the DB abstraction -works. - -=head1 METHODS - -This module is meant to be used as a base class, so the interface -consists of methods which should be overridden. Unless otherwise specified -each method is abstract. - -All methods are called as class methods. DB Platform modules are free to -use package variables to hold information between calls. - -=head2 load - -This method will look at the C<DBPlatform> configuration directive in -smolder.conf and determine which subclass to use, load it and return it. - - my $db_platform = Smolder::DBPlatform->load(); - -Or if you know the specific DB platform that you want you can just pass it -in. - - my $mysql_platform = Smolder::DBPlatform->load('MySQL'); - -=cut - -sub load { - my ( $class, $type ) = @_; - - # get the type from the config if we don't already have it - unless ($type) { - require Smolder::Conf; - $type = Smolder::Conf->get('DBPlatform'); - } - - # load the class if we can - my $subclass = 'Smolder::DBPlatform::' . $type; - eval "require $subclass"; - if ($@) { - croak "Failed to load $subclass. $@\n\nMaybe '$type' isn't a supported database?"; - } - return $subclass; -} - -=head2 verify_dependencies - -Makes sure all required dependencies are in place before starting the -build, and before beginning installation. The C<mode> parameter will -be either "build" or "install" depending on when the method is called. - -This method should either succeed or die() with a message for the -user. - -This should search for any required shared object files and header files -using L<Smolder::Platform>'s <check_libs()> method. - - $db_platform->verify_dependencies(mode => 'install') - -=cut - -sub verify_dependencies { - my $class = shift; - die "verify_dependencies() must be implemented in $class"; -} - -=head2 verify_admin - -Given the password, hostname and database name, returns true if those credentials -can be used for administrative access to the database. - - $db_platform->verify_admin( - passwd => $pw, - host => 'localhost', - db_name => 'smolder', - ); - -=cut - -sub verify_admin { - my $class = shift; - die "verify_admin() must be implemented in $class"; -} - -=head2 run_sql_file - -Given the DB username, password, hostname, database name and full file name, runs the SQL -contained in the file. - - $db_platform->run_sql_file( - user => $user, - passwd => $pw, - host => $host, - db_name => 'smolder', - file => '/usr/local/smolder/foo.sql', - ); - -=cut - -sub run_sql_file { - my $class = shift; - die "run_sql_file() must be implemented in $class"; -} - -=head2 dbh - -Given the username, password, database name and host name will return the appropriate -database handle. - - my $dbh = $db_platform->dbh( - user => 'smolder', - passwd => 's3cr3t', - db_name => 'smolder', - host => 'localhost', - ); - -=cut - -sub dbh { - my $class = shift; - die "dbh() must be implemented in $class"; -} - -=head2 dbi_driver - -Returns the class name of the C<DBI> driver that this DBPlatform module uses. - -=cut - -sub dbi_driver { - my $class = shift; - die "dbi_driver() must be implemented in $class"; -} - -=head2 cdbi_class - -Returns the class name of the C<Class::DBI> driver that this DBPlatform module uses. - -=cut - -sub cdbi_class { - my $class = shift; - die "cdbi_class() must be implemented in $class"; -} - -=head2 dump_database - -Given the filename of where to put the dump, this method will create the SQL necessary -to restore the database to it's present state including all schema creationg statements. - - $db_platform->dump_database('/usr/local/smolder/dump.sql'); - -=cut - -sub dump_database { - my $class = shift; - die "dump_database() must be implemented in $class"; -} - -=head2 drop_database - -Given the password of the database admin user, the hostname and database name, will drop the -existing database. - - $db_platform->drop_database( - admin_password => 's3cr3t', - host => 'localhost', - db_name => 'smolder', - ); - -=cut - -sub drop_database { - my $class = shift; - die "drop_database() must be implemented in $class"; -} - -=head2 create_database - -Given the password of the database admin user, the hostname and database name, will create -the initial database. - - $db_platform->create_database( - admin_password => 's3cr3t', - host => 'localhost', - db_name => 'smolder', - ); - -=cut - -sub create_database { - my $class = shift; - die "create_database() must be implemented in $class"; -} - -=head2 create_user - -Given the password of the database admin user, the hostname, the database name, the new user's -username and password, will create a new database user with access to the database. - - $db_platform->create_user( - admin_passwd => $admin_password, - host => $db_host, - db_name => $db_name, - user => $db_user, - passwd => $db_pass, - ); - -=cut - -sub create_user { - my $class = shift; - die "create_user() must be implemented in $class"; -} - -=head2 sql_create_dir - -Returns the full path to the directory containing the SQL files for the creation -of the database for the particular DB driver being used. - -=cut - -sub sql_create_dir { - my $class = shift; - die "sql_create_dir() must be implemented in $class"; -} - -=head2 sql_upgrade_dir - -Returns the full path to the directory containing the SQL files for the upgrade -of the database for the particular DB driver being used. - -=cut - -sub sql_upgrade_dir { - my $class = shift; - die "sql_upgrade_dir() must be implemented in $class"; -} - -=head2 get_enum_values - -Given the table and column names will return all legal values if that column -is an ENUM type as an arrayref. - - my $values = $db_platform->get_enum_values( - table => $table, - column => $column, - ); - -=cut - -sub get_enum_values { - my $class = shift; - die "get_enum_values() must be implemented in $class"; -} - -=head2 unique_failure_msg - -Given a DB failure message, will return true if the message was a failure due to a -failed UNIQUE contstraint, else will return false. - - eval { $class->create(%args) }; - if( $@ ) { - die unless $db_platform->unique_failure_msg($@); - } - -=cut - -sub unique_failure_msg { - my $class = shift; - die "unique_failure_msg() must be implemented in $class"; -} - -1; Modified: trunk/lib/Smolder/Mech.pm =================================================================== --- trunk/lib/Smolder/Mech.pm 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/lib/Smolder/Mech.pm 2009-03-28 22:21:22 UTC (rev 861) @@ -2,7 +2,7 @@ use strict; use warnings; use base 'Test::WWW::Mechanize'; -use Smolder::Conf qw(DBPlatform); +use Smolder::Conf; use Smolder::TestData qw(base_url); use JSON qw(from_json); use Test::Builder; @@ -84,9 +84,7 @@ sub get { my $self = shift; - if ( DBPlatform eq 'SQLite' ) { - Smolder::DB->disconnect(); - } + Smolder::DB->disconnect(); return $self->SUPER::get(@_); } @@ -100,9 +98,7 @@ sub submit { my $self = shift; - if ( DBPlatform eq 'SQLite' ) { - Smolder::DB->disconnect(); - } + Smolder::DB->disconnect(); return $self->SUPER::submit(@_); } @@ -116,9 +112,7 @@ sub request { my $self = shift; - if ( DBPlatform eq 'SQLite' ) { - Smolder::DB->disconnect(); - } + Smolder::DB->disconnect(); return $self->SUPER::request(@_); } Modified: trunk/lib/Smolder/Server.pm =================================================================== --- trunk/lib/Smolder/Server.pm 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/lib/Smolder/Server.pm 2009-03-28 22:21:22 UTC (rev 861) @@ -2,23 +2,9 @@ use strict; use warnings; use base 'CGI::Application::Server'; +use File::Spec::Functions qw(catdir devnull); use Smolder::Conf qw(Port HostName LogFile); -use Smolder::Dispatch; -use File::Spec::Functions qw(catdir devnull); -# load all of our controller modules so they are in memory -use Smolder::Control; -use Smolder::Control::Admin; -use Smolder::Control::Admin::Developers; -use Smolder::Control::Admin::Projects; -use Smolder::Control::Developer; -use Smolder::Control::Developer::Graphs; -use Smolder::Control::Developer::Prefs; -use Smolder::Control::Developer::Projects; -use Smolder::Control::Public; -use Smolder::Control::Public::Auth; -use Smolder::Control::Public::Graphs; -use Smolder::Control::Public::Projects; -use Smolder::Redirect; +use Smolder::DB; sub new { my $class = shift; @@ -27,14 +13,6 @@ $server->port(Port); my $htdocs = Smolder::Conf->htdocs_dir; - # if we need to do logging - my $log_file = LogFile || devnull(); - my $ok = open(STDERR, '>>', $log_file); - if( !$ok ) { - warn "Could not open logfile $log_file for appending: $!"; - exit(1); - } - $server->entry_points( { '/' => 'Smolder::Redirect', @@ -59,9 +37,34 @@ my $self = shift; # do we have a database? If not then create one + Smolder::DB->create_database unless -e Smolder::DB->db_file; # check the DB version to make sure that we don't need to upgrade + # preload our perl modules + require Smolder::Dispatch; + require Smolder::Control; + require Smolder::Control::Admin; + require Smolder::Control::Admin::Developers; + require Smolder::Control::Admin::Projects; + require Smolder::Control::Developer; + require Smolder::Control::Developer::Graphs; + require Smolder::Control::Developer::Prefs; + require Smolder::Control::Developer::Projects; + require Smolder::Control::Public; + require Smolder::Control::Public::Auth; + require Smolder::Control::Public::Graphs; + require Smolder::Control::Public::Projects; + require Smolder::Redirect; + + # send warnings to our logs + my $log_file = LogFile || devnull(); + my $ok = open(STDERR, '>>', $log_file); + if( !$ok ) { + warn "Could not open logfile $log_file for appending: $!"; + exit(1); + } + return $self->run(); # return $self->background(); } Modified: trunk/lib/Smolder/Upgrade.pm =================================================================== --- trunk/lib/Smolder/Upgrade.pm 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/lib/Smolder/Upgrade.pm 2009-03-28 22:21:22 UTC (rev 861) @@ -2,7 +2,7 @@ use warnings; use strict; -use Smolder::Conf qw(DBName DBUser DBHost DBPass DBPlatform); +use Smolder::Conf; use File::Spec::Functions qw(catfile catdir); use Smolder::DB; use Carp qw(croak); Modified: trunk/smolder.conf.example =================================================================== --- trunk/smolder.conf.example 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/smolder.conf.example 2009-03-28 22:21:22 UTC (rev 861) @@ -1,27 +1,12 @@ -# Database platform: can be 'MySQL' or 'SQLite', but please use SQLite -DBPlatform "SQLite" -# Database name, host, user and password for Smolder. Only needed -# if you are using MySQL as the DBPlatform -#DBUser "smolder" -#DBPass "smolder" -#DBName "smolder" -#DBHost "localhost" -# Port that the Smolder HTTP server runs on Port 8080 -# HostName: the virtual host for the Smolder server. HostName "smolder.test" -#LogFile '/home/mpeters/development/smolder/logs/smolder.log' -# Email address used as the 'From' address on all outgoing emails +LogFile '/home/mpeters/development/smolder/logs/smolder.log' FromAddress 'smolder@smolder.test' -# Host name of the SMTP server #SMTPHost 127.0.0.1 -# ProjectFullReportsMax: this sets the limit of the number of full -# reports (compressed XML files) we should save. All summary data is -# stored, even after this limit is reached, but we would loose the -# ability to view the details of those that have been purged. This -# directive mainly exists to save disk space for very active projects -# A value of '0' means that there is no limit. ProjectFullReportsMax 50 -# A secret key used for encrypting various bits (auth tokens, etc) Secret "219fdh210kak1@)_492js" +TemplateDir '/home/mpeters/development/smolder/templates' +DataDir '/home/mpeters/development/smolder/data' +HtdocsDir '/home/mpeters/development/smolder/htdocs' +SQLDir '/home/mpeters/development/smolder/sql' Copied: trunk/sql/db_version.sql (from rev 857, trunk/sql/sqlite/db_version.sql) =================================================================== --- trunk/sql/db_version.sql (rev 0) +++ trunk/sql/db_version.sql 2009-03-28 22:21:22 UTC (rev 861) @@ -0,0 +1,5 @@ +CREATE TABLE db_version ( + db_version TEXT NOT NULL +); + +INSERT INTO db_version VALUES ("1.3"); Copied: trunk/sql/developer.sql (from rev 857, trunk/sql/sqlite/developer.sql) =================================================================== --- trunk/sql/developer.sql (rev 0) +++ trunk/sql/developer.sql 2009-03-28 22:21:22 UTC (rev 861) @@ -0,0 +1,18 @@ +CREATE TABLE developer ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT DEFAULT '', + fname TEXT DEFAULT '', + lname TEXT DEFAULT '', + email TEXT DEFAULT '', + password TEXT DEFAULT '', + admin INTEGER DEFAULT 0, + preference INTEGER NOT NULL, + guest INTEGER DEFAULT 0, + CONSTRAINT 'fk_developer_preference' FOREIGN KEY ('preference') REFERENCES 'preference' ('id') +); + +CREATE INDEX i_preference_developer on developer (preference); +CREATE UNIQUE INDEX unique_username_developer on developer (username); + +INSERT INTO developer (id, username, fname, lname, email, password, admin, preference, guest) VALUES (1, 'admin', 'Joe', 'Admin', 'te...@te...', 'YhKDbhvT1LKkg', 1, 1, 0); +INSERT INTO developer (id, username, fname, lname, email, password, admin, preference, guest) VALUES (2, 'anonymous', '', '', '', '', 0, 2, 1); Deleted: trunk/sql/insert.sql =================================================================== --- trunk/sql/insert.sql 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/sql/insert.sql 2009-03-28 22:21:22 UTC (rev 861) @@ -1,5 +0,0 @@ -INSERT INTO db_version VALUES ("1.3"); -INSERT INTO preference (id) VALUES (1); -INSERT INTO preference (id) VALUES (2); -INSERT INTO developer (id, username, fname, lname, email, password, admin, preference, guest) VALUES (1, 'admin', 'Joe', 'Admin', 'te...@te...', 'YhKDbhvT1LKkg', 1, 1, 0); -INSERT INTO developer (id, username, fname, lname, email, password, admin, preference, guest) VALUES (2, 'anonymous', '', '', '', '', 0, 2, 1); Copied: trunk/sql/preference.sql (from rev 857, trunk/sql/sqlite/preference.sql) =================================================================== --- trunk/sql/preference.sql (rev 0) +++ trunk/sql/preference.sql 2009-03-28 22:21:22 UTC (rev 861) @@ -0,0 +1,12 @@ +CREATE TABLE preference ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + email_type TEXT DEFAULT 'full', + email_freq TEXT DEFAULT 'on_new', + email_limit INT DEFAULT 0, + email_sent INT DEFAULT 0, + email_sent_timestamp INTEGER +); + +INSERT INTO preference (id) VALUES (1); +INSERT INTO preference (id) VALUES (2); + Copied: trunk/sql/project.sql (from rev 857, trunk/sql/sqlite/project.sql) =================================================================== --- trunk/sql/project.sql (rev 0) +++ trunk/sql/project.sql 2009-03-28 22:21:22 UTC (rev 861) @@ -0,0 +1,14 @@ +CREATE TABLE project ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + start_date INTEGER NOT NULL, + public INTEGER DEFAULT 1, + enable_feed INTEGER DEFAULT 1, + default_platform TEXT DEFAULT '', + default_arch TEXT DEFAULT '', + graph_start TEXT DEFAULT 'project', + allow_anon INTEGER DEFAULT 0 +); + +CREATE UNIQUE INDEX i_project_name_project on project (name); + Copied: trunk/sql/project_developer.sql (from rev 857, trunk/sql/sqlite/project_developer.sql) =================================================================== --- trunk/sql/project_developer.sql (rev 0) +++ trunk/sql/project_developer.sql 2009-03-28 22:21:22 UTC (rev 861) @@ -0,0 +1,16 @@ +CREATE TABLE project_developer ( + project INTEGER NOT NULL, + developer INTEGER NOT NULL, + preference INTEGER, + admin INTEGER DEFAULT 0, + added INTEGER DEFAULT 0, + PRIMARY KEY (project, developer), + CONSTRAINT 'fk_project_developer_project' FOREIGN KEY ('project') REFERENCES 'project' ('id') ON DELETE CASCADE, + CONSTRAINT 'fk_project_developer_developer' FOREIGN KEY ('developer') REFERENCES 'developer' ('id') ON DELETE CASCADE, + CONSTRAINT 'fk_project_developer_preference' FOREIGN KEY ('preference') REFERENCES 'preference' ('id') +); + +CREATE INDEX i_developer_project_developer on project_developer (developer); +CREATE INDEX i_project_project_developer on project_developer (project); +CREATE INDEX i_preference_project_developer on project_developer (preference); + Copied: trunk/sql/smoke_report.sql (from rev 857, trunk/sql/sqlite/smoke_report.sql) =================================================================== --- trunk/sql/smoke_report.sql (rev 0) +++ trunk/sql/smoke_report.sql 2009-03-28 22:21:22 UTC (rev 861) @@ -0,0 +1,36 @@ +CREATE TABLE smoke_report ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + project INTEGER NOT NULL, + developer INTEGER NOT NULL, + added INTEGER NOT NULL, + architecture TEXT DEFAULT '', + platform TEXT DEFAULT '', + pass INTEGER DEFAULT 0, + fail INTEGER DEFAULT 0, + skip INTEGER DEFAULT 0, + todo INTEGER DEFAULT 0, + todo_pass INTEGER DEFAULT 0, + test_files INTEGER DEFAULT 0, + total INTEGER DEFAULT 0, + comments BLOB DEFAULT '', + invalid INTEGER DEFAULT 0, + invalid_reason BLOB DEFAULT '', + duration INTEGER DEFAULT 0, + purged INTEGER DEFAULT 0, + failed INTEGER DEFAULT 0, + CONSTRAINT 'fk_smoke_report_project' FOREIGN KEY ('project') REFERENCES 'project' ('id') ON DELETE CASCADE, + CONSTRAINT 'fk_smoke_report_developer' FOREIGN KEY ('developer') REFERENCES 'developer' ('id') ON DELETE CASCADE +); + +CREATE INDEX i_project_smoke_report ON smoke_report (project); +CREATE INDEX i_developer_smoke_report ON smoke_report (developer); + +CREATE TABLE smoke_report_tag ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + smoke_report INTEGER NOT NULL, + tag TEXT DEFAULT '', + CONSTRAINT 'fk_smoke_report_tag_smoke_report' FOREIGN KEY ('smoke_report') REFERENCES 'smoke_report' ('id') ON DELETE CASCADE +); + +CREATE INDEX i_project_smoke_tag_tag ON smoke_report_tag (tag); +CREATE INDEX i_report_smoke_report_tag ON smoke_report_tag (smoke_report, tag); Modified: trunk/t/constraints.t =================================================================== --- trunk/t/constraints.t 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/t/constraints.t 2009-03-28 22:21:22 UTC (rev 861) @@ -85,6 +85,7 @@ sub _check_with_dfv { my ( $name, $data, $pass, @args ) = @_; + local $Test::Builder::Level = $Test::Builder::Level + 1; my $sub_name = "Smolder::Constraints::$name"; my $constraint; { Deleted: trunk/t/mysql_iso_level.t =================================================================== --- trunk/t/mysql_iso_level.t 2009-03-28 17:30:55 UTC (rev 860) +++ trunk/t/mysql_iso_level.t 2009-03-28 22:21:22 UTC (rev 861) @@ -1,20 +0,0 @@ -use strict; -use warnings; -use Test::More; -use Smolder::TestScript; -use Smolder::Conf qw(DBPlatform); - -plan(tests => 2); - -SKIP: { - skip('Not using MySQL', 2) if(lc DBPlatform ne 'mysql'); - use_ok("Smolder::DB"); - - # A test to make sure that the isolation level for innodb tables needed - # is READ-COMMITTED or stricter - my $dbh = Smolder::DB->db_Main(); - my $iso_level = $dbh->selectrow_array('SELECT @@global.tx_isolation'); - - like($iso_level, qr/READ-COMMITTED|REPEATABLE-READ|SERIALIZABLE/, 'database isolation level'); - $dbh->disconnect(); -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |