#!/bin/sh

##
# Check out/update all modules in a CVS repository.
##
# Wilfredo Sanchez | wsanchez@mit.edu
##

#set -e # exit on error
set -u # undefined variable is an error

Destination='/afs/sipb/project/darwin/src'
   Location=''
    CVSROOT=':pserver:sipb@anoncvs.opensource.apple.com:/cvs/Darwin'
KILLMODULES="cygnus XFree86 cc egcs"

##
# Usage
##

usage ()
{
    echo "Usage: $(basename $0) <options> [-d <repository>] [-o <destination>]"
    echo "                        [-s <location>]"
    echo "	<repository>: CVS repository to check out from"
    echo "		($CVSROOT)"
    echo "	<destination>: Destination directory"
    echo "		($Destination)"
    echo "	<location>: Prefix mask of locations"
    echo "		($Location)"
    echo "Options: -v be verbose"
    echo "         -u update existing modules"
    echo "         -c checkout non-existing modules"
    echo "         -l make symlinks in <destination>/modules"
    echo "If -u -c and -l are not specified, all three are implied."
    exit 1;
}

##
# Handle command line
##

        q_Flag='-Q'
Default_Action='YES'
      Checkout='default'
        Update='default'
          Link='default'
	  
if ! args=$(getopt cd:hlo:s:uv $*); then usage; fi
set -- ${args}
for option; do
    case "${option}" in
      -d)
	CVSROOT="$2"
	shift; shift
	;;
      -o)
	Destination="$2"
	shift; shift
	;;
      -s)
	Location="$2"
	shift; shift
	;;
      -v)
	q_Flag=""
	shift
	;;
      -h)
	usage
	;;
      -c)
	Default_Action='NO'; Checkout='YES'
	;;
      -u)
	Default_Action='NO';   Update='YES'
	;;
      -l)
	Default_Action='NO';     Link='YES'
	;;
    esac
done

if [ "${Checkout}" = "default" ]; then Checkout="${Default_Action}"; fi
if [ "${Update}"   = "default" ]; then   Update="${Default_Action}"; fi
if [ "${Link}"     = "default" ]; then     Link="${Default_Action}"; fi

export CVSROOT

willKill="NO"

shouldKill ()
{
    mod=$1;

    for kill in $KILLMODULES; do
	if [ $kill = $mod ]; then
	     willKill="YES"
	     return
	fi
    done

    willKill="NO"
}


##
# Do The Right Thing
##

# Get a list of all modules.
# We are looking for (<module>,<location>) pairs.
# Filter out -d modules and remove nested modules.
#
# [ ssen: not all sed's support [[:space:]] notation ]

set -- $(
    cvs checkout -c |
    sed -e 's/^\([ ].*\)$//'		       \
	-e 's/^[^ ]*[ ]*-d[ ]*.*$//'	       \
	-e 's/^\([^&]*\)&.*$/\1/'
    )

if [ ! -d "${Destination}"         ]; then mkdir "${Destination}"        ; fi
if [ ! -d "${Destination}/HEAD"    ]; then mkdir "${Destination}/HEAD"   ; fi
if [ ! -d "${Destination}/modules" ]; then mkdir "${Destination}/modules"; fi

topcwd=$(pwd)

while [ $# != 0 ]; do
      module=$1; shift
    location=$(dirname "$1"); shift

    isPrefix=$(expr match "${location}/${module}" "${Location}.*")
    shouldKill "${module}"

    if [ $willKill = "YES" ] || [ $isPrefix -eq 0 ]; then
	if [ -z "${q_Flag}" ]; then
	    echo "Skipping module ${module}"
	fi
    else
	if [ "${Update}" = "YES" ]; then
	    cd "$topcwd"
	    if [ -d "${Destination}/HEAD/${location}/${module}/CVS" ]; then
		if [ -z "${q_Flag}" ]; then
		    echo "Updating module ${module}"
		fi
		cd "${Destination}/HEAD/${location}/${module}"
		cvs ${q_Flag} update -f -P . 2>&1
	    fi
	fi
	if [ "${Checkout}" = "YES" ]; then
	    cd "$topcwd"
	    if [ ! -d "${Destination}/HEAD/${location}/${module}/CVS" ]; then
		if [ -z "${q_Flag}" ]; then
		    echo "Checking out module ${module}"
		fi
		mkdir -p "${Destination}/HEAD/${location}"
		rm -fr "${Destination}/HEAD/${location}/${module}"
		cd "${Destination}/HEAD/${location}"
		cvs ${q_Flag} checkout -f -P "${module}" 2>&1
	    fi
	fi
	if [ "${Link}" = "YES" ]; then
	    cd "$topcwd"
	    if [ -d "${Destination}/HEAD/${location}/${module}/CVS" ]; then
		if [ -z "${q_Flag}" ]; then
		    echo "modules/${module} -> HEAD/${location}/${module}";
		fi
		rm -f "${Destination}/modules/${module}"
		ln -s "../HEAD/${location}/${module}" "${Destination}/modules/${module}"
	    fi
	fi
    fi
done
