Revert "Bug 7167: New version for updatedatabase"

This reverts commit c9cb55ef47.
This commit is contained in:
Jared Camins-Esakov 2012-12-27 14:02:56 -05:00
parent 72f9f2239f
commit 7535f2bfa3
17 changed files with 99 additions and 1297 deletions

View file

@ -28,7 +28,6 @@ require Exporter;
use C4::Context;
use C4::Templates; # to get the template
use C4::Branch; # GetBranches
use C4::Update::Database;
use C4::VirtualShelves;
use POSIX qw/strftime/;
use List::MoreUtils qw/ any /;
@ -135,9 +134,9 @@ sub get_template_and_user {
my $in = shift;
my $template =
C4::Templates::gettemplate( $in->{'template_name'}, $in->{'type'}, $in->{'query'} );
my ( $user, $cookie, $sessionID, $flags, $new_session );
my ( $user, $cookie, $sessionID, $flags );
if ( $in->{'template_name'} !~m/maintenance/ ) {
( $user, $cookie, $sessionID, $flags, $new_session ) = checkauth(
( $user, $cookie, $sessionID, $flags ) = checkauth(
$in->{'query'},
$in->{'authnotrequired'},
$in->{'flagsrequired'},
@ -469,12 +468,6 @@ sub get_template_and_user {
$template->param(OpacPublic => '1') if ($user || C4::Context->preference("OpacPublic"));
}
if ( $new_session ) {
# Check the version and redirect if DB is not up-to-date
version_check($in->{query}, $in->{'type'}, $cookie);
}
return ( $template, $borrowernumber, $cookie, $flags);
}
@ -556,6 +549,50 @@ has authenticated.
=cut
sub _version_check {
my $type = shift;
my $query = shift;
my $version;
# If Version syspref is unavailable, it means Koha is beeing installed,
# and so we must redirect to OPAC maintenance page or to the WebInstaller
# also, if OpacMaintenance is ON, OPAC should redirect to maintenance
if (C4::Context->preference('OpacMaintenance') && $type eq 'opac') {
warn "OPAC Install required, redirecting to maintenance";
print $query->redirect("/cgi-bin/koha/maintenance.pl");
safe_exit;
}
unless ( $version = C4::Context->preference('Version') ) { # assignment, not comparison
if ( $type ne 'opac' ) {
warn "Install required, redirecting to Installer";
print $query->redirect("/cgi-bin/koha/installer/install.pl");
} else {
warn "OPAC Install required, redirecting to maintenance";
print $query->redirect("/cgi-bin/koha/maintenance.pl");
}
safe_exit;
}
# check that database and koha version are the same
# there is no DB version, it's a fresh install,
# go to web installer
# there is a DB version, compare it to the code version
my $kohaversion=C4::Context::KOHAVERSION;
# remove the 3 last . to have a Perl number
$kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/;
$debug and print STDERR "kohaversion : $kohaversion\n";
if ($version < $kohaversion){
my $warning = "Database update needed, redirecting to %s. Database is $version and Koha is $kohaversion";
if ($type ne 'opac'){
warn sprintf($warning, 'Installer');
print $query->redirect("/cgi-bin/koha/installer/install.pl?step=3");
} else {
warn sprintf("OPAC: " . $warning, 'maintenance');
print $query->redirect("/cgi-bin/koha/maintenance.pl");
}
safe_exit;
}
}
sub _session_log {
(@_) or return 0;
open my $fh, '>>', "/tmp/sessionlog" or warn "ERROR: Cannot append to /tmp/sessionlog";
@ -572,38 +609,6 @@ sub _timeout_syspref {
return $timeout;
}
sub version_check {
my ( $query, $type, $cookie ) = @_;
# check we have a Version. Otherwise => go to installer
unless ( C4::Context->preference('Version') ) {
if ( $type ne 'opac' ) {
$debug && warn "Install required, redirecting to Installer";
print $query->redirect("/cgi-bin/koha/installer/install.pl");
} else {
$debug && warn "OPAC Install required, redirecting to maintenance";
print $query->redirect("/cgi-bin/koha/maintenance.pl");
}
safe_exit;
}
# check if you're uptodate, and if you're not, head to updater
my $koha39 = "3.0900028";
# Old updatedatabase method
if (C4::Context->preference('Version') < $koha39) {
print $query->redirect("/cgi-bin/koha/installer/install.pl?step=3");
safe_exit;
}
# New updatedatabase method
unless ( C4::Update::Database::is_uptodate() ) {
# not up-to-date, redirect to updatedatabase page
warn "redirect to updatedatabase";
print $query->redirect(-location => "/cgi-bin/koha/admin/updatedatabase.pl", -cookie => $cookie);
safe_exit;
}
}
sub checkauth {
my $query = shift;
$debug and warn "Checking Auth";
@ -612,16 +617,11 @@ sub checkauth {
my $flagsrequired = shift;
my $type = shift;
$type = 'opac' unless $type;
my $new_session = 0;
my $dbh = C4::Context->dbh;
my $timeout = _timeout_syspref();
# days
if ($timeout =~ /(\d+)[dD]/) {
$timeout = $1 * 86400;
};
$timeout = 600 unless $timeout;
_version_check($type,$query);
# state variables
my $loggedin = 0;
my %info;
@ -725,7 +725,6 @@ sub checkauth {
my $sessionID = $session->id;
C4::Context->_new_userenv($sessionID);
$cookie = $query->cookie( CGISESSID => $sessionID );
$userid = $query->param('userid');
if ( ( $cas && $query->param('ticket') )
|| $userid
@ -740,7 +739,6 @@ sub checkauth {
checkpw( $dbh, $userid, $password, $query );
$userid = $retuserid;
$info{'invalidCasLogin'} = 1 unless ($return);
$new_session = 1;
}
elsif (
( $pki_field eq 'Common Name' && $ENV{'SSL_CLIENT_S_DN_CN'} )
@ -779,7 +777,6 @@ sub checkauth {
( $return, $cardnumber, $retuserid ) =
checkpw( $dbh, $userid, $password, $query );
$userid = $retuserid if ( $retuserid ne '' );
$new_session = 1;
}
if ($return) {
#_session_log(sprintf "%20s from %16s logged in at %30s.\n", $userid,$ENV{'REMOTE_ADDR'},(strftime '%c', localtime));
@ -921,7 +918,7 @@ sub checkauth {
unless ($cookie) {
$cookie = $query->cookie( CGISESSID => '' );
}
return ( $userid, $cookie, $sessionID, $flags, $new_session );
return ( $userid, $cookie, $sessionID, $flags );
}
#
@ -1066,6 +1063,19 @@ sub check_api_auth {
my $dbh = C4::Context->dbh;
my $timeout = _timeout_syspref();
unless (C4::Context->preference('Version')) {
# database has not been installed yet
return ("maintenance", undef, undef);
}
my $kohaversion=C4::Context::KOHAVERSION;
$kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/;
if (C4::Context->preference('Version') < $kohaversion) {
# database in need of version update; assume that
# no API should be called while databsae is in
# this condition.
return ("maintenance", undef, undef);
}
# FIXME -- most of what follows is a copy-and-paste
# of code from checkauth. There is an obvious need
# for refactoring to separate the various parts of
@ -1285,6 +1295,19 @@ sub check_cookie_auth {
my $dbh = C4::Context->dbh;
my $timeout = _timeout_syspref();
unless (C4::Context->preference('Version')) {
# database has not been installed yet
return ("maintenance", undef);
}
my $kohaversion=C4::Context::KOHAVERSION;
$kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/;
if (C4::Context->preference('Version') < $kohaversion) {
# database in need of version update; assume that
# no API should be called while databsae is in
# this condition.
return ("maintenance", undef);
}
# FIXME -- most of what follows is a copy-and-paste
# of code from checkauth. There is an obvious need
# for refactoring to separate the various parts of

View file

@ -23,7 +23,6 @@ use strict;
our $VERSION = 3.07.00.049;
use C4::Context;
use C4::Installer::PerlModules;
use C4::Update::Database;
=head1 NAME
@ -467,15 +466,7 @@ Koha software version.
sub set_version_syspref {
my $self = shift;
# get all updatedatabase, and mark them as passed, as it's a fresh install
my $versions = C4::Update::Database::list_versions_available();
for my $v ( @$versions ) {
my $queries;
$queries->{queries} = ["initial setup"];
$queries->{comments} = ["initial setup"];
C4::Update::Database::set_infos($v,$queries,undef,undef);
}
# mark the "old" 3.6 version number
my $kohaversion=C4::Context::KOHAVERSION;
# remove the 3 last . to have a Perl number
$kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/;

View file

@ -628,17 +628,12 @@ our $PERL_DEPS = {
'usage' => 'Core',
'required' => '0',
'min_ver' => '1.09',
},
},
'String::Random' => {
'usage' => 'OpacSelfRegistration',
'required' => '0',
'min_ver' => '0.22',
},
'File::Find::Rule' => {
'usage' => 'Core',
'required' => '1',
'min_ver' => '0.33',
},
};
1;

View file

@ -1,554 +0,0 @@
package C4::Update::Database;
# Copyright Biblibre 2012
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use Modern::Perl;
use C4::Context;
use File::Basename;
use File::Find::Rule;
use Digest::MD5;
use List::MoreUtils qw/uniq/;
use YAML;
=head1 NAME
C4::Update::Database.pm
=head1 SYNOPSIS
use C4::Update::Database;
This package is used by admin/updatedatabase.pl, to manage DB updates
=head1 FUNCTIONS
=cut
my $VERSIONS_PATH = C4::Context->config('intranetdir') . '/installer/data/mysql/versions';
my $version;
my $list;
my $dbh = C4::Context->dbh;
=head2 get_filepath
my $file = get_filepath($version);
this sub will return the full path of a given DB update number
=cut
sub get_filepath {
my ( $version ) = @_;
my @files = File::Find::Rule->file->name( "$version.sql", "$version.pl" ) ->in( ( $VERSIONS_PATH ) );
if ( scalar @files != 1 ) {
die "This version ($version) returned has ".scalar @files." corresponding, need only 1";
}
return $files[0];
}
=head2 get_md5
my $md5 = get_md5($filepath)
returns the md5sum of the selected file.
This is used to check consistency of updates
=cut
sub get_md5 {
my ( $filepath ) = @_;
open(FILE, $filepath);
my $ctx = Digest::MD5->new;
$ctx->addfile(*FILE);
my $md5 = $ctx->hexdigest;
close(FILE);
return $md5;
}
=head2 execute_version
$result = execute_version($version_number);
Execute an update.
This sub will detect if the number is made through a .pl or a .sql, and behave accordingly
if there is more than 1 file with the same number, an error will be issued
if you try to execute a version_number that has already be executed, then it will also issue an error
the sub return an result hash, with the version number and the result
=cut
sub execute_version {
my ( $version ) = @_;
my $report;
my $filepath;
eval {
$filepath = get_filepath $version;
};
if ( $@ ) {
return { $version => $@ };
}
my @file_infos = fileparse( $filepath, qr/\.[^.]*/ );
my $extension = $file_infos[2];
my $filename = $version . $extension;
my $md5 = get_md5 $filepath;
my $r = md5_already_exists( $md5 );
if ( scalar @$r ) {
my $p = @$r[0];
$report->{$version} = {
error => "ALREADY_EXISTS",
filepath => $filepath,
old_version => @$r[0]->{version},
md5 => @$r[0]->{md5},
};
return $report;
}
my $queries;
given ( $extension ) {
when ( /.sql/ ) {
$queries = get_queries ( $filepath );
}
when ( /.pl/ ) {
eval {
$queries = get_queries ( $filepath );
};
if ($@) {
$report->{$version} = {
error => "LOAD_FUNCTIONS_FAILED",
filename => $filename,
error_str => $@,
};
}
}
default {
$report->{$version} = {
error => "BAD_EXTENSION",
extension => $extension,
};
}
}
return $report
if ( defined $report->{$version} );
my $errors = execute ( $queries );
$report->{$version} = scalar( @$errors ) ? $errors : "OK";
set_infos ( $version, $queries, $errors, $md5 );
return $report;
}
=head2 list_versions_available
my @versions = list_versions_available;
return an array with all version available
=cut
sub list_versions_available {
my @versions;
my @files = File::Find::Rule->file->name( "*.sql", "*.pl" ) ->in( ( $VERSIONS_PATH ) );
for my $f ( @files ) {
my @file_infos = fileparse( $f, qr/\.[^.]*/ );
push @versions, $file_infos[0];
}
@versions = uniq @versions;
return \@versions;
}
=head2 list_versions_already_applied
my @versions = list_versions_available;
return an array with all version that have already been applied
This sub check first that the updatedb tables exist and create them if needed
=cut
sub list_versions_already_applied {
# 1st check if tables exist, otherwise create them
$dbh->do(qq{
CREATE TABLE IF NOT EXISTS `updatedb_error` ( `version` varchar(32) DEFAULT NULL, `error` text ) ENGINE=InnoDB CHARSET=utf8;
});
$dbh->do(qq{
CREATE TABLE IF NOT EXISTS `updatedb_query` ( `version` varchar(32) DEFAULT NULL, `query` text ) ENGINE=InnoDB CHARSET=utf8;
});
$dbh->do(qq{
CREATE TABLE IF NOT EXISTS `updatedb_report` ( `version` text, `md5` varchar(50) DEFAULT NULL, `comment` text, `status` int(1) DEFAULT NULL ) ENGINE=InnoDB CHARSET=utf8;
});
my $query = qq/ SELECT version, comment, status FROM updatedb_report ORDER BY version/;
my $sth = $dbh->prepare( $query );
$sth->execute;
my $versions = $sth->fetchall_arrayref( {} );
map {
my $version = $_;
my @comments = defined $_->{comment} ? split '\\\n', $_->{comment} : "";
push @{ $version->{comments} }, { comment => $_ } for @comments;
delete $version->{comment};
} @$versions;
$sth->finish;
for my $version ( @$versions ) {
$query = qq/ SELECT query FROM updatedb_query WHERE version = ? ORDER BY version/;
$sth = $dbh->prepare( $query );
$sth->execute( $version->{version} );
$version->{queries} = $sth->fetchall_arrayref( {} );
$sth->finish;
$query = qq/ SELECT error FROM updatedb_error WHERE version = ? ORDER BY version/;
$sth = $dbh->prepare( $query );
$sth->execute( $version->{version} );
$version->{errors} = $sth->fetchall_arrayref( {} );
$sth->finish;
}
return $versions;
}
=head2 execute
my @errors = $execute(\@queries);
This sub will execute queries coming from an execute_version based on a .sql file
=cut
sub execute {
my ( $queries ) = @_;
my @errors;
for my $query ( @{$queries->{queries}} ) {
eval {
$dbh->do( $query );
};
push @errors, get_error();
}
return \@errors;
}
=head2 get_tables_name
my $tables = get_tables_name;
return an array with all Koha mySQL table names
=cut
sub get_tables_name {
my $sth = $dbh->prepare("SHOW TABLES");
$sth->execute();
my @tables;
while ( my ( $table ) = $sth->fetchrow_array ) {
push @tables, $table;
}
return \@tables;
}
my $tables;
=head2 check_coherency
my $errors = check_coherency($query); UNUSED
This sub will try to check if a SQL query is useless or no.
for queries that are CREATE TABLE, it will check if the table already exists
for queries that are ALTER TABLE, it will search if the modification has already been made
for queries that are INSERT, it will search if the insert has already been made if it's a syspref or a permission
Those test cover 90% of the updatedatabases cases. That will help finding duplicate or inconsistencies
=cut
#sub check_coherency {
# my ( $query ) = @_;
# $tables = get_tables_name() if not $tables;
#
# given ( $query ) {
# when ( /CREATE TABLE(?:.*?)? `?(\w+)`?/ ) {
# my $table_name = $1;
# if ( grep { /$table_name/ } @$tables ) {
# die "COHERENCY: Table $table_name already exists";
# }
# }
#
# when ( /ALTER TABLE *`?(\w+)`? *ADD *(?:COLUMN)? `?(\w+)`?/ ) {
# my $table_name = $1;
# my $column_name = $2;
# next if $column_name =~ /(UNIQUE|CONSTRAINT|INDEX|KEY|FOREIGN)/;
# if ( not grep { /$table_name/ } @$tables ) {
# return "COHERENCY: Table $table_name does not exist";
# } else {
# my $sth = $dbh->prepare( "DESC $table_name $column_name" );
# my $rv = $sth->execute;
# if ( $rv > 0 ) {
# die "COHERENCY: Field $table_name.$column_name already exists";
# }
# }
# }
#
# when ( /INSERT INTO `?(\w+)`?.*?VALUES *\((.*?)\)/ ) {
# my $table_name = $1;
# my @values = split /,/, $2;
# s/^ *'// foreach @values;
# s/' *$// foreach @values;
# given ( $table_name ) {
# when ( /systempreferences/ ) {
# my $syspref = $values[0];
# my $sth = $dbh->prepare( "SELECT COUNT(*) FROM systempreferences WHERE variable = ?" );
# $sth->execute( $syspref );
# if ( ( my $count = $sth->fetchrow_array ) > 0 ) {
# die "COHERENCY: Syspref $syspref already exists";
# }
# }
#
# when ( /permissions/){
# my $module_bit = $values[0];
# my $code = $values[1];
# my $sth = $dbh->prepare( "SELECT COUNT(*) FROM permissions WHERE module_bit = ? AND code = ?" );
# $sth->execute($module_bit, $code);
# if ( ( my $count = $sth->fetchrow_array ) > 0 ) {
# die "COHERENCY: Permission $code already exists";
# }
# }
# }
# }
# }
# return 1;
#}
=head2 get_error
my $errors = get_error()
This sub will return any mySQL error that occured during an update
=cut
sub get_error {
my @errors = $dbh->selectrow_array(qq{SHOW ERRORS}); # Get errors
my @warnings = $dbh->selectrow_array(qq{SHOW WARNINGS}); # Get warnings
if ( @errors ) { # Catch specifics errors
return qq{$errors[0] : $errors[1] => $errors[2]};
} elsif ( @warnings ) {
return qq{$warnings[0] : $warnings[1] => $warnings[2]}
if $warnings[0] ne 'Note';
}
return;
}
=head2 get_queries
my $result = get_queries($filepath);
this sub will return a hashref with 2 entries:
$result->{queries} is an array with all queries to execute
$result->{comments} is an array with all comments in the .sql file
=cut
sub get_queries {
my ( $filepath ) = @_;
open my $fh, "<", $filepath;
my @queries;
my @comments;
if ( $filepath =~ /\.pl$/ ) {
if ( do $filepath ) {
my $infos = _get_queries();
@queries = @{ $infos->{queries} } if exists $infos->{queries};
@comments = @{ $infos->{comments} } if exists $infos->{comments};
}
if ( $@ ) {
die "I can't load $filepath. Please check the execute flag and if this file is a valid perl script ($@)";
}
} else {
my $old_delimiter = $/;
while ( <$fh> ) {
my $line = $_;
chomp $line;
$line =~ s/^\s*//;
if ( $line =~ /^--/ ) {
my @l = split $old_delimiter, $line;
if ( @l > 1 ) {
my $tmp_query;
for my $l ( @l ) {
if ( $l =~ /^--/ ) {
$l =~ s/^--\s*//;
push @comments, $l;
next;
}
$tmp_query .= $l . $old_delimiter;
}
push @queries, $tmp_query if $tmp_query;
next;
}
$line =~ s/^--\s*//;
push @comments, $line;
next;
}
if ( $line =~ /^delimiter (.*)$/i ) {
$/ = $1;
next;
}
$line =~ s#$/##;
push @queries, $line if not $line =~ /^\s*$/; # Push if query is not empty
}
$/ = $old_delimiter;
close $fh;
}
return { queries => \@queries, comments => \@comments };
}
=head2 md5_already_exists
my $result = md5_already_exists($md5);
check if the md5 of an update has already been applied on the database.
If yes, it will return a hash with the version related to this md5
=cut
sub md5_already_exists {
my ( $md5 ) = @_;
my $query = qq/SELECT version, md5 FROM updatedb_report WHERE md5 = ?/;
my $sth = $dbh->prepare( $query );
$sth->execute( $md5 );
my @r;
while ( my ( $version, $md5 ) = $sth->fetchrow ) {
push @r, { version => $version, md5 => $md5 };
}
$sth->finish;
return \@r;
}
=head2 set_infos
set_info($version,$queries, $error, $md5);
this sub will insert into the updatedb tables what has been made on the database (queries, errors, result)
=cut
sub set_infos {
my ( $version, $queries, $errors, $md5 ) = @_;
SetVersion($version) if not -s $errors;
for my $query ( @{ $queries->{queries} } ) {
my $sth = $dbh->prepare("INSERT INTO updatedb_query(version, query) VALUES (?, ?)");
$sth->execute( $version, $query );
$sth->finish;
}
for my $error ( @$errors ) {
my $sth = $dbh->prepare("INSERT INTO updatedb_error(version, error) VALUES (?, ?)");
$sth->execute( $version, $error );
}
my $sth = $dbh->prepare("INSERT INTO updatedb_report(version, md5, comment, status) VALUES (?, ?, ?, ?)");
$sth->execute(
$version,
$md5,
join ('\n', @{ $queries->{comments} }),
( @$errors > 0 ) ? 0 : 1
);
}
=head2 mark_as_ok
mark_as_ok($version);
this sub will force to mark as "OK" an update that has failed
once this has been made, the status will look as "forced OK", and appear in green like versions that have been applied without any problem
=cut
sub mark_as_ok {
my ( $version ) = @_;
my $sth = $dbh->prepare( "UPDATE updatedb_report SET status = 2 WHERE version=?" );
my $affected = $sth->execute( $version );
if ( $affected < 1 ) {
my $filepath = get_filepath $version;
my $queries = get_queries $filepath;
my $md5 = get_md5 $filepath;
set_infos $version, $queries, undef, $md5;
$sth->execute( $version );
}
$sth->finish;
}
=head2 is_uptodate
is_uptodate();
return 1 if the database is up to date else 0.
The database is up to date if all versions are excecuted.
=cut
sub is_uptodate {
my $versions_available = C4::Update::Database::list_versions_available;
my $versions = C4::Update::Database::list_versions_already_applied;
for my $v ( @$versions_available ) {
if ( not grep { $v eq $$_{version} } @$versions ) {
return 0;
}
}
return 1;
}
=head2 TransformToNum
Transform the Koha version from a 4 parts string
to a number, with just 1 . (ie: it's a number)
=cut
sub TransformToNum {
my $version = shift;
# remove the 3 last . to have a Perl number
$version =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/;
$version =~ s/Bug(\d+)/$1/;
return $version;
}
sub SetVersion {
my $new_version = TransformToNum(shift);
return unless $new_version =~ /\d\.\d+/;
my $current_version = TransformToNum( C4::Context->preference('Version') );
unless ( C4::Context->preference('Version') ) {
my $finish = $dbh->prepare(qq{
INSERT IGNORE INTO systempreferences (variable,value,explanation)
VALUES ('Version',?,'The Koha database version. WARNING: Do not change this value manually, it is maintained by the webinstaller')
});
$finish->execute($new_version);
return;
}
if ( $new_version > $current_version ) {
my $finish = $dbh->prepare("UPDATE systempreferences SET value=? WHERE variable='Version'");
$finish->execute($new_version);
}
}
=head2 TableExists($table)
=cut
sub TableExists {
my $table = shift;
eval {
local $dbh->{PrintError} = 0;
local $dbh->{RaiseError} = 0;
$dbh->do(qq{SELECT * FROM $table WHERE 1 = 0 });
};
return 1 unless $@;
return 0;
}
1;

View file

@ -32,7 +32,6 @@ use C4::Output;
use C4::Auth;
use C4::Context;
use C4::Installer;
use C4::Update::Database;
#use Smart::Comments '####';
@ -48,45 +47,7 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
}
);
my $kohaVersion = C4::Context->preference("Version");
# restore ., for display consistency
$kohaVersion =~ /(.)\.(..)(..)(...)/;
# transform digits to Perl number, to display 3.6.1.2 instead of 3.06.01.002
$kohaVersion = ($1+0).".".($2+0).".".($3+0).".".($4+0);
my $dbrev_applied=""; # the list of database revisions
# the $kohaVersion is duplicated since 3.7: the 3.6 (that uses the old mechanism) and the 3.7 (new mechanism).
# Both versions reflects how the database has been upgraded
my $already_applied = C4::Update::Database::list_versions_already_applied();
# $last_known contains the previous DBrev applied number (all . removed). It's used to have a . instead of a number in case of continuous updates
my $last_known=0;
# $last_known_sep contains the previous DBrev applied with the separator (used for display)
my $last_known_sep="";
for my $v ( @$already_applied ) {
my $current = $v->{version};
$current =~s/\.//g;
# if the current number is the previous one +1, then just add a ., for a better display N.........N+10, for example
# (instead of N / N+1 / N+2 / ...)
if ($current==$last_known+1) {
$dbrev_applied.=".";
} else { # we're not N+1, start a new range
# if version don't end by a ., no need to add the current loop number
# this avoid having N...N (in case of an isolated BDrev number)
if ($last_known & $dbrev_applied =~ /\.$/) {
$dbrev_applied .= "...".$last_known_sep;
}
# start a new range
$dbrev_applied .= " ".$v->{version};
}
$last_known= $current;
$last_known_sep=$v->{version};
}
# add the last DB rev number, we don't want to end with "..."
if ($dbrev_applied =~ /\.$/) {
$dbrev_applied .= "...".$last_known_sep;
}
my $kohaVersion = C4::Context::KOHAVERSION;
my $osVersion = `uname -a`;
my $perl_path = $^X;
if ($^O ne 'VMS') {
@ -115,7 +76,6 @@ my $warnIsRootUser = (! $loggedinuser);
$template->param(
kohaVersion => $kohaVersion,
dbrev_applied => $dbrev_applied,
osVersion => $osVersion,
perlPath => $perl_path,
perlVersion => $perlVersion,

View file

@ -1,60 +0,0 @@
#!/usr/bin/perl
# Copyright BibLibre 2012
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
=head1 NAME
ajax-updatedb-getinfos.pl
=head1 DESCRIPTION
this script returns comments for a updatedatabase version
=cut
use Modern::Perl;
use CGI;
use JSON;
use C4::Update::Database;
use C4::Output;
my $input = new CGI;
my $version = $input->param('version');
my $filepath;
my $queries;
eval {
$filepath = C4::Update::Database::get_filepath( $version );
$queries = C4::Update::Database::get_queries( $filepath );
};
my $param = {comments => "", queries => ""};
if ( $@ ){
$param->{errors} = $@;
} else {
if ( exists $queries->{comments} and @{ $queries->{comments} } ) {
$param->{comments} = join ( "<br/>", @{ $queries->{comments} } );
}
if ( exists $queries->{queries} and @{ $queries->{queries} } ) {
$param->{queries} = join ( "<br/>", @{ $queries->{queries} } );
}
}
my $json_text = to_json( $param, { utf8 => 1 } );
output_with_http_headers $input, undef, $json_text, 'json';

View file

@ -1,101 +0,0 @@
#!/usr/bin/perl
# Copyright Biblibre 2012
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use Modern::Perl;
use CGI;
use C4::Auth;
use C4::Output;
use C4::Update::Database;
my $query = new CGI;
my $op = $query->param('op') || 'list';
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
{ template_name => "admin/updatedatabase.tmpl",
query => $query,
type => "intranet",
authnotrequired => 0,
flagsrequired => { parameters => 1 },
}
);
if ( $op eq 'update' ) {
my @versions = $query->param('version');
@versions = sort {
C4::Update::Database::TransformToNum( $a ) <=> C4::Update::Database::TransformToNum( $b )
} @versions;
my @reports;
for my $version ( @versions ) {
push @reports, C4::Update::Database::execute_version $version;
}
my @report_loop = map {
my ( $v, $r ) = each %$_;
my @errors = ref ( $r ) eq 'ARRAY'
?
map {
{ error => $_ }
} @$r
:
{ error => $r };
{
version => $v,
report => \@errors,
}
} @reports;
$template->param( report_loop => \@report_loop );
$op = 'list';
}
if ( $op eq 'mark_as_ok' ) {
my @versions = $query->param('version');
C4::Update::Database::mark_as_ok $_ for @versions;
$op = 'list';
}
if ( $op eq 'list' ) {
my $versions_available = C4::Update::Database::list_versions_available;
my $versions = C4::Update::Database::list_versions_already_applied;
for my $v ( @$versions_available ) {
if ( not grep { $v eq $$_{version} } @$versions ) {
push @$versions, {
version => $v,
available => 1
};
}
}
my @sorted = sort {
C4::Update::Database::TransformToNum( $$a{version} ) <=> C4::Update::Database::TransformToNum( $$b{version} )
} @$versions;
my @available = grep { defined $$_{available} and $$_{available} == 1 } @sorted;
my @v_available = map { {version => $$_{version}} } @available;
$template->param(
dev_mode => $ENV{DEBUG},
versions => \@sorted,
nb_available => scalar @available,
available => [ map { {version => $$_{version}} } @available ],
);
}
output_html_with_http_headers $query, $cookie, $template->output;

View file

@ -2083,27 +2083,6 @@ CREATE TABLE `tags_index` ( -- a weighted list of all tags and where they are us
REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for database updates
--
CREATE TABLE`updatedb_error` (
`version` varchar(32) DEFAULT NULL,
`error` text
) ENGINE=InnoDB CHARSET=utf8;
CREATE TABLE `updatedb_query` (
`version` varchar(32) DEFAULT NULL,
`query` text
) ENGINE=InnoDB CHARSET=utf8;
CREATE TABLE `updatedb_report` (
`version` text,
`md5` varchar(50) DEFAULT NULL,
`comment` text,
`status` int(1) DEFAULT NULL
) ENGINE=InnoDB CHARSET=utf8;
--
-- Table structure for table `userflags`
--

View file

@ -1,44 +0,0 @@
#!/usr/bin/perl
# You write good Perl, so you start with Modern::Perl, of course
use Modern::Perl;
# then you load Packages that could be usefull
use C4::Context;
# Loading this package is usefull if you need to check if a table exist (TableExists)
use C4::Update::Database;
# you *must* have the sub _get_queries
# it returns an array of all SQL that have to be executed
# this array will be stored "forever" in your Koha database
# thus, you will be able to know which SQL has been executed
# at the time of upgrade. Very handy, because since then
# your database configuration may have changed and you'll wonder
# what has really be executed, not what would be executed today !
# put in an array the SQL to execute
# put in an array the comments
sub _get_queries {
my @queries;
my @comments;
push @comments, "Add sample feature";
unless ( C4::Update::Database::TableExists('testtable') ) {
push @queries, qq{
CREATE TABLE `testtable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`source` text DEFAULT NULL,
`text` mediumtext NOT NULL,
`timestamp` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
};
push @comments, qq { * Added the table testtable that did not exist};
}
push @queries, qq{INSERT IGNORE INTO `systempreferences` (variable,value,explanation,options,type) VALUES('testsyspref1',0,'Enable or disable display of Quote of the Day on the OPAC home page',NULL,'YesNo')};
push @queries, qq{INSERT IGNORE INTO `systempreferences` (variable,value,explanation,options,type) VALUES('testsyspref2',0,'Enable or disable display of Quote of the Day on the OPAC home page',NULL,'YesNo')};
push @comments , qq{ * Added 2 sysprefs};
# return queries and comments
return { queries => \@queries, comments => \@comments };
}
1;

View file

@ -1,27 +0,0 @@
-- This is an example for .sql file
-- all the comments (ie= what is after --) will be identified as comment
-- and displayed as such in Koha updatedatabase interface
-- the .sql is easy: just define a separator if you plan to have multi-line SQL
-- then, your sql
-- basic example, without delimiter defined:
UPDATE systempreferences SET value="something" WHERE variable="TestSysprefBasic";
INSERT INTO itemtypes (itemtype, description) VALUES ('SAMPLE','A description');
-- End of basic sample
-- more complex example, with delimiter defined:
DELIMITER //
-- I've defined a delimiter
-- so I can put SQL on many lines
-- Note that in this sample, the ; at the end of each query is not required.
CREATE TABLE `testtable1` (
`entry` varchar(255) NOT NULL default '',
`weight` bigint(20) NOT NULL default 0,
PRIMARY KEY (`entry`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
//
-- or on a single line, as previously
-- without ; just for the sample
INSERT INTO `systempreferences` VALUES ('TestSyspref1','2','set the level of error info sent to the browser. 0=none, 1=some, 2=most','0|1|2','Choice')
//

View file

@ -312,24 +312,29 @@ elsif ( $step && $step == 3 ) {
# Not 1st install, the only sub-step : update database
#
#Do updatedatabase And report
if ( ! defined $ENV{PERL5LIB} ) {
my $find = "C4/Context.pm";
my $path = $INC{$find};
$path =~ s/\Q$find\E//;
$ENV{PERL5LIB} = "$path:$path/installer";
warn "# plack? inserted PERL5LIB $ENV{PERL5LIB}\n";
if ( ! defined $ENV{PERL5LIB} ) {
my $find = "C4/Context.pm";
my $path = $INC{$find};
$path =~ s/\Q$find\E//;
$ENV{PERL5LIB} = "$path:$path/installer";
warn "# plack? inserted PERL5LIB $ENV{PERL5LIB}\n";
}
my $cmd = C4::Context->config("intranetdir") . "/installer/data/$info{dbms}/updatedatabase.pl";
my ($success, $error_code, $full_buf, $stdout_buf, $stderr_buf) = IPC::Cmd::run(command => $cmd, verbose => 0);
if (@$stdout_buf) {
$template->param(update_report => [ map { { line => $_ } } split(/\n/, join('', @$stdout_buf)) ] );
$template->param(has_update_succeeds => 1);
}
if (@$stderr_buf) {
$template->param(update_errors => [ map { { line => $_ } } split(/\n/, join('', @$stderr_buf)) ] );
$template->param(has_update_errors => 1);
warn "The following errors were returned while attempting to run the updatedatabase.pl script:\n";
foreach my $line (@$stderr_buf) {warn "$line\n";}
}
my $koha39 = "3.0900028";
my $cmd;
# Old updatedatabase method
my $current_version = C4::Context->preference('Version');
if ( $current_version < $koha39 ) {
$cmd = C4::Context->config("intranetdir") . "/installer/data/$info{dbms}/updatedatabase.pl";
my ($success, $error_code, $full_buf, $stdout_buf, $stderr_buf) = IPC::Cmd::run(command => $cmd, verbose => 0);
print_std( "updatedatabase.pl", $stdout_buf, $stderr_buf );
$current_version= $koha39;
}
$template->param( $op => 1 );
}
else {
@ -401,20 +406,4 @@ else {
}
}
}
sub print_std {
my ( $script, $stdout_buf, $stderr_buf ) = @_;
if (@$stdout_buf) {
$template->param(update_report => [ map { { line => $_ } } split(/\n/, join('', @$stdout_buf)) ] );
$template->param(has_update_succeeds => 1);
}
if (@$stderr_buf) {
$template->param(update_errors => [ map { { line => $_ } } split(/\n/, join('', @$stderr_buf)) ] );
$template->param(has_update_errors => 1);
warn "The following errors were returned while attempting to run the $script script:\n";
foreach my $line (@$stderr_buf) {warn "$line\n";}
}
}
output_html_with_http_headers $query, $cookie, $template->output;

View file

@ -2042,14 +2042,6 @@ div.pager p {
margin: 0;
}
tr.dragClass td {
background-color: grey;
color: yellow;
}
.underline {
text-decoration : underline;
}
div#acqui_order_supplierlist > div.supplier {
border: 1px solid #EEEEEE;
margin: 0.5em;

View file

@ -37,7 +37,7 @@
<table>
<caption>Server information</caption>
<tr><th scope="row">Koha version: </th><td>[% kohaVersion |html %] with the following database revisions applied: [% dbrev_applied|html %]</td></tr>
<tr><th scope="row">Koha version: </th><td>[% kohaVersion |html %]</td></tr>
<tr><th scope="row">OS version ('uname -a'): </th><td>[% osVersion |html %]</td></tr>
<tr><th scope="row">Perl interpreter: </th><td>[% perlPath |html %]</td></tr>
<tr><th scope="row">Perl version: </th><td>[% perlVersion |html %]</td></tr>

View file

@ -110,13 +110,6 @@
<dt><a href="/cgi-bin/koha/admin/didyoumean.pl">Did you mean?</a></dt>
<dd>Choose which plugins to use to suggest searches to patrons and staff.</dd>
</dl>
<h3>Update Database</h3>
<dl>
<dt><a href="/cgi-bin/koha/admin/updatedatabase.pl">Check your updates</a></dt>
<dd>Verify your database versions and execute new updates</dd>
</dl>
</div>
</div>

View file

@ -1,217 +0,0 @@
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha &rsaquo; Administration &rsaquo; Update Database</title>
[% INCLUDE 'doc-head-close.inc' %]
<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" />
<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.dataTables.min.js"></script>
[% INCLUDE 'datatables-strings.inc' %]
<script type="text/javascript" src="[% themelang %]/js/datatables.js"></script>
<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
$("#versionst").dataTable($.extend(true, {}, dataTablesDefaults, {
"aaSorting" : [[0, "desc"]],
"sPaginationType": "four_button",
}));
} );
function see_details(a){
var div = $(a).siblings('div');
$(div).slideToggle("fast", function() {
var isVisible = $(div).is(":visible");
if ( isVisible ){$(a).text("Hide details");}else{$(a).text("Show details");}
} );
}
function get_infos(version, node){
$.getJSON('/cgi-bin/koha/admin/ajax-updatedb-getinfos.pl',
{ version: version },
function(param) {
if ( param['errors'] ) {
$(node).replaceWith(_("Errors occured: ") + param['errors']);
}
var s;
s = "<b>" + _("Comments:") + "</b>";
s += '<br/>';
if ( param['comments'] ) {
s += param['comments'];
} else {
s += _("No comments");
}
s += '<br/><br/>';
s += "<b>" + _("Queries:") + "</b>";
s += '<br/>';
if ( param['queries'] ) {
s += param['queries'];
} else {
s += _("No queries");
}
$(node).replaceWith(s);
}
);
}
//]]>
</script>
</head>
<body>
[% INCLUDE 'header.inc' %]
[% INCLUDE 'cat-search.inc' %]
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> &rsaquo; Database update</div>
<div id="doc3" class="yui-t2">
<div id="bd">
<div id="yui-main">
<div class="yui-b">
<h2>Database update</h2>
[% IF report_loop %]
<div class="report" style="display:block; margin:1em;">
Report :
<ul>
[% FOREACH report_loo IN report_loop %]
<li>
[% report_loo.version %] --
[% FOREACH r IN report_loo.report %]
[% IF r.error.error == "ALREADY_EXISTS" %]
<span style="color:orange;">
[% r.error.filepath %] already executed in version [% r.error.old_version %] : same md5 ([% r.error.md5 %])
[<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=mark_as_ok&version=[% report_loo.version %]">Mark as OK</a>]
</span>
[% ELSIF r.error.error == "LOAD_FUNCTIONS_FAILED" %]
<span style="color:red;">
Load functions in [% r.error.filename %] failed ([% r.error.error_str %])
</span>
[% ELSIF r.error.error == "BAD_EXTENSION" %]
<span style="color:red;">
This extension ([% r.error.extension %]) is not take into account (only .pl or .sql)";
</span>
[% ELSE %]
[% IF r.error == "OK" %]
<span style="color:green;">
[% r.error %];
</span>
[% ELSE %]
<span style="color:red;">
[% r.error %];
</span>
[% END %]
[% END %]
[% END %]
</li>
[% END %]
</ul>
</div>
[% END %]
<span class="infos" style="display:block; margin:1em;">
[% IF nb_available %]
Your datebase is not up to date.<br/>
[% IF nb_available == 1 %]
1 update available [<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=update&version=[% available.first.version %]">UPDATE [% available.first.version %]</a>]
[% ELSE %]
[% nb_available %] updates available [<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=update[% FOREACH av IN available %]&version=[% av.version %][% END %]">UPDATE ALL</a>]:
[% IF ( dev_mode ) %]
<ul>
[% FOREACH av IN available %]
<li>[% av.version %] [<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=update&version=[% av.version %]">UPDATE</a>]</li>
[% END %]
</ul>
[% END %]
[% END %]
[% ELSE %]
Your database is up to date
[% END %]
</span>
<table id="versionst">
<thead>
<tr>
<th>DB revision</th>
<th>Status</th>
<th>Comments</th>
<th>Details</th>
</tr>
</thead>
<tbody>
[% FOREACH v IN versions %]
<tr>
<td>[% v.version %]</td>
<td>
[% IF v.available %]
Not applied
[% IF (dev_mode) %]
[<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=update&version=[% v.version %]">Execute</a>]
[% END %]
[% ELSE %]
[% SWITCH v.status %]
[% CASE 0 %]
<span style="color:red;">
Applied and failed
[<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=mark_as_ok&version=[% v.version %]">Mark as OK</a>]
</span>
[% CASE 1 %]
<span style="color:green;">Applied and OK</span>
[% CASE 2 %]
<span style="color:green;">Applied and Forced</span>
[% CASE %]
<span style="color:red;">Status does not exist !</span>
[% END %]
[% END %]
</td>
<td>
[% FOREACH c IN v.comments %]
[% c.comment %]<br/>
[% END %]
</td>
<td width="50%">
[% IF v.available %]
<span style="display:block;"><a href="#" onclick="get_infos('[% v.version %]', this); return false;">Get comments</a></span>
[% ELSE %]
<div class="details" style="display:none;">
<div class="queries" style="display:block;">
<b>Queries</b> :
<ul>
[% FOREACH q IN v.queries %]
<li>[% q.query %]<br/></li>
[% END %]
</ul>
</div>
[% IF v.status == 1 %]
<div class="status" style="display:block;">
<b>Status</b> :
<span style="color:green;">OK</span>
</div>
[% ELSE %]
<div class="status" style="display:block;">
<b>Status</b> :
[% IF v.status == 2 %]
<span style="color:green;">OK</span>
[FORCED]
[% ELSE %]
<span style="color:red;">Failed</span>
[<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=mark_as_ok&version=[% v.version %]">Mark as OK</a>]
[% END %]
</div>
<div class="errors" style="display:block;">
<b>Errors</b> :
<ul>
[% FOREACH e IN v.errors %]
<li><span>[% e.error %]</span></li>
[% END %]
</ul>
</div>
[% END %]
</div>
<a href="#" onclick="see_details(this);return false;">Show details</a>
[% END %]
</td>
</tr>
[% END %]
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>

View file

@ -42,8 +42,6 @@ my ( $template, $loggedinuser, $cookie, $flags ) = get_template_and_user(
}
);
C4::Auth::version_check($query, 'intranet', $cookie);
my $all_koha_news = &GetNewsToDisplay("koha");
my $koha_news_count = scalar @$all_koha_news;

View file

@ -1,115 +0,0 @@
#!/usr/bin/perl
# Copyright Biblibre 2012
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use Modern::Perl;
use C4::Context;
use C4::Update::Database;
use Getopt::Long;
my $help;
my $version;
my $list;
my $all;
my $min;
GetOptions(
'h|help|?' => \$help,
'm:s' => \$version,
'l|list' => \$list,
'a|all' => \$all,
'min:s' => \$min,
);
if ( $help or not( $version or $list or $all ) ) {
usage();
exit;
}
my @reports;
if ($version) {
my $report = C4::Update::Database::execute_version($version);
push @reports, $report;
}
if ($list) {
my $available = C4::Update::Database::list_versions_available();
my $already_applied = C4::Update::Database::list_versions_already_applied();
say "Versions available:";
for my $v (@$available) {
if ( not grep { $v eq $_->{version} } @$already_applied ) {
say "\t- $_" for $v;
}
}
say "Versions already applied:";
say "\t- $_->{version}" for @$already_applied;
}
if ($all) {
my $versions_available = C4::Update::Database::list_versions_available();
my $versions = C4::Update::Database::list_versions_already_applied;
my $min_version =
$min
? $min =~ m/\d\.\d{2}\.\d{2}\.\d{3}/
? C4::Update::Database::TransformToNum($min)
: $min
: 0;
for my $v (@$versions_available) {
# We execute ALL versions where version number >= min_version
# OR version is not a number
if ( not grep { $v eq $_->{version} } @$versions
and ( not $v =~ /\d\.\d{2}\.\d{2}\.\d{3}/ or
C4::Update::Database::TransformToNum($v) >= $min_version ) )
{
my $report = C4::Update::Database::execute_version $v;
push @reports, $report;
}
}
}
if ( $version or $all ) {
say @reports ? "Report:" : "Nothing to report";
for my $report (@reports) {
my ( $v, $r ) = each %$report;
if ( ref($r) eq 'HASH' ) {
say "\t$v => $r->{error}";
}
elsif ( ref($r) eq 'ARRAY' ) {
say "\t$_" for @$r;
}
else {
say "\t$v => $r";
}
}
}
sub usage {
say "update.pl";
say "This script updates your database for you";
say "Usage:";
say "\t-h\tShow this help message";
say "\t-m\tExecute a given version";
say "\t-l\tList all the versions";
say "\t-all\tExecute all available versions";
say
"\t-min\tWith -all, Execute all available versions since a given version";
say "\t\tCan be X.XX.XX.XXX or X.XXXXXXX";
}