#!/usr/bin/perl -w

use strict;
use warnings;

use Pod::Usage;
use Getopt::Long;
use File::Type;
use Log::Log4perl;
use Drupal::Admin;


# Logging
my $log_conf = q/
	log4perl.logger.main = INFO, Screen
        log4perl.logger.Drupal.Admin = ERROR, Screen
        log4perl.logger.Drupal.Admin.ModuleState = ERROR, Screen
        log4perl.logger.Drupal.Admin.ModuleCheckbox = ERROR, Screen
        log4perl.logger.Drupal.Admin.Status = ERROR, Screen

	log4perl.appender.Screen        = Log::Log4perl::Appender::Screen
	log4perl.appender.Screen.stderr = 0
        log4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayout

        # log4perl.appender.Logfile = Log::Log4perl::Appender::File
        # log4perl.appender.Logfile.filename = drupal-upgrade.log
        # log4perl.appender.Logfile.mode = write 
        # log4perl.appender.Logfile.layout = Log::Log4perl::Layout::SimpleLayout

/;
Log::Log4perl::init( \$log_conf );
my $logger = Log::Log4perl::get_logger();

my($user, $password, $baseurl, $basepath, $tar, $drupaltgz);

GetOptions (
	    'user=s' => \$user,
	    'password=s' => \$password,
	    'baseurl=s' => \$baseurl,
	    'basepath=s' => \$basepath,
	    'tar=s' => \$tar
	   ) or pod2usage(2);

$drupaltgz = shift;

pod2usage(2) unless defined($user)
  && defined($password)
  && defined($baseurl)
  && defined($basepath)
  && defined($drupaltgz);

# Set $tar if it hasn't been given as an option
if( !defined($tar) ){
  $tar = `which tar`;
  chomp($tar);
  $logger->logdie("No tar given and could not find one in path") if $?;
}

&check_path_sanity;
&check_tar;

my $dpa = new Drupal::Admin(baseurl => $baseurl);

$logger->info("Logging in to site");
$dpa->login(user => $user, password => $password);

# Offline the site
$logger->info("Offlining site");
$dpa->offline;

# Save the original theme
my $original_theme = $dpa->defaulttheme;

# Set the theme to bluemarine (core theme)
$logger->info("Setting theme to bluemarine");
$dpa->defaulttheme('bluemarine');

# Save the original module state
my $original_modstate = $dpa->modulestate;

# Disable all optional modules
$logger->info("Disabling all optional modules");
my $modstate = $dpa->modulestate;
$modstate->core_required_disable;
$modstate->commit;

# Extract new drupal files
$logger->info("Extracting new drupal files");
system("cd $basepath; $tar --strip=1 -xf $drupaltgz");

# Run update
$logger->info("Running update (1)");
$dpa->update;

# Restore original module config
$logger->info("Restoring original module configuration");
$original_modstate->commit;

# Run update again
$logger->info("Running update (2)");
$dpa->update;

# Restore original theme
$logger->info("Restoring original theme \"$original_theme\"");
$dpa->defaulttheme($original_theme);

# Online the site
$logger->info("Onlining site");
$dpa->online;


#
# Some simple sanity checks
#
sub check_path_sanity {
  # $drupaltgz must be readable
  $logger->logdie("The drupal archive \"$drupaltgz\" is not readable") unless -r $drupaltgz;

  # drupaltgz should be of the form "drupal-N.N.tar.gz
  $logger->logdie("The drupal archive \"$drupaltgz\" is not of the form \"drupal-N.N.tar.gz\"")
    unless $drupaltgz =~ /drupal-\d+\.\d+\.tar\.gz$/;

  # $drupaltgz must be gzipped data
  my $t = new File::Type;
  $logger->logdie("The file \"$drupaltgz\" does not appear to be a gzipped archive")
    unless $t->mime_type($drupaltgz) =~ /gzip/;

  # $basepath must be writeable
  $logger->logdie("The drupal filesystem base path \"$basepath\" must be a writeable directory")
    unless -d $basepath && -w $basepath;
}

#
# Check that we have GNU tar
#
sub check_tar {
  open(TAR, "$tar --version|") || $logger->logdie("Could not open a pipe to $tar");
  while( my $line = <TAR> ){
    return if $line =~ /GNU/;
  }

  $logger->logdie("$tar does not appear to be GNU tar");
}


__END__

=pod

=head1 NAME 

drupal-upgrade - Script to perform drupal core upgrade

=head1 SYNOPSIS

drupal-upgrade [options] /path/to/new_drupal.tgz

 Required arguments:
  --user        drupal admin user
  --password    drupal admin password
  --baseurl     base URL for the drupal site (no terminal slash)
  --basepath    base path for the drupal installation

 Options:
  --tar         path to gnu tar

=head1 NOTES

This script overwrites the current drupal files with the new drupal
files. It does NOT make any backups. Make sure you have a backup of
your current drupal installation and database!

Script requires GNU tar to be in path, or specified as an option.
