Parent Directory
|
Revision Log
This commit was manufactured by cvs2svn to create branch 'rel-2-4-patches'.
1 #!/usr/bin/env perl 2 ################################################################################ 3 # WeBWorK Online Homework Delivery System 4 # Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ 5 # $CVSHeader: webwork2/bin/wwdb_upgrade,v 1.13 2007/04/04 15:05:25 glarose Exp $ 6 # 7 # This program is free software; you can redistribute it and/or modify it under 8 # the terms of either: (a) the GNU General Public License as published by the 9 # Free Software Foundation; either version 2, or (at your option) any later 10 # version, or (b) the "Artistic License" which comes with this package. 11 # 12 # This program is distributed in the hope that it will be useful, but WITHOUT 13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the 15 # Artistic License for more details. 16 ################################################################################ 17 18 use strict; 19 use warnings; 20 use Getopt::Std; 21 use DBI; 22 use Data::Dumper; 23 24 BEGIN { 25 die "WEBWORK_ROOT not found in environment.\n" 26 unless exists $ENV{WEBWORK_ROOT}; 27 } 28 29 use lib "$ENV{WEBWORK_ROOT}/lib"; 30 use WeBWorK::CourseEnvironment; 31 use WeBWorK::Utils qw/runtime_use/; 32 use WeBWorK::Utils::CourseManagement qw/listCourses/; 33 34 our ($opt_v); 35 getopts("v"); 36 37 if ($opt_v) { 38 $| = 1; 39 *verbose = sub { print STDERR @_ }; 40 } else { 41 *verbose = sub {}; 42 } 43 44 # global variables, hah hah. 45 my ($dbh, %sql_tables); 46 47 ################################################################################ 48 49 my $i = -1; 50 our @DB_VERSIONS; 51 52 $DB_VERSIONS[++$i]{desc} = "is the initial version of database, identical to database structure in WeBWorK 2.2.x."; 53 54 $DB_VERSIONS[++$i]{desc} = "adds dbupgrade table to facilitate automatic database upgrades."; 55 $DB_VERSIONS[ $i]{global_code} = sub { 56 $dbh->do("CREATE TABLE `dbupgrade` (`name` VARCHAR(255) NOT NULL PRIMARY KEY, `value` TEXT)"); 57 $dbh->do("INSERT INTO `dbupgrade` (`name`, `value`) VALUES (?, ?)", {}, "db_version", 1); 58 $sql_tables{dbupgrade} = (); 59 }; 60 61 $DB_VERSIONS[++$i]{desc} = "adds problems_per_page field to set and set_user tables of each course."; 62 $DB_VERSIONS[ $i]{course_code} = sub { 63 my $course = shift; 64 $dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `problems_per_page` INT") 65 if exists $sql_tables{"${course}_set"}; 66 $dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `problems_per_page` INT") 67 if exists $sql_tables{"${course}_set_user"}; 68 }; 69 70 $DB_VERSIONS[++$i]{desc} = "adds depths table to keep track of dvipng depth information."; 71 $DB_VERSIONS[ $i]{global_code} = sub { 72 $dbh->do("CREATE TABLE depths (md5 CHAR(33) NOT NULL, depth SMALLINT, PRIMARY KEY (md5))"); 73 $sql_tables{depths} = (); 74 }; 75 76 $DB_VERSIONS[++$i]{desc} = "changes type of key timestamp field to BIGINT"; 77 $DB_VERSIONS[ $i]{course_code} = sub { 78 my $course = shift; 79 return unless exists $sql_tables{"${course}_key"}; 80 $dbh->do("ALTER TABLE `${course}_key` CHANGE COLUMN `timestamp` `timestamp` BIGINT"); 81 }; 82 83 $DB_VERSIONS[++$i]{desc} = "changes type of problem_user status field to FLOAT"; 84 $DB_VERSIONS[ $i]{course_code} = sub { 85 my $course = shift; 86 return unless exists $sql_tables{"${course}_problem_user"}; 87 $dbh->do("UPDATE `${course}_problem_user` SET `status`=NULL WHERE `status`=''"); 88 $dbh->do("ALTER TABLE `${course}_problem_user` CHANGE COLUMN `status` `status` FLOAT"); 89 }; 90 91 $DB_VERSIONS[++$i]{desc} = "changes types of alphanumeric keyfields to TINYBLOB NOT NULL"; 92 $DB_VERSIONS[ $i]{course_code} = sub { 93 my $course = shift; 94 $dbh->do("ALTER TABLE `${course}_user` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL") 95 if exists $sql_tables{"${course}_user"}; 96 $dbh->do("ALTER TABLE `${course}_password` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL") 97 if exists $sql_tables{"${course}_password"}; 98 $dbh->do("ALTER TABLE `${course}_permission` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL") 99 if exists $sql_tables{"${course}_permission"}; 100 $dbh->do("ALTER TABLE `${course}_key` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL") 101 if exists $sql_tables{"${course}_key"}; 102 $dbh->do("ALTER TABLE `${course}_set` CHANGE COLUMN `set_id` `set_id` TINYBLOB NOT NULL") 103 if exists $sql_tables{"${course}_set"}; 104 $dbh->do("ALTER TABLE `${course}_problem` CHANGE COLUMN `set_id` `set_id` TINYBLOB NOT NULL") 105 if exists $sql_tables{"${course}_problem"}; 106 $dbh->do("ALTER TABLE `${course}_set_user` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL") 107 if exists $sql_tables{"${course}_set_user"}; 108 $dbh->do("ALTER TABLE `${course}_set_user` CHANGE COLUMN `set_id` `set_id` TINYBLOB NOT NULL") 109 if exists $sql_tables{"${course}_set_user"}; 110 $dbh->do("ALTER TABLE `${course}_problem_user` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL") 111 if exists $sql_tables{"${course}_problem_user"}; 112 $dbh->do("ALTER TABLE `${course}_problem_user` CHANGE COLUMN `set_id` `set_id` TINYBLOB NOT NULL") 113 if exists $sql_tables{"${course}_problem_user"}; 114 }; 115 116 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for user table"; 117 $DB_VERSIONS[ $i]{course_code} = sub { 118 my $course = shift; 119 return unless exists $sql_tables{"${course}_user"}; 120 $dbh->do("ALTER TABLE `${course}_user` DROP KEY `user_id`"); 121 $dbh->do("ALTER TABLE `${course}_user` ADD UNIQUE KEY (`user_id`(255))"); 122 }; 123 124 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for password table"; 125 $DB_VERSIONS[ $i]{course_code} = sub { 126 my $course = shift; 127 return unless exists $sql_tables{"${course}_password"}; 128 $dbh->do("ALTER TABLE `${course}_password` DROP KEY `user_id`"); 129 $dbh->do("ALTER TABLE `${course}_password` ADD UNIQUE KEY (`user_id`(255))"); 130 }; 131 132 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for permission table"; 133 $DB_VERSIONS[ $i]{course_code} = sub { 134 my $course = shift; 135 return unless exists $sql_tables{"${course}_permission"}; 136 $dbh->do("ALTER TABLE `${course}_permission` DROP KEY `user_id`"); 137 $dbh->do("ALTER TABLE `${course}_permission` ADD UNIQUE KEY (`user_id`(255))"); 138 }; 139 140 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for key table"; 141 $DB_VERSIONS[ $i]{course_code} = sub { 142 my $course = shift; 143 return unless exists $sql_tables{"${course}_key"}; 144 $dbh->do("ALTER TABLE `${course}_key` DROP KEY `user_id`"); 145 $dbh->do("ALTER TABLE `${course}_key` ADD UNIQUE KEY (`user_id`(255))"); 146 }; 147 148 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for set table"; 149 $DB_VERSIONS[ $i]{course_code} = sub { 150 my $course = shift; 151 return unless exists $sql_tables{"${course}_set"}; 152 $dbh->do("ALTER TABLE `${course}_set` DROP KEY `set_id`"); 153 $dbh->do("ALTER TABLE `${course}_set` ADD UNIQUE KEY (`set_id`(255))"); 154 }; 155 156 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for problem table"; 157 $DB_VERSIONS[ $i]{course_code} = sub { 158 my $course = shift; 159 return unless exists $sql_tables{"${course}_problem"}; 160 $dbh->do("ALTER TABLE `${course}_problem` DROP KEY `set_id`"); 161 $dbh->do("ALTER TABLE `${course}_problem` ADD UNIQUE KEY (`set_id`(255), `problem_id`)"); 162 $dbh->do("ALTER TABLE `${course}_problem` DROP KEY `problem_id`"); 163 $dbh->do("ALTER TABLE `${course}_problem` ADD KEY (`problem_id`)"); 164 }; 165 166 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for set_user table"; 167 $DB_VERSIONS[ $i]{course_code} = sub { 168 my $course = shift; 169 return unless exists $sql_tables{"${course}_set_user"}; 170 $dbh->do("ALTER TABLE `${course}_set_user` DROP KEY `user_id`"); 171 $dbh->do("ALTER TABLE `${course}_set_user` ADD UNIQUE KEY (`user_id`(255), `set_id`(255))"); 172 $dbh->do("ALTER TABLE `${course}_set_user` DROP KEY `set_id`"); 173 $dbh->do("ALTER TABLE `${course}_set_user` ADD KEY (`set_id`(255))"); 174 }; 175 176 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for problem_user table"; 177 $DB_VERSIONS[ $i]{course_code} = sub { 178 my $course = shift; 179 return unless exists $sql_tables{"${course}_problem_user"}; 180 $dbh->do("ALTER TABLE `${course}_problem_user` DROP KEY `user_id`"); 181 $dbh->do("ALTER TABLE `${course}_problem_user` ADD UNIQUE KEY (`user_id`(255), `set_id`(255), `problem_id`)"); 182 $dbh->do("ALTER TABLE `${course}_problem_user` DROP KEY `set_id`"); 183 $dbh->do("ALTER TABLE `${course}_problem_user` ADD KEY (`set_id`(255), `problem_id`)"); 184 $dbh->do("ALTER TABLE `${course}_problem_user` DROP KEY `problem_id`"); 185 $dbh->do("ALTER TABLE `${course}_problem_user` ADD KEY (`problem_id`)"); 186 }; 187 188 $DB_VERSIONS[++$i]{desc} = "changes psvn index from PRIMARY KEY to UNIQUE KEY"; 189 $DB_VERSIONS[ $i]{course_code} = sub { 190 my $course = shift; 191 return unless exists $sql_tables{"${course}_set_user"}; 192 $dbh->do("ALTER TABLE `${course}_set_user` ADD UNIQUE KEY (`psvn`)"); 193 $dbh->do("ALTER TABLE `${course}_set_user` DROP PRIMARY KEY"); 194 }; 195 196 $DB_VERSIONS[++$i]{desc} = "adds hide_score and hide_work fields to set and set_user"; 197 $DB_VERSIONS[ $i]{course_code} = sub { 198 my $course = shift; 199 if ( exists $sql_tables{"${course}_set"} ) { 200 $dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `hide_score` ENUM('0','1')"); 201 $dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `hide_work` ENUM('0','1')"); 202 } 203 if ( exists $sql_tables{"${course}_set_user"} ) { 204 $dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `hide_score` ENUM('0','1')"); 205 $dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `hide_work` ENUM('0','1')"); 206 } 207 }; 208 209 $DB_VERSIONS[++$i]{desc} = "updates hide_score and hide_work in set and set_user tables to allow more (and more descriptive) possible values"; 210 $DB_VERSIONS[ $i]{course_code} = sub { 211 my $course = shift; 212 if ( exists $sql_tables{"${course}_set"} ) { 213 $dbh->do("ALTER TABLE `${course}_set` MODIFY COLUMN `hide_score` ENUM('0','1','2')"); 214 $dbh->do("ALTER TABLE `${course}_set` MODIFY COLUMN `hide_work` ENUM('0','1','2')"); 215 } 216 if ( exists $sql_tables{"${course}_set_user"} ) { 217 $dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_score` ENUM('0','1','2')"); 218 $dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_work` ENUM('0','1','2')"); 219 } 220 }; 221 222 $DB_VERSIONS[++$i]{desc} = "adds time_limit_cap field to set and set_user tables"; 223 $DB_VERSIONS[ $i]{course_code} = sub { 224 my $course = shift; 225 if ( exists $sql_tables{"${course}_set"} ) { 226 $dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `time_limit_cap` ENUM('0','1')"); 227 } 228 if ( exists $sql_tables{"${course}_set_user"} ) { 229 $dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `time_limit_cap` ENUM('0','1')"); 230 } 231 }; 232 233 $DB_VERSIONS[++$i]{desc} = "updates hide_score and hide_work in set and set_user tables to have more descriptive values, set default values"; 234 $DB_VERSIONS[ $i]{course_code} = sub { 235 my $course = shift; 236 if ( exists $sql_tables{"${course}_set"} ) { 237 $dbh->do("ALTER TABLE `${course}_set` MODIFY COLUMN `hide_score` ENUM('N','Y','BeforeAnswerDate') DEFAULT 'N'"); 238 $dbh->do("ALTER TABLE `${course}_set` MODIFY COLUMN `hide_work` ENUM('N','Y','BeforeAnswerDate') DEFAULT 'N'"); 239 } 240 if ( exists $sql_tables{"${course}_set_user"} ) { 241 $dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_score` ENUM('N','Y','BeforeAnswerDate') DEFAULT 'N'"); 242 $dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_work` ENUM('N','Y','BeforeAnswerDate') DEFAULT 'N'"); 243 } 244 }; 245 246 $DB_VERSIONS[++$i]{desc} = "adds locations, location_addresses, set_locations and set_locations_user tables to database, and add restrict_ip to set and set_user."; 247 $DB_VERSIONS[ $i]{global_code} = sub { 248 $dbh->do("CREATE TABLE locations (location_id TINYBLOB NOT NULL, description TEXT, PRIMARY KEY (location_id(1000)))"); 249 $dbh->do("CREATE TABLE location_addresses (location_id TINYBLOB NOT NULL, ip_mask TINYBLOB NOT NULL, PRIMARY KEY (location_id(500),ip_mask(500)))"); 250 }; 251 $DB_VERSIONS[ $i]{course_code} = sub { 252 my $course = shift; 253 254 $dbh->do("CREATE TABLE `${course}_set_locations` (set_id TINYBLOB NOT NULL, location_id TINYBLOB NOT NULL, PRIMARY KEY (set_id(500),location_id(500)))"); 255 $dbh->do("CREATE TABLE `${course}_set_locations_user` (set_id TINYBLOB NOT NULL, user_id TINYBLOB NOT NULL, location_id TINYBLOB NOT NULL, PRIMARY KEY (set_id(300),user_id(300),location_id(300)))"); 256 257 if ( exists $sql_tables{"${course}_set"} ) { 258 $dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `restrict_ip` enum('No','RestrictTo','DenyFrom') DEFAULT 'No'"); 259 } 260 if ( exists $sql_tables{"${course}_set_user"} ) { 261 $dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `restrict_ip` enum('No','RestrictTo','DenyFrom')"); 262 } 263 }; 264 265 $DB_VERSIONS[++$i]{desc} = "updates defaults for hide_work and hide_score in set_user tables."; 266 $DB_VERSIONS[ $i]{course_code} = sub { 267 my $course = shift; 268 269 if ( exists $sql_tables{"${course}_set_user"} ) { 270 $dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_score` ENUM('N','Y','BeforeAnswerDate')"); 271 $dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_work` ENUM('N','Y','BeforeAnswerDate')"); 272 } 273 }; 274 275 $DB_VERSIONS[++$i]{desc} = "adds relax_restrict_ip, hide_problem_score columns to set and set_user tables."; 276 $DB_VERSIONS[ $i]{course_code} = sub { 277 my $course = shift; 278 279 if ( exists $sql_tables{"${course}_set"} ) { 280 $dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `relax_restrict_ip` ENUM('No','AfterAnswerDate','AfterVersionAnswerDate') DEFAULT 'No'"); 281 $dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `hide_score_by_problem` ENUM('N','Y') DEFAULT 'N'"); 282 } 283 if ( exists $sql_tables{"${course}_set_user"} ) { 284 $dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `relax_restrict_ip` ENUM('No','AfterAnswerDate','AfterVersionAnswerDate')"); 285 $dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `hide_score_by_problem` ENUM('N','Y')"); 286 } 287 }; 288 289 $DB_VERSIONS[++$i]{desc} = "adds set and set_user fields to allow set-level proctor, updates permissions to allow finer-grained regulation of proctoring."; 290 $DB_VERSIONS[ $i]{course_code} = sub { 291 my $course = shift; 292 if ( exists $sql_tables{"${course}_permission"} ) { 293 $dbh->do("UPDATE `${course}_permission` SET `permission`=3 where `permission`=2"); 294 } 295 if ( exists $sql_tables{"${course}_set"} ) { 296 $dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `restricted_login_proctor` ENUM('No','Yes') DEFAULT 'No'"); 297 } 298 if ( exists $sql_tables{"${course}_set_user"} ) { 299 $dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `restricted_login_proctor` ENUM('No','Yes')"); 300 } 301 }; 302 303 our $THIS_DB_VERSION = $i; 304 305 ################################################################################ 306 307 my $ce = WeBWorK::CourseEnvironment->new({ 308 webwork_dir => $ENV{WEBWORK_ROOT}, 309 }); 310 311 my @ww_courses = listCourses($ce); 312 313 $dbh = DBI->connect( 314 $ce->{database_dsn}, 315 $ce->{database_username}, 316 $ce->{database_password}, 317 { 318 PrintError => 0, 319 RaiseError => 1, 320 }, 321 ); 322 323 { 324 verbose("Obtaining dbupgrade lock...\n"); 325 my ($lock_status) = $dbh->selectrow_array("SELECT GET_LOCK('dbupgrade', 10)"); 326 if (not defined $lock_status) { 327 print "Couldn't obtain lock because an error occurred.\n"; 328 exit 2; 329 } 330 if ($lock_status) { 331 verbose("Got lock.\n"); 332 } else { 333 print "Timed out while waiting for lock.\n"; 334 exit 2; 335 } 336 } 337 338 %sql_tables = get_sql_tables(); 339 340 my $db_version = exists $sql_tables{dbupgrade} ? get_db_version() : 0; 341 342 if (not defined $db_version) { 343 print "Failed to get db_version -- can't continue.\n"; 344 exit 1; 345 } 346 347 verbose("Initial db_version is $db_version\n"); 348 349 if ($db_version > $THIS_DB_VERSION) { 350 print "db_version is $db_version, but the current database version is only $THIS_DB_VERSION. This database was probably used with a newer version of WeBWorK.\n"; 351 exit; 352 } 353 354 while ($db_version < $THIS_DB_VERSION) { 355 $db_version++; 356 unless (upgrade_to_version($db_version)) { 357 print "\nUpgrading from version ".($db_version-1)." to $db_version failed.\n\n"; 358 unless (ask_permission("Ignore this error and go on to the next version?", 0)) { 359 exit 3; 360 } 361 } 362 set_db_version($db_version); 363 } 364 365 print "\nDatabase is up-to-date at version $db_version.\n"; 366 367 END { 368 verbose("Releasing dbupgrade lock...\n"); 369 my ($lock_status) = $dbh->selectrow_array("SELECT RELEASE_LOCK('dbupgrade')"); 370 if (not defined $lock_status) { 371 print "Couldn't release lock because the lock does not exist.\n"; 372 exit 2; 373 } 374 if ($lock_status) { 375 verbose("Released lock.\n"); 376 } else { 377 print "Couldn't release lock because the lock is not held by this thread.\n"; 378 exit 2; 379 } 380 } 381 382 ################################################################################ 383 384 sub get_sql_tables { 385 my $sql_tables_ref = $dbh->selectcol_arrayref("SHOW TABLES"); 386 my %sql_tables; @sql_tables{@$sql_tables_ref} = (); 387 388 return %sql_tables; 389 } 390 391 sub get_db_version { 392 my $vers_value_should_be = "This value should always be a positive integer."; 393 my $vers_stop_now = "You should stop now and take a closer look."; 394 395 my @record = $dbh->selectrow_array("SELECT `value` FROM `dbupgrade` WHERE `name`='db_version'"); 396 if (@record) { 397 my $db_version = $record[0]; 398 if (not defined $db_version) { 399 print "'db_version' exists, but it has a NULL value. $vers_value_should_be $vers_stop_now\n"; 400 return; 401 } elsif ($db_version !~ /^-?\d+$/) { 402 print "'db_version' is set to the non-numeric value '$db_version'. $vers_value_should_be $vers_stop_now\n"; 403 return; 404 } elsif ($db_version < 0) { 405 print "'db_version' is set to the negative value '$db_version'. $vers_value_should_be $vers_stop_now\n"; 406 return; 407 } elsif ($db_version == 0) { 408 print "'db_version' is set 0, which is reserved to indicate a pre-automatic-upgrade version. $vers_value_should_be $vers_stop_now\n"; 409 return; 410 } else { 411 # db_version is positive! yay! 412 return $db_version; 413 } 414 } else { 415 print "The 'dbupgrade' table exists, but doesn't contain a 'db_version' setting. $vers_stop_now\n"; 416 return; 417 } 418 } 419 420 sub set_db_version { 421 my $vers = shift; 422 $dbh->do("UPDATE `dbupgrade` SET `value`=? WHERE `name`='db_version'", {}, $vers); 423 } 424 425 sub upgrade_to_version { 426 my $vers = shift; 427 my %info = %{$DB_VERSIONS[$vers]}; 428 429 print "\nUpgrading database from version " . ($vers-1) . " to $vers...\n"; 430 my $desc = $info{desc} || "has no description."; 431 print "(Version $vers $desc)\n"; 432 433 if (exists $info{global_code}) { 434 eval { $info{global_code}->() }; 435 if ($@) { 436 print "\nAn error occured while running the system upgrade code for version $vers:\n"; 437 print "$@"; 438 return 0 unless ask_permission("Ignore this error and keep going?", 0); 439 } 440 } 441 442 if (@ww_courses and exists $info{course_code}) { 443 foreach my $curr_course (@ww_courses) { 444 eval { $info{course_code}->($curr_course) }; 445 if ($@) { 446 print "\nAn error occured while running the course upgrade code for version $vers on course $curr_course:\n"; 447 print "$@"; 448 next if ask_permission("Ignore this error and go on to the next course?", 0); 449 } 450 } 451 } 452 453 print "Done.\n"; 454 return 1; 455 } 456 457 ################################################################################ 458 459 sub ask_permission { 460 my ($prompt, $default) = @_; 461 462 $default = 1 if not defined $default; 463 my $options = $default ? "[Y/n]" : "[y/N]"; 464 465 while (1) { 466 print "$prompt $options "; 467 my $resp = <STDIN>; 468 chomp $resp; 469 return $default if $resp eq ""; 470 return 1 if lc $resp eq "y"; 471 return 0 if lc $resp eq "n"; 472 $prompt = 'Please enter "y" or "n".'; 473 } 474 }
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |