View | Details | Raw Unified | Return to bug 25078
Collapse All | Expand All

(-)a/C4/Installer.pm (-48 / +138 lines)
Lines 23-38 use Try::Tiny; Link Here
23
use Encode qw( encode decode is_utf8 );
23
use Encode qw( encode decode is_utf8 );
24
use DBIx::RunSQL;
24
use DBIx::RunSQL;
25
use YAML::XS;
25
use YAML::XS;
26
use File::Slurp qw( read_file );
27
use DBI;
28
26
use C4::Context;
29
use C4::Context;
27
use Koha::Schema;
30
use Koha::Schema;
28
use DBI;
29
use Koha;
31
use Koha;
30
32
31
use vars qw(@ISA @EXPORT);
33
use vars qw(@ISA @EXPORT);
32
BEGIN {
34
BEGIN {
33
    require Exporter;
35
    require Exporter;
34
    @ISA = qw( Exporter );
36
    @ISA = qw( Exporter );
35
    push @EXPORT, qw( primary_key_exists foreign_key_exists index_exists column_exists TableExists TransformToNum CheckVersion NewVersion SetVersion sanitize_zero_date update get_db_entries );
37
    push @EXPORT, qw( primary_key_exists foreign_key_exists index_exists column_exists TableExists TransformToNum CheckVersion NewVersion SetVersion sanitize_zero_date update get_db_entries get_atomic_updates run_atomic_updates );
36
};
38
};
37
39
38
=head1 NAME
40
=head1 NAME
Lines 711-754 sub get_db_entries { Link Here
711
    return \@need_update;
713
    return \@need_update;
712
}
714
}
713
715
716
sub run_db_rev {
717
    my ($file) = @_;
718
719
    my $db_rev = do $file;
720
721
    my $error;
722
    my $out = '';
723
    open my $outfh, '>', \$out;
724
    try {
725
        my $schema = Koha::Database->new->schema;
726
        $schema->txn_do(
727
            sub {
728
                $db_rev->{up}->( { dbh => $schema->storage->dbh, out => $outfh } );
729
            }
730
        );
731
    }
732
    catch {
733
        $error = $_;
734
    };
735
736
    close $outfh;
737
    $out = decode( 'UTF-8', $out );
738
739
    my $db_entry = {
740
        filepath    => $file,
741
        bug_number  => $db_rev->{bug_number},
742
        description => $db_rev->{description},
743
        exec_output => $out,
744
        version     => scalar version_from_file($file),
745
        time        => POSIX::strftime( "%H:%M:%S", localtime ),
746
        error       => $error
747
    };
748
    $db_entry->{output} = generate_output_db_entry($db_entry, $out);
749
    return $db_entry;
750
}
751
714
sub update {
752
sub update {
715
    my ( $files, $params ) = @_;
753
    my ( $files, $params ) = @_;
716
754
717
    my $force = $params->{force} || 0;
755
    my $force = $params->{force} || 0;
718
756
719
    my $schema = Koha::Database->new->schema;
720
    my ( @done, @errors );
757
    my ( @done, @errors );
721
    for my $file ( @$files ) {
758
    for my $file ( @$files ) {
722
759
723
        my $db_rev = do $file;
760
        my $db_entry = run_db_rev($file);
724
725
        my $error;
726
727
        my $out = '';
728
        open my $outfh, '>', \$out;
729
        try {
730
            $schema->txn_do(
731
                sub {
732
                    $db_rev->{up}->({ dbh => $schema->storage->dbh, out => $outfh });
733
                }
734
            );
735
        } catch {
736
            $error = $_;
737
        };
738
739
        close $outfh;
740
        $out = decode('UTF-8', $out);
741
742
        my $db_entry = {
743
            bug_number  => $db_rev->{bug_number},
744
            description => $db_rev->{description},
745
            version     => version_from_file($file),
746
            time        => POSIX::strftime( "%H:%M:%S", localtime ),
747
        };
748
        $db_entry->{output} = output_version( { %$db_entry, done => !$error, report => $out } );
749
761
750
        if ( $error ) {
762
        if ( $db_entry->{error} ) {
751
            push @errors, { %$db_entry, error => $error };
763
            push @errors, $db_entry;
752
            $force ? next : last ;
764
            $force ? next : last ;
753
                # We stop the update if an error occurred!
765
                # We stop the update if an error occurred!
754
        }
766
        }
Lines 759-788 sub update { Link Here
759
    return { success => \@done, error => \@errors };
771
    return { success => \@done, error => \@errors };
760
}
772
}
761
773
762
sub output_version {
774
sub generate_output_db_entry {
763
    my ( $db_entry ) = @_;
775
    my ( $db_entry ) = @_;
764
776
765
    my $description = $db_entry->{description};
777
    my $description = $db_entry->{description};
766
    my $report = $db_entry->{report};
778
    my $output      = $db_entry->{output};
767
    my $DBversion = $db_entry->{version};
779
    my $DBversion   = $db_entry->{version};
768
    my $bug_number = $db_entry->{bug_number};
780
    my $bug_number  = $db_entry->{bug_number};
769
    my $time = $db_entry->{time};
781
    my $time        = $db_entry->{time};
770
    my $done = defined $db_entry->{done}
782
    my $exec_output = $db_entry->{exec_output};
771
                ? $db_entry->{done}
783
    my $done        = defined $db_entry->{done}
772
                    ? " done"
784
                       ? $db_entry->{done}
773
                    : " failed"
785
                           ? " done"
774
                : ""; # For old versions, we don't know if we succeed or failed
786
                           : " failed"
787
                       : ""; # For old versions, we don't know if we succeed or failed
775
788
776
    my @output;
789
    my @output;
777
790
778
    if ($bug_number) {
791
    if ( $DBversion ) {
779
        push @output, sprintf('Upgrade to %s %s [%s]: Bug %5s - %s', $DBversion, $done, $time, $bug_number, $description);
792
        if ($bug_number) {
780
    } else {
793
            push @output, sprintf('Upgrade to %s %s [%s]: Bug %5s - %s', $DBversion, $done, $time, $bug_number, $description);
781
        push @output, sprintf('Upgrade to %s %s [%s]: %s', $DBversion, $done, $time, $description);
794
        } else {
795
            push @output, sprintf('Upgrade to %s %s [%s]: %s', $DBversion, $done, $time, $description);
796
        }
797
    } else { # Atomic update
798
        if ($bug_number) {
799
            push @output, sprintf('DEV atomic update %s %s [%s]: Bug %5s - %s', $db_entry->{filepath}, $done, $time, $bug_number, $description);
800
        } else { # Old atomic update syntax
801
            push @output, sprintf('DEV atomic update %s %s [%s]', $db_entry->{filepath}, $done, $time);
802
        }
782
    }
803
    }
783
804
784
    if ($report) {
805
    if ($exec_output) {
785
        foreach my $line (split /\n/, $report) {
806
        foreach my $line (split /\n/, $exec_output) {
786
            push @output, sprintf "\t\t\t\t\t\t   - %s", $line;
807
            push @output, sprintf "\t\t\t\t\t\t   - %s", $line;
787
        }
808
        }
788
    }
809
    }
Lines 790-795 sub output_version { Link Here
790
    return \@output;
811
    return \@output;
791
}
812
}
792
813
814
sub get_atomic_updates {
815
    my @atomic_upate_files;
816
    # if there is anything in the atomicupdate, read and execute it.
817
    my $update_dir = C4::Context->config('intranetdir') . '/installer/data/mysql/atomicupdate/';
818
    opendir( my $dirh, $update_dir );
819
    foreach my $file ( sort readdir $dirh ) {
820
        next if $file !~ /\.(perl|pl)$/;  #skip other files
821
        next if $file eq 'skeleton.perl' || $file eq 'skeleton.pl'; # skip the skeleton files
822
823
        push @atomic_upate_files, $file;
824
    }
825
    return \@atomic_upate_files;
826
}
827
828
sub run_atomic_updates {
829
    my ( $files ) = @_;
830
831
    my $update_dir = C4::Context->config('intranetdir') . '/installer/data/mysql/atomicupdate/';
832
    my ( @done, @errors );
833
    for my $file ( @$files ) {
834
        my $filepath = $update_dir . $file;
835
836
        my $atomic_update;
837
        if ( $file =~ m{\.perl$} ) {
838
            my $code = read_file( $filepath );
839
            my ( $out, $err ) = ('', '');
840
            {
841
                open my $oldout, ">&STDOUT";
842
                close STDOUT;
843
                open STDOUT,'>:encoding(utf8)', \$out;
844
                my $DBversion = Koha::version; # We need $DBversion and $dbh for the eval
845
                my $dbh = C4::Context->dbh;
846
                eval $code; ## no critic (StringyEval)
847
                $err = $@;
848
                warn $err if $err;
849
                close STDOUT;
850
                open STDOUT, ">&", $oldout;
851
            }
852
853
            $atomic_update = {
854
                filepath    => $filepath,
855
                description => '',
856
                version     => undef,
857
                time        => POSIX::strftime( "%H:%M:%S", localtime ),
858
            };
859
860
861
            $atomic_update->{output} =
862
              $out
863
              ? [ split "\n", $out ]
864
              : generate_output_db_entry($atomic_update); # There wad an error, we didn't reach NewVersion)
865
866
            $atomic_update->{error} = $err if $err;
867
        } elsif ( $file =~ m{\.pl$} ) {
868
            $atomic_update = run_db_rev($filepath);
869
        } else {
870
            warn "Atomic update must be .perl or .pl ($file)";
871
        }
872
873
        if ( $atomic_update->{error} ) {
874
            push @errors, $atomic_update;
875
        } else {
876
            push @done, $atomic_update;
877
        }
878
    }
879
880
    return { success => \@done, error => \@errors };
881
}
882
793
=head2 DropAllForeignKeys($table)
883
=head2 DropAllForeignKeys($table)
794
884
795
Drop all foreign keys of the table $table
885
Drop all foreign keys of the table $table
Lines 874-880 sub NewVersion { Link Here
874
        $description = $descriptions;
964
        $description = $descriptions;
875
    }
965
    }
876
966
877
    my $output = output_version( {
967
    my $output = generate_output_db_entry( {
878
            bug_number  => $bug_number,
968
            bug_number  => $bug_number,
879
            description => $description,
969
            description => $description,
880
            report      => $report,
970
            report      => $report,
(-)a/installer/data/mysql/updatedatabase.pl (-18 / +11 lines)
Lines 46-52 use MARC::Record; Link Here
46
use MARC::File::XML ( BinaryEncoding => 'utf8' );
46
use MARC::File::XML ( BinaryEncoding => 'utf8' );
47
47
48
use File::Path qw[remove_tree]; # perl core module
48
use File::Path qw[remove_tree]; # perl core module
49
use File::Slurp;
50
49
51
# FIXME - The user might be installing a new database, so can't rely
50
# FIXME - The user might be installing a new database, so can't rely
52
# on /etc/koha.conf anyway.
51
# on /etc/koha.conf anyway.
Lines 24284-24290 if( CheckVersion( $DBversion ) ) { Link Here
24284
}
24283
}
24285
24284
24286
unless ( $ENV{HTTP_HOST} ) { # Is that correct?
24285
unless ( $ENV{HTTP_HOST} ) { # Is that correct?
24287
    my $files = C4::Installer::get_db_entries;
24286
    my $files = get_db_entries;
24288
    my $report = update( $files, { force => $force } );
24287
    my $report = update( $files, { force => $force } );
24289
24288
24290
    for my $s ( @{ $report->{success} } ) {
24289
    for my $s ( @{ $report->{success} } ) {
Lines 24294-24317 unless ( $ENV{HTTP_HOST} ) { # Is that correct? Link Here
24294
        say Encode::encode_utf8(join "\n", @{$e->{output}});
24293
        say Encode::encode_utf8(join "\n", @{$e->{output}});
24295
        say Encode::encode_utf8("ERROR - " . $e->{error});
24294
        say Encode::encode_utf8("ERROR - " . $e->{error});
24296
    }
24295
    }
24297
}
24298
24296
24299
# SEE bug 13068
24297
    my $atomic_update_files = get_atomic_updates;
24300
# if there is anything in the atomicupdate, read and execute it.
24298
    $report = run_atomic_updates($atomic_update_files);
24301
my $update_dir = C4::Context->config('intranetdir') . '/installer/data/mysql/atomicupdate/';
24299
    for my $s ( @{ $report->{success} } ) {
24302
opendir( my $dirh, $update_dir );
24300
        say Encode::encode_utf8(join "\n", @{$s->{output}});
24303
foreach my $file ( sort readdir $dirh ) {
24304
    next if $file !~ /\.(sql|perl)$/;  #skip other files
24305
    next if $file eq 'skeleton.perl'; # skip the skeleton file
24306
    print "DEV atomic update: $file\n";
24307
    if ( $file =~ /\.sql$/ ) {
24308
        my $installer = C4::Installer->new();
24309
        my $rv = $installer->load_sql( $update_dir . $file ) ? 0 : 1;
24310
    } elsif ( $file =~ /\.perl$/ ) {
24311
        my $code = read_file( $update_dir . $file );
24312
        eval $code; ## no critic (StringyEval)
24313
        say "Atomic update generated errors: $@" if $@;
24314
    }
24301
    }
24302
    for my $e ( @{ $report->{error} } ) {
24303
        say Encode::encode_utf8(join "\n", @{$e->{output}});
24304
        say Encode::encode_utf8("ERROR - " . $e->{error});
24305
    }
24306
24307
24315
}
24308
}
24316
24309
24317
exit;
24310
exit;
(-)a/installer/install.pl (-1 / +10 lines)
Lines 431-438 elsif ( $step && $step == 3 ) { Link Here
431
431
432
        my $db_entries = get_db_entries();
432
        my $db_entries = get_db_entries();
433
        my $report = update( $db_entries );
433
        my $report = update( $db_entries );
434
        my $atomic_update_files = get_atomic_updates;
435
        my $atomic_update_report = run_atomic_updates( $atomic_update_files );
434
436
435
        $template->param( success => $report->{success}, error => $report->{error} );
437
        $template->param(
438
            success        => $report->{success},
439
            error          => $report->{error},
440
            atomic_updates => {
441
                success => $atomic_update_report->{success},
442
                error   => $atomic_update_report->{error}
443
            }
444
        );
436
445
437
        #warn "The following errors were returned while attempting to run the updatedatabase.pl script:\n"; #FIXME restore this
446
        #warn "The following errors were returned while attempting to run the updatedatabase.pl script:\n"; #FIXME restore this
438
        $template->param( $op => 1 );
447
        $template->param( $op => 1 );
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/installer/step3.tt (-11 / +45 lines)
Lines 263-269 Link Here
263
                    [% END %]
263
                    [% END %]
264
264
265
                    [%# Success for new versions %]
265
                    [%# Success for new versions %]
266
                    [% IF success %]
266
                    [% IF success.size %]
267
                        <ul>
267
                        <ul>
268
                            [% FOR s IN success %]
268
                            [% FOR s IN success %]
269
                                [% FOR o IN s.output %]
269
                                [% FOR o IN s.output %]
Lines 276-296 Link Here
276
                        </ul>
276
                        </ul>
277
                    [% END %]
277
                    [% END %]
278
278
279
                    [%# Errors for old versions %]
279
                    [% IF atomic_updates.success.size %]
280
                    [% IF has_update_errors %]
280
                        <p>Atomic updates:</p>
281
                        <p>Update errors :</p>
282
                        <ul>
281
                        <ul>
283
                            [% FOREACH update_error IN update_errors %]
282
                            [% FOR s IN atomic_updates.success %]
284
                                <li class="update_error">[% update_error.line | html %]</li>
283
                                [% FOR o IN s.output %]
284
                                    <li>[% o | html %]</li>
285
                                    [% IF s.output.size > 1 %]
286
                                        [% IF loop.first %]<ul>[% ELSIF loop.last %]</ul>[% END %]
287
                                    [% END %]
288
                                [% END %]
285
                            [% END %]
289
                            [% END %]
286
                        </ul>
290
                        </ul>
287
                    [% END %]
291
                    [% END %]
288
292
289
                    [%# Errors for new versions %]
293
                    [% IF has_update_errors OR error.size %]
290
                    [% IF error %]
294
                        <p>Update errors :</p>
291
                        <p>Update error :</p>
295
                        [%# Errors for old versions %]
296
                        [% IF has_update_errors %]
297
                            <ul>
298
                                [% FOREACH update_error IN update_errors %]
299
                                    <li class="update_error">[% update_error.line | html %]</li>
300
                                [% END %]
301
                            </ul>
302
                        [% END %]
303
304
                        [%# Errors for new versions %]
305
                        [% IF error.size %]
306
                            <ul>
307
                                [% FOR e IN error %]
308
                                    [% FOR o IN e.output %]
309
                                        <li class="update_error">
310
                                            [% o | html %]
311
                                            <br/>
312
                                            ERROR: [% e.error | html %]
313
314
                                            [% IF e.output.size > 1 %]
315
                                                [% IF loop.first %]<ul>[% ELSIF loop.last %]</ul>[% END %]
316
                                            [% END %]
317
                                        </li>
318
                                    [% END %]
319
                                [% END %]
320
                            </ul>
321
                        [% END %]
322
                    [% END %]
323
324
                    [% IF atomic_updates.error.size %]
325
                        <p>Atomic update error :</p>
292
                        <ul>
326
                        <ul>
293
                            [% FOR e IN error %]
327
                            [% FOR e IN atomic_updates.error %]
294
                                [% FOR o IN e.output %]
328
                                [% FOR o IN e.output %]
295
                                    <li class="update_error">
329
                                    <li class="update_error">
296
                                        [% o | html %]
330
                                        [% o | html %]
Lines 305-310 Link Here
305
                            [% END %]
339
                            [% END %]
306
                        </ul>
340
                        </ul>
307
                    [% END %]
341
                    [% END %]
342
308
                    [% UNLESS error OR has_update_errors %]
343
                    [% UNLESS error OR has_update_errors %]
309
                        <p>Everything went okay. Update done.</p>
344
                        <p>Everything went okay. Update done.</p>
310
                        <p><a href="install.pl?step=3&amp;op=finished" class="btn btn-primary">Continue to log in to Koha</a></p>
345
                        <p><a href="install.pl?step=3&amp;op=finished" class="btn btn-primary">Continue to log in to Koha</a></p>
311
- 

Return to bug 25078