| 1 | ################################################################################ |
1 | ################################################################################ |
| 2 | # WeBWorK Online Homework Delivery System |
2 | # WeBWorK Online Homework Delivery System |
| 3 | # Copyright © 2000-2006 The WeBWorK Project, http://openwebwork.sf.net/ |
3 | # Copyright © 2000-2006 The WeBWorK Project, http://openwebwork.sf.net/ |
| 4 | # $CVSHeader: webwork2/lib/WeBWorK/Utils/CourseManagement.pm,v 1.35 2006/09/26 15:57:41 sh002i Exp $ |
4 | # $CVSHeader: webwork2/lib/WeBWorK/Utils/CourseManagement.pm,v 1.37 2006/09/29 19:39:53 sh002i Exp $ |
| 5 | # |
5 | # |
| 6 | # This program is free software; you can redistribute it and/or modify it under |
6 | # This program is free software; you can redistribute it and/or modify it under |
| 7 | # the terms of either: (a) the GNU General Public License as published by the |
7 | # the terms of either: (a) the GNU General Public License as published by the |
| 8 | # Free Software Foundation; either version 2, or (at your option) any later |
8 | # Free Software Foundation; either version 2, or (at your option) any later |
| 9 | # version, or (b) the "Artistic License" which comes with this package. |
9 | # version, or (b) the "Artistic License" which comes with this package. |
| … | |
… | |
| 27 | use warnings; |
27 | use warnings; |
| 28 | use Carp; |
28 | use Carp; |
| 29 | use DBI; |
29 | use DBI; |
| 30 | use File::Path qw(rmtree); |
30 | use File::Path qw(rmtree); |
| 31 | use File::Spec; |
31 | use File::Spec; |
|
|
32 | use String::ShellQuote; |
| 32 | use WeBWorK::CourseEnvironment; |
33 | use WeBWorK::CourseEnvironment; |
| 33 | use WeBWorK::Debug; |
34 | use WeBWorK::Debug; |
| 34 | use WeBWorK::Utils qw(runtime_use readDirectory); |
35 | use WeBWorK::Utils qw(runtime_use readDirectory); |
| 35 | |
36 | |
| 36 | our @EXPORT = (); |
37 | our @EXPORT = (); |
| … | |
… | |
| 256 | ); |
257 | ); |
| 257 | my $sourceDir = $sourceCE->{courseDirs}->{templates}; |
258 | my $sourceDir = $sourceCE->{courseDirs}->{templates}; |
| 258 | |
259 | |
| 259 | if (-d $sourceDir) { |
260 | if (-d $sourceDir) { |
| 260 | my $destDir = $ce->{courseDirs}->{templates}; |
261 | my $destDir = $ce->{courseDirs}->{templates}; |
| 261 | my $errno = system "/bin/cp -R $sourceDir/* $destDir"; |
262 | my $cp_cmd = "2>&1 /bin/cp -R " . shell_quote($sourceDir) . "/* " . shell_quote($destDir); |
|
|
263 | my $cp_out = readpipe $cp_cmd; |
| 262 | if ($errno) { |
264 | if ($?) { |
| 263 | warn "Failed to copy templates from course '$sourceCourse' (errno=$errno): $!\n"; |
265 | my $exit = $? >> 8; |
|
|
266 | my $signal = $? & 127; |
|
|
267 | my $core = $? & 128; |
|
|
268 | warn "Failed to copy templates from course '$sourceCourse' with command '$cp_cmd' (exit=$exit signal=$signal core=$core): $cp_out\n"; |
| 264 | } |
269 | } |
| 265 | } else { |
270 | } else { |
| 266 | warn "Failed to copy templates from course '$sourceCourse': templates directory '$sourceDir' does not exist.\n"; |
271 | warn "Failed to copy templates from course '$sourceCourse': templates directory '$sourceDir' does not exist.\n"; |
| 267 | } |
272 | } |
| 268 | } |
273 | } |
| … | |
… | |
| 336 | } |
341 | } |
| 337 | |
342 | |
| 338 | ##### step 1: move course directory ##### |
343 | ##### step 1: move course directory ##### |
| 339 | |
344 | |
| 340 | # move top-level course directory |
345 | # move top-level course directory |
| 341 | my $mvCmd = $oldCE->{externalPrograms}->{mv}; |
346 | my $mv_cmd = "2>&1"." ".$oldCE->{externalPrograms}{mv}." ".shell_quote($oldCourseDir)." ".shell_quote($newCourseDir); |
| 342 | debug("moving course dir: $mvCmd $oldCourseDir $newCourseDir\n"); |
347 | debug("moving course dir: $mv_cmd"); |
| 343 | my $mvResult = system $mvCmd, $oldCourseDir, $newCourseDir; |
348 | my $mv_out = readpipe $mv_cmd; |
| 344 | $mvResult and die "failed to move course directory with command: '$mvCmd $oldCourseDir $newCourseDir' (errno: $mvResult): $!\n"; |
349 | if ($?) { |
|
|
350 | my $exit = $? >> 8; |
|
|
351 | my $signal = $? & 127; |
|
|
352 | my $core = $? & 128; |
|
|
353 | die "Failed to move course directory with command '$mv_cmd' (exit=$exit signal=$signal core=$core): $mv_out\n"; |
|
|
354 | } |
| 345 | |
355 | |
| 346 | # get new course environment |
356 | # get new course environment |
| 347 | my $newCE = $oldCE->new( |
357 | my $newCE = $oldCE->new( |
| 348 | $oldCE->{webworkDirs}->{root}, |
358 | $oldCE->{webworkDirs}->{root}, |
| 349 | $oldCE->{webworkURLs}->{root}, |
359 | $oldCE->{webworkURLs}->{root}, |
| … | |
… | |
| 395 | next; |
405 | next; |
| 396 | } |
406 | } |
| 397 | |
407 | |
| 398 | # try to move the directory |
408 | # try to move the directory |
| 399 | debug("Going to move $oldDir to $newDir...\n"); |
409 | debug("Going to move $oldDir to $newDir...\n"); |
| 400 | my $mvResult = system $mvCmd, $oldDir, $newDir; |
410 | my $mv_cmd = "2>&1"." ".$oldCE->{externalPrograms}{mv}." ".shell_quote($oldDir)." ".shell_quote($newDir); |
| 401 | $mvResult and warn "$courseDirName: Failed to move directory with command: '$mvCmd $oldDir $newDir': $! (errno: $mvResult) You will have to move this directory manually.\n"; |
411 | my $mv_out = readpipe $mv_cmd; |
|
|
412 | if ($?) { |
|
|
413 | my $exit = $? >> 8; |
|
|
414 | my $signal = $? & 127; |
|
|
415 | my $core = $? & 128; |
|
|
416 | warn "Failed to move directory with command '$mv_cmd' (exit=$exit signal=$signal core=$core): $mv_out\n"; |
|
|
417 | } |
| 402 | } else { |
418 | } else { |
| 403 | debug("oldDir $oldDir was already moved.\n"); |
419 | debug("oldDir $oldDir was already moved.\n"); |
| 404 | } |
420 | } |
| 405 | } |
421 | } |
| 406 | |
422 | |
| … | |
… | |
| 597 | die "$courseID: course database dump failed.\n" unless $archiveHelperResult; |
613 | die "$courseID: course database dump failed.\n" unless $archiveHelperResult; |
| 598 | |
614 | |
| 599 | ##### step 2: tar and gzip course directory ##### |
615 | ##### step 2: tar and gzip course directory ##### |
| 600 | |
616 | |
| 601 | # archive top-level course directory |
617 | # archive top-level course directory |
| 602 | #FIXME (check) don't follow links |
|
|
| 603 | #FIXME archive relative to the coursesDir |
|
|
| 604 | my $tarCmd = $ce->{externalPrograms}->{tar}; |
618 | my $tar_cmd = "2>&1"." ".$ce->{externalPrograms}{tar} |
| 605 | debug("archiving course dir: $tarCmd $archivePath $courseDir \n"); |
619 | . " -C " . shell_quote($coursesDir) |
| 606 | my $tarStatement = "cd $coursesDir && $tarCmd -zcf $archivePath $courseID"; |
620 | . " -czf " . shell_quote($archivePath) |
| 607 | my $tarResult = system $tarStatement ; |
621 | . " " . shell_quote($courseID); |
| 608 | $tarResult and die "Failed to tar course directory with command:<br>\n '$tarStatement ' <br>\n(errno: $tarResult): $!<br>\n"; |
622 | debug("archiving course dir: $tar_cmd\n"); |
| 609 | |
623 | my $tar_out = readpipe $tar_cmd; |
|
|
624 | if ($?) { |
|
|
625 | my $exit = $? >> 8; |
|
|
626 | my $signal = $? & 127; |
|
|
627 | my $core = $? & 128; |
|
|
628 | die "Failed to archive course directory with command '$tar_cmd' (exit=$exit signal=$signal core=$core): $tar_out\n"; |
|
|
629 | } |
| 610 | } |
630 | } |
| 611 | |
631 | |
| 612 | ################################################################################ |
632 | ################################################################################ |
| 613 | |
633 | |
| 614 | sub unarchiveCourse { |
634 | sub unarchiveCourse { |
| … | |
… | |
| 627 | my $ce = $options{ce}; |
647 | my $ce = $options{ce}; |
| 628 | my %dbOptions = defined $options{dbOptions} ? %{ $options{dbOptions} } : (); |
648 | my %dbOptions = defined $options{dbOptions} ? %{ $options{dbOptions} } : (); |
| 629 | my $coursesDir = $ce->{webworkDirs}->{courses}; |
649 | my $coursesDir = $ce->{webworkDirs}->{courses}; |
| 630 | |
650 | |
| 631 | ############################################################### |
651 | ############################################################### |
| 632 | # RPC call to system to tar and gzip the courses directory |
652 | # RPC call to tar and gzip the courses directory |
| 633 | ############################################################### |
653 | ############################################################### |
| 634 | my $tarCmd = $ce->{externalPrograms}->{tar}; |
654 | my $tar_cmd = "2>&1"." ".$ce->{externalPrograms}{tar} |
| 635 | debug("unarchiving course dir: cd $coursesDir && $tarCmd -zxf $archivePath \n"); # the z is ignored. |
655 | . " -C " . shell_quote($coursesDir) |
| 636 | my $tarStatement = "cd $coursesDir && $tarCmd -zxf $archivePath "; |
656 | . " -xzf " . shell_quote($archivePath); |
| 637 | my $tarResult = system $tarStatement ; |
657 | debug("unarchiving course dir: $tar_cmd\n"); |
| 638 | $tarResult and die "Failed to untar course directory with command: '$tarStatement ' (errno: $tarResult): $!\n"; |
658 | my $tar_out = readpipe $tar_cmd; |
|
|
659 | if ($?) { |
|
|
660 | my $exit = $? >> 8; |
|
|
661 | my $signal = $? & 127; |
|
|
662 | my $core = $? & 128; |
|
|
663 | die "Failed to unarchive course directory with command '$tar_cmd' (exit=$exit signal=$signal core=$core): $tar_out\n"; |
|
|
664 | } |
| 639 | ############################################################### |
665 | ############################################################### |
| 640 | # End RPC call to system to tar and gzip the courses directory |
666 | # End RPC call to tar and gzip the courses directory |
| 641 | ############################################################### |
667 | ############################################################### |
| 642 | |
668 | |
| 643 | # read the global.conf and course.conf files for the newly created course |
669 | # read the global.conf and course.conf files for the newly created course |
| 644 | debug( "Checking that course directory is at $coursesDir/$courseID: = ", -e "$coursesDir/$courseID"); |
670 | debug( "Checking that course directory is at $coursesDir/$courseID: = ", -e "$coursesDir/$courseID"); |
| 645 | my $ce2 = WeBWorK::CourseEnvironment->new( |
671 | my $ce2 = WeBWorK::CourseEnvironment->new( |