#!/bin/bash
description="Installs or updates drupal modules and sites"
argusage="<module> <version> [optional paths file]"
function usage {
echo "Description:" $description
echo "Usage: dget" $1 $argusage
echo "    - Default directories are specified in the file drupalpaths"
echo "      but an alternative paths file may be specified in any command"
echo "      Also, a final parameter can be added to indicate module type"
echo "      which can be module (default), theme or script"
}
d_install="Installs drupal or a contrib module"
d_cvs="Installs drupal or contrib module from cvs"
d_patch="Patches drupal or a contrib module"
d_revert="Reverts module (or drupal) to particular archived version (not implemented yet)"
d_remove="Removes a module, or all drupal code from paths" 
d_create="Creates a shared drupal website using symbolic links to drupal"
d_destroy="Destroys a website (opposite to create)" 
d_upgrade="Upgrades an installation to a new set of paths"
d_backup="Backs up the database associated with a drupal site" 
d_restore="Restores the database associated with a drupal site" 
d_test="Test command to see what directories will be used"
#todo: drupal 7; delete directories before ln; make symlinks more direct
# dget can be installed by 
# chmod +x dget ; ln -s `pwd`/dget /usr/local/bin
# mkdir -p /etc/opt/drupal
# mv d*paths /etc/opt/drupal

# change the following if you need to:
if [ -f /etc/opt/drupal/drupalpaths ] #recommended place to keep this
then
  PATHSDIR=/etc/opt/drupal
else
  PATHSDIR=.						#else just use current directory
fi
ftpdir=http://ftp.drupal.org/files/projects
acquiadir=http://acquia.com/files/downloads
MYSQLUSER=root

function usage2 {
echo
echo "Command is one of the following:"
echo "    install -" $d_install
echo "    cvs     -" $d_cvs
echo "    patch   -" $d_patch
#echo "    revert -" $d_revert
echo "    remove  -" $d_remove
echo "for sites:"
echo "    create  -" $d_create
echo "    destroy -" $d_destroy
echo "    upgrade -" $d_upgrade
echo "    backup  -" $d_remove
echo "    restore -" $d_remove
echo "    test    -" $d_test
echo "    --help  -" "this help message"
echo
echo "For help on a specific command, use: dget command help"
echo
echo "Version 2.8 December 18, 2008 (c) Andrew Fountain, licensed under the GPL v2"
}
args=$#
argsneeded=3	#overridden in individual commands if necessary
function helpcheck {
  if [ $args -lt $argsneeded ] || [ "$module" == "help" ] || [ "$module" == "--help" ]; then
    if [ "$module" != "help" ] && [ "$module" != "--help" ]; then
      echo
      echo "  ** not enough arguments supplied **"
    fi
    echo
    usage $command
    echo
    cusage
    exit
  fi
}
command=$1
module=$2
version=$3
modname=$module-$version

if [ $# -lt 1 ]; then
  echo
  echo "  ** not enough arguments supplied **"
  echo
  usage "command"; usage2
  echo
  exit
fi


#sort out directory paths for everything to go in
if [ -n "$5" ]; then
  type=$5
elif [ "$module" == "drupal" ]; then
  type="drupal"
elif [ "$module" == "acquia-drupal" ]; then
  type="drupal"
  ftpdir=$acquiadir
else
  type="module"
fi

source $PATHSDIR/drupalpaths
if [ -n "$4" ]; then		# alternative install paths
  if [ -e "$PATHSDIR/$4" ]; then		# name of a paths file
    source $PATHSDIR/$4
  else
    type=$4
  fi
fi
targetdir=$moduledir
if [ "$type" == "drupal" ]; then
  targetdir=$drupaldir
elif [ "$type" == "module" ]; then
  targetdir=$moduledir
elif [ "$type" == "theme" ]; then
  targetdir=$themedir
elif [ "$type" == "script" ]; then
  targetdir=$scriptdir
else
  echo "$PATHSDIR/$type does not match a paths file, and is not one of:  module, theme or script"
  exit
fi

########### dsymlinks function used by create and update
function dsymlinks {
  mkdir -p $site/sites/all
  ln -sfn $drupaldir $site/drupal_link #master symlink to drupal code
  ln -sfn drupal_link/includes $site
  ln -sfn drupal_link/misc $site
  ln -sfn drupal_link/modules $site
  ln -sfn drupal_link/profiles $site
  ln -sfn drupal_link/scripts $site
  ln -sfn drupal_link/themes $site
  ln -sfn drupal_link/cron.php $site
  ln -sfn drupal_link/index.php $site
  ln -sfn drupal_link/install.php $site
  ln -sfn drupal_link/update.php $site
  ln -sfn drupal_link/xmlrpc.php $site

  ln -sfn $themedir $site/sites/all/themes
  ln -sfn $moduledir $site/sites/all/modules
  ln -sfn $scriptdir $site/sites/all/scripts
}

########### install
if [ "$command" == "install" ]; then
  description=$d_install
  function cusage {
    echo "    - e.g. dget install drupal 6.2"
    echo "           dget install cck 6.x-1.x-dev"
    echo "           dget install drupal 5.7 d5paths #installs in alternative locations"
    echo "           dget install acquia-drupal 1.0.2-ISR.2988 a6paths #installs acquia drupal"
    echo "           dget install zen 6.x-1.1 theme (tells install to use theme dir)"
  }
  helpcheck
  echo "Installing $module $version into $targetdir"
  mkdir -p $drupaldir	#make sure all directories are there
  mkdir -p $moduledir
  mkdir -p $themedir
  mkdir -p $scriptdir
  mkdir -p $archivedir

  wget -qN $ftpdir/$modname.tar.gz
  return_val=$?
  if [ "$return_val" -ne 0 ]; then
    echo " **** failed to wget $ftpdir/$modname.tar.gz"
    exit
  fi
  if [ "$type" == "drupal" ]; then
    mkdir ~/dget_temp
    tar -zxf $modname.tar.gz -C ~/dget_temp
    if [ "$module" == "acquia-drupal" ]; then #get actual name of directory without build number
      modname=`ls ~/dget_temp`
    fi
    echo "   Moving new version of drupal from:" ~/dget_temp/$modname to $targetdir
    rm -fR $targetdir    #delete old version
    mv ~/dget_temp/$modname $targetdir
    rm -fR ~/dget_temp
  else
    rm -fR $targetdir/$module     #delete old version
    tar -zxf $modname.tar.gz -C $targetdir
    chdate=`stat -c %y $modname.tar.gz | awk '{printf $1 "\n"}'`  #date for archive copy
    mv $modname.tar.gz $archivedir/$modname'_'$chdate.tar.gz
  fi

########### cvs
elif [ "$command" == "cvs" ]; then
  description=$d_cvs
  function cusage {
    echo "    - same as install, but checks out from cvs"
    echo "    - e.g. dget cvs drupal HEAD d7paths"
    echo "    - e.g. dget cvs calendar DRUPAL-6--2:2008-07-04T20:00:00"
  }
  helpcheck
  echo "Checking out $module $version into $targetdir"
  cvsdir=pserver:anonymous:anonymous@cvs.drupal.org:/cvs/
  cvsfolder=drupal-contrib
  cvstarget=contributions/modules/
  if  [ "$4" == "themes" ]; then
    cvstarget=contributions/themes/
  fi
  if [ "$module" == "drupal" ]; then
    cvsfolder=drupal
    cvstarget=
  else
    targetdir=$targetdir/$module
  fi
  if [ -z "$version" ];then              # default version to HEAD
    version="HEAD"
  fi

  mkdir temp_cvs
  tempcvs=temp_cvs/$module
  echo installing from CVS $module version: $version into: $targetdir
  cvs -z6 -Q -d:$cvsdir$cvsfolder checkout -r $version -d $tempcvs $cvstarget$module
  return_val=$?
  if [ "$return_val" -ne 0 ]; then
    echo "cvs checkout failed for $modname"
  else
    echo "Archiving to: $archivedir/$modname-cvs_$(date +"%Y%m%d").tar.gz"
    mkdir -p $targetdir   # to create directories if not done yet
    mkdir -p $archivedir
    tar -zcf $archivedir/$modname-cvs_$(date +"%Y%m%d").tar.gz -C temp_cvs $module
    rm -fR $targetdir
    mv $tempcvs $targetdir
  fi
  rm -fR temp_cvs

########### patch
elif [ "$command" == "patch" ]; then
  description=$d_patch
  argusage="<relative path> <patchname> [optional paths file]"
  function cusage {
    echo "    - e.g. dget patch / xmlsitemap.d6.patch"
    echo "           dget patch /admin_menu admin_menu_10.patch"
  }
  helpcheck
   echo "Running patch $3 using directory $targetdir$module"
  patchlocation="http://drupal.org/files/issues"
  echo "Fetching $patchlocation/$3"
  wget -qN $patchlocation/$3
  patch -u -p0 -d $targetdir$module <$3
  rm -f $3

########### create
elif [ "$command" == "create" ]; then
  description=$d_create
  argusage="<root directory> <database name> [optional paths file]"
  function cusage {
    echo "    - e.g. dget create /var/www/mydrupalsite mysite"
    echo "           dget create /var/www/myd5site myd5 d5paths"
  }
  helpcheck
  site=$2
  echo "Creating drupal site in directory $site using database name: $3"
  rm -Rf $site
  mkdir -p $site
  cp $drupaldir/.htaccess $site  #in case we need to customize it for this site
  cp -R $drupaldir/sites $site
  dsymlinks
  #this assumes you have permission for MySQL and your drupal user already has grants to all databases
  echo -n "$MYSQLUSER password for MySQL to create new database $3 - "
  echo "CREATE DATABASE $3 CHARACTER SET utf8 COLLATE utf8_unicode_ci;" | mysql -u $MYSQLUSER -p
  #was: mysqladmin -u $MYSQLUSER -p create $3
  #note that the following code is only tested on Drupal 6.3 and above
  chmod 777 -R $site/sites/default
  cp $site/sites/default/default.settings.php $site/sites/default/settings.php
  chmod a+w $site/sites/default/settings.php
  echo "now visit the new site, and press enter to remove write permissions to sites/default"
  read input
  echo changing access on $site/sites/default
  chmod a-w $site/sites/default/settings.php
  chmod 755 $site/sites/default

########### destroy
elif [ "$command" == "destroy" ]; then
  description=$d_destroy
  argusage="<root directory> <database name>"
  argsneeded=3
  function cusage {
    echo "    - e.g. dget destroy /var/www/mydrupalsite mysite"
    echo "           dget destroy /home/user77/htdocs/myd5site u77d5"
  }
  helpcheck
  site=$2
  echo "Destroying drupal site in directory $site and database name: $3"
  rm -Rf $site
  echo -n "$MYSQLUSER password for MySQL to drop database $3 - "
  mysqladmin --force -u $MYSQLUSER -p drop $3

########### backup
elif [ "$command" == "backup" ]; then
  description=$d_backup
  argusage="<database name> <optional backup directory, default to current>"
  argsneeded=2
  function cusage {
    echo "    - e.g. dget backup mysite"
    echo "           dget backup u77d5  /home/user77/htdocs/myd5site"
  }
  helpcheck
  if [ -n "$3" ]; then
    BACKFILE=$3/$2_$(date +"%Y-%m-%d").sql.bz
  else
    BACKFILE=$2_$(date +"%Y-%m-%d").sql.bz
  fi
  echo "Backup drupal database: $2 into file: $BACKFILE"
  echo -n "$MYSQLUSER password for MySQL to backup database $2 - "
  nice mysqldump -u $MYSQLUSER -p --compress --add-drop-table --extended-insert $2 | bzip2 -9 >$BACKFILE

########### restore
elif [ "$command" == "restore" ]; then
  description=$d_restore
  argusage="<database name> <optional backup path, default: current path_today>"
  argsneeded=2
  function cusage {
    echo "    - e.g. dget restore mysite"
    echo "           dget restore u77d5  /home/user77/htdocs/u77d5_2008-11-30.sql.bz"
  }
  helpcheck
  if [ -n "$3" ]; then
    BACKFILE=$3
  else
    BACKFILE=$2_$(date +"%Y-%m-%d").sql.bz
  fi
  echo "Restore drupal site from file $BACKFILE for database name: $2"
  read -s -p "Enter $MYSQLUSER password for MySQL to restore database $2 :" MYPASS
  #clever code to drop all old tables to guarantee a clean start
  mysqldump -u $MYSQLUSER -p$MYPASS --add-drop-table --no-data $2 | grep ^DROP | mysql -u $MYSQLUSER -p$MYPASS $2
  nice bzip2 -dc < $BACKFILE | mysql -u $MYSQLUSER -p$MYPASS $2
  echo "Done"

########### upgrade
elif [ "$command" == "upgrade" ]; then
  description=$d_upgrade
  argusage="<root directory> x [optional paths file]"
  if [ $args == 3 ]; then
    echo
    echo "**** there must be exactly 2 or 4 arguments ****"
    argsneeded=4
  else
    argsneeded=2
  fi
  function cusage {
    echo "    - Note that x is a placeholder argument"
    echo "      and only needed if there is an optional alternative paths file"
    echo "    - e.g. dget upgrade /var/www/mydrupalsite"
    echo "           dget upgrade /home/fred/html x d7paths"
  }
  helpcheck
  site=$2
  echo "upgrading drupal site in directory: $site"
  echo "         using drupal contained in: $drupaldir"
  dsymlinks

########### revert
elif [ "$command" == "revert" ]; then
  description=$d_revert
  function cusage {
    echo "    - e.g. dget revert cck 6.2-1.x-dev_20080101"
  }
  helpcheck
  echo "Nothing has been done"

########### remove
elif [ "$command" == "remove" ]; then
  description=$d_remove
  argusage="module x [optional paths file]"
  argsneeded=2
  function cusage {
    echo "    - If the module name is all, then the entire installation is removed"
    echo "      There is no version number needed, so the third parameter is just the placeholder x"
    echo "      and only needed if there is an optional alternative paths file"
    echo "    - e.g. dget remove cck x d5paths"
    echo "           dget remove drupal"
    echo "           dget remove all"
  }
  helpcheck
  if [ "$module" == "all" ]; then
    echo -n "Do you want to remove: $drupaldir, $moduledir, $themedir and $scriptdir (y/n)?"
    read yn
    if [ "$yn" == "y" ]; then
      rm -Rf $drupaldir 
      rm -Rf $moduledir 
      rm -Rf $themedir 
      rm -Rf $scriptdir
      echo "Directories deleted"
    fi
  else
    echo -n "Do you want to remove: $module from $targetdir (y/n)?"
    read yn
    if [ "$yn" == "y" ]; then
      echo "Removing $module from $targetdir"
      rm -fR $targetdir/$module     #delete old version
    fi
  fi

########### test
elif [ "$command" == "test" ]; then
  description=$d_test
  function cusage {
    echo "    - e.g. dget test drupal 6.2 d7paths"
  }
  helpcheck
  echo "**test**"
  echo "Modulename: $module"
  echo "Version:    $version"
  echo "Target:     $targetdir"
  echo "Type:       $type"

########### --help
elif [ "$command" == "--help" ]; then
  echo
  usage "command"; usage2

else
  echo
  echo "  ** Unknown command:" $command
  echo
  usage "command"; usage2
fi
exit
