#!/bin/sh
################################################################################
# Updates and recompiles a local KDE CVS tree                                  #
# 2000 by Frerich Raabe <raabe@kde.org>                                        #
################################################################################
# Do not edit this file, change kde-buildrc instead!                           #
################################################################################

# These strings are defined as variables to make the output look more
# consistent.
#
str_okay="done!"
str_error="failed!"

# The variables whose name is prefixed with ERR_ hold the error codes which
# are returned by the script and depend on the reason for aborting the
# execution.
#
# No error has been noticed, everything seems to be fine.
#
err_no_error="0"

# Could not change into a directory of a module - wrong owner/access
# settings?
#
err_change_into_mod_dir="1"

# Could not find the file 'Makefile.in' for a module, mostly happens if
# 'make -f Makefile.cvs' hasn't been executed for a module.
#
err_no_makefile_in="2"

# The 'configure' command failed for a module because the system doesn't
# support certain features - I hope you activated logfile generation... ;)
#
err_configure_fail="3"

# The compilation of a module failed - if the module is defined in
# $critical_modules (see below) the execution is aborted, otherwise the script
# will continue with the next module.
#
err_compile_fail="4"

# The installation of a module failed - this mostly happens if there's not
# enough free disk space on the partition which $KDEDIRS is mounted to.
#
err_install_fail="5"

# The $KDESRCDIR variable wasn't set or contains a non-existant directory.
#
err_inv_kdesrcdir="6"

# The $QTDIR variable wasn't set, points to a non-existant directory or
# doesn't contain a bin/, lib/, or include/ subdirectory.
#
err_inv_qtdir="7"

# There is no CVS client specified in the configuration file, or the
# specified client is invalid.
#
err_cvsclient_fail="8"

# There was no cvsup server specified in the configuration file.
#
err_inv_cvsup_server="9"

# The script was unable to create a temporary cvsup configuration file
# in /tmp, mostly due to insufficient diskspace.
#
err_no_temp_supfile="10"

# The configuration file couldn't be found.
#
err_no_config="11"

# Certain modules depend on others - those "base" modules which are required
# by others to compile and/or run should be listed here to ensure that the
# script is aborted in case on of these modules doesn't build.
#
critical_modules="kdesupport kdelibs kdebase"

# Internal variable, do not change.
#
dateformat="`date +%Y%m%d`"

# This function computes the time which was needed for a certain task.
#
compute_time() {
  duration=$[`date +%s`-$starttime]
  hours=`echo $[$duration / 3600] | sed -e "s/^[0-9]\$/0&/"`
  minutes=`echo $[$[$duration % 3600] / 60] | sed -e "s/^[0-9]\$/0&/"`
  seconds=`echo $[$duration % 60] | sed -e "s/^[0-9]\$/0&/"`
}

# This function installs a compiled CVS module.
#
install_module() {
  echo -n "  Installing..."
  if test "x$KDELOGDIR" != x; then
    echo "-> Installation <---------------------------------------------------------------" >> $logfile
    cmd_make_install="$cmd_make_install >> $logfile 2>&1"
    starttime=`date +%s`
   fi

  if eval ${cmd_make_install}; then
    if test "x$KDELOGDIR" != x; then
      compute_time
      echo "--------------------------------------------------------------------------------" >> $logfile
      echo "Time needed for installation of module $module: $hours:$minutes:$seconds" >> $logfile
      echo "" >> $logfile
      echo "Build of module $module successfully finished at `date +%c`" >> $logfile
      test "x$cmd_compress" != x && eval "$cmd_compress $logfile"
    fi
    echo -e "$str_okay"
    echo "Module $module successfully installed in $KDEDIRS!"
    if test "x$module" = xkdebase -a "x$HOMEDIR" != x; then
      for HOME in $HOMEDIR; do
        test -d $HOME/.kde -a -w $HOME/.kde && rm -rf $HOME/.kde
        test -e $HOME/.kderc -a -w $HOME/.kderc && rm -f $HOME/.kderc
      done
    fi
  else
    echo -e "$str_error"
    test "x$cmd_compress" != x && eval "$cmd_compress $logfile"
    echo "$critical_modules" | grep -q $module && exit $err_install_fail
  fi
}

# Get current configuration, bail out if it couldn't be found.
#
if !(test -e ./kde-buildrc); then
  echo "ERROR: Cannot load configuration file ./kde-buildrc!"; exit $err_no_config
else
  . ./kde-buildrc
fi

# This generates in 'modules' a list of the modules which shall be updated.
#
potential_modules=`find $KDESRCDIR -type d -mindepth 1 -maxdepth 1 -follow | sed -e "s@.*/?*@@"`
for module in $potential_modules; do
  if test -d $KDESRCDIR/$module/CVS -a -w $KDESRCDIR/$module && !(echo $EXCLUDE | grep -q $module); then
    modules="$modules $module"
  fi
done

# Various checks to ensure that the user didn't specify invalid data which
# would make our script break.
#
if test "x$CVSCLIENT" != xcvs -a "x$CVSCLIENT" != xcvsup; then
  echo "ERROR: Invalid CVS type specified, valid types are 'cvs' and 'cvsup'!"; exit $err_cvsclient_fail
fi
if test "x$KDELOGDIR" != x -a ! -d "$KDELOGDIR"; then
  if ! mkdir -p "$KDELOGDIR" > /dev/null 2>&1; then
    echo "WARNING: Could not create logfile-directory."
    echo "WARNING: Logfile generation deactivated."
    KDELOGDIR=""
  fi
else
  if test "x$KDELOGDIR" != x -a ! -w "$KDELOGDIR"; then
    echo "WARNING: Could not obtain write access to specified logfile-directory."
    echo "WARNING: Logfile generation deactivated."
    KDELOGDIR=""
  fi
fi
test "x$KDELOGDIR" != x && str_error="$str_error\x00a\x00d\x020\x020Check the logfile in $KDELOGDIR for further information."
if test ! -d "$KDESRCDIR"; then
  echo "ERROR: Invalid source directory specified!"; exit $err_inv_kdesrcdir
fi
if test ! -d "$QTDIR" -o ! -d "$QTDIR/lib" -o ! -d "$QTDIR/bin" -o ! -d "$QTDIR/include"; then
  echo "ERROR: Invalid Qt directory specified!"; exit $err_inv_qtdir
fi
if which bzip2 > /dev/null 2>&1; then
  cmd_compress="`which bzip2` -f "
else
  if which gzip > /dev/null 2>&1; then
    cmd_compress="`which gzip` -f "
  else
    echo "WARNING: Neither bzip2 nor gzip was found, disabling compression of logfiles."
    cmd_compress=""
  fi
fi

# Clean the installation directory if selected.
#
if test "x$INSTALLFROMSCRATCH" = xyes; then
  if test ! -w $KDEDIRS; then
    echo "Enter the root password to clean the installation directory."
    echo "WARNING: All files and directories in $KDEDIRS will be deleted!"
    echo -n "Please enter root "
    su -c"rm -rf $KDEDIRS/*"
  else
    rm -rf $KDEDIRS/*
  fi
fi

# Optionally activate cheap tweaks.
#
if test "x$TWEAKCOMPILE" = xyes; then
  CFLAGS="-O0"
  CXXFLAGS="-O0"
  export CFLAGS CXXFLAGS
fi

# This checks whether the user wants a certain branch and generates the
# command line. For cvsup users it even generates a supfile. :-)
#
if test "x$CVSCLIENT" = xcvs; then
  cmd_update="cvs up"
  if test "x$BRANCH" != x; then
    cmd_update="$cmd_update -dPr $BRANCH"
  else
    cmd_update="$cmd_update -dPA"
  fi
  if test "x$CVSROOT" = x; then
    if test "x$ACCOUNT" = x; then
      CVSROOT=":pserver:anonymous@anoncvs.kde.org:/home/kde"
    else
      CVSROOT=":pserver:$ACCOUNT@cvs.kde.org:/home/kde"
    fi
    export CVSROOT
  fi
else
  if test "x$CVSUPSERVER" = x; then
    echo "ERROR: No cvsup server specified!"
    exit $err_inv_cvsup_server
  fi
  supfile=`mktemp /tmp/$0.XXXXXX`
  if [ $? -ne 0 ]; then
    echo "ERROR: Could not create temporare cvsup configuration file in /tmp!"
    exit $err_no_temp_supfile
  fi
  cmd_update="cvsup $supfile"
  echo "*default host=$CVSUPSERVER" >> $supfile
  echo "*default base=$SRCDIR" >> $supfile
  echo "*default prefix=$SRCDIR" >> $supfile
  echo "*default relase=cvs" >> $supfile
  echo "*default delete" >> $supfile
  echo "*default compress" >> $supfile
  if test "x$BRANCH" != x; then
    echo "*default tag=$BRANCH" >> $supfile
  else
    echo "*default tag=." >> $supfile
  fi
  echo "*default use-rel-suffix" >> $supfile
  for module in $modules; do
    if test -d $KDESRCDIR/$module/CVS && !(echo $EXCLUDE | grep -q $module); then
      echo "$module" >> $supfile
    fi
  done
fi

# Guess what? We'll finally start checking out the modules. :-)
#
for module in $modules; do
  if test "x$KDELOGDIR" != x; then
    logfile="$KDELOGDIR/$module-build-$dateformat"
    echo "================================================================================" > $logfile
    echo "Build log of module $module, started on `date +%c`" >> $logfile
    echo "================================================================================" >> $logfile
    echo "" >> $logfile
  fi
  if ! cd $KDESRCDIR/$module; then
    echo "WARNING: Could not change into directory $KDESRCDIR/$module."
    echo "Update for module $module skipped."
  else
    echo -n "Updating module $module..."
    if test "x$KDELOGDIR" != x; then
      echo "-> Update <---------------------------------------------------------------" >> $logfile
      cmd_update_raw="$cmd_update >> $logfile 2>&1"
      starttime=`date +%s`
    fi
    
    eval ${cmd_update_raw}
    if test "x$module" != xkde-common -a "x$CVSCLIENT" = xcvs -a ! -e admin/Makefile.common; then
      if test -d ../kde-common; then
        ln -s ../kde-common/admin .
      else
        echo "WARNING: Could not find admin/ subdirectory for this module!"
      fi
    fi
    if test "x$CVS_CLEAN" = xyes -a -e admin/Makefile.common; then
      cmd_make_cvs_clean="make -f admin/Makefile.common cvs-clean"
      test "x$KDELOGDIR" != x && cmd_make_cvs_clean="$cmd_make_cvs_clean >> $logfile 2>&1"
    fi
    
    if eval ${cmd_make_cvs_clean}; then
      if test -e Makefile.cvs; then
        cmd_make_makefile_cvs="make -f Makefile.cvs"
        test "x$KDELOGDIR" != x && cmd_make_makefile_cvs="$cmd_make_makefile_cvs >> $logfile 2>&1"
        if eval ${cmd_make_makefile_cvs}; then
          echo "$str_okay"
        else
          echo -e "$str_error"
        fi
      fi
    else
      echo -e "$str_error"
    fi
    if test "x$KDELOGDIR" != x; then
      compute_time
      echo "--------------------------------------------------------------------------------" >> $logfile
      echo "Time needed for updating module $module: $hours:$minutes:$seconds" >> $logfile
      echo "" >> $logfile
    fi
  fi
done

for module in $KDEMODULES; do
  if ! cd $KDESRCDIR/$module; then
    if echo "$critical_modules" | grep -q $module; then
      echo "ERROR: Could not change into directory $KDESRCDIR/$module!"
      exit $err_change_into_mod_dir
    else
      echo "WARNING: Could not change into directory $KDESRCDIR/$module."
      echo "WARNING: Skipping module $module."
    fi
  else
    cd $KDESRCDIR/$module

    # Check whether 'make -f Makefile.cvs' has been called.
    #
    if test ! -e "Makefile.in"; then
      if echo "$critical_modules" | grep -q $module; then
        echo "ERROR: Please execute 'make -f Makefile.cvs' first for this module!"
        exit $err_no_makefile_in
      else
        echo "WARNING: 'make -f Makefile.cvs' seems not to be executed for this"
        echo "WARNING: module, skipping compilation."
      fi
    else
      echo "Building module: $module"

      # Configure the module.
      #
      echo -n "  Configuring..."
      cmd_configure="./configure --enable-debug --enable-profile --prefix=$KDEDIRS --with-qt-libs=$QTDIR"
      test "x$NICECOMPILE" = xyes && cmd_configure="nice $cmd_configure"
      if test "x$KDELOGDIR" != x; then
        logfile="$KDELOGDIR/$module-build-$dateformat"
        echo "-> Configuration <--------------------------------------------------------------" >> $logfile
        cmd_configure="$cmd_configure >> $logfile 2>&1"
        starttime=`date +%s`
      fi

      if eval ${cmd_configure}; then
        if test "x$KDELOGDIR" != x; then
          compute_time
          echo "--------------------------------------------------------------------------------" >> $logfile
          echo "Time needed for configuration of module $module: $hours:$minutes:$seconds" >> $logfile
          echo "" >> $logfile
        fi
        echo -e "$str_okay"

        # Compile the module.
        #
        echo -n "  Compiling..."
        cmd_make="make"
        echo "$critical_modules" | grep -q $module || cmd_make="$cmd_make -k"
        if test "x$KDELOGDIR" != x; then
          echo "-> Compilation <----------------------------------------------------------------" >> $logfile
          cmd_make="$cmd_make >> $logfile 2>&1"
          starttime=`date +%s`
        fi
        test "x$NICECOMPILE" = xyes && cmd_make="nice $cmd_make"

        if eval ${cmd_make}; then
          if test "x$KDELOGDIR" != x; then
            compute_time
            echo "--------------------------------------------------------------------------------" >> $logfile
            echo "Time needed for compilation of module $module: $hours:$minutes:$seconds" >> $logfile
            echo "" >> $logfile
          fi
          echo -e "$str_okay"

          # Install the module.
          #
          cmd_make_install="make"
          echo "$critical_modules" | grep -q $module || cmd_make_install="$cmd_make_install -k "
          test "x$NICECOMPILE" = xyes && cmd_make_install="nice $cmd_make_install"
          cmd_make_install="$cmd_make_install install"
          if test ! -w $KDEDIRS; then
            echo -n "  To install module $module, please enter the root "
            su -c"install_module"
          else
            install_module
          fi
        else
          echo -e "$str_error"
          test "x$cmd_compress" != x && eval "$cmd_compress $logfile"
          echo "$critical_modules" | grep -q $module && exit $err_compile_fail
        fi
      else
        echo -e "$str_error"
        test "x$cmd_compress" != x && eval "$cmd_compress $logfile"
        echo "$critical_modules" | grep -q $module && exit $err_configure_fail
      fi
    fi
  fi
done

exit $err_no_error

=head1 NAME

kde-build - Updates and recompiles a tree of KDE CVS modules

=head1 SYNOPSIS

        kde-build

=head1 DESCRIPTION

kde-build has been designed to keep a local copy of several KDE CVS
modules up to date and recompile them. Those modules have to be saved in a
common directory, e.g. something like

    ~/kde-src/
      |
      +-> kdelibs/
      |
      +-> kdebase/
      |
      \-> kdenetwork/

In this case, the KDE source directory would be ~/kde-src/. The script will
take care of compiling them in the correct order, checks for dependencies
and resolves them as far as possible.

Please not that, prior to first invokation of the script, the configuration
file 'F<kde-buildrc>' has to be modified to reflect the local environment,
such as paths etc.

=head1 RETURN VALUE

The following error codes are returned by the script.

0 - No error seems to have occured.

1 - The script could not change into the directory of a module.

2 - The script could not open the file 'Makefile.in' of a module.

3 - The configuration of a module failed.

4 - The compilation of a module failed.

5 - The installation of a module failed.

6 - An invalid source directory was specified.

7 - An invalid Qt directory was specified.

8 - An invalid CVS client was specified.

9 - No cvsup server was specified.

10 - The temporary CVSUP configuration file couldn't be created.

11 - The configuration file F<kde-buildrc> couldn't be loaded.

=head1 EXAMPLES

        cd ~/scripts/; vi ./kde-buildrc; ./kde-build

=head1 BUGS

Lots, mostly that the script wasn't written with portability in mind
and therefore won't run very nice on platforms other than Linux.

=head1 TODO

Add a DIAGNOSIS section to this man page.

=head1 AUTHOR

Frerich Raabe <raabe@kde.org>

=cut
