#! /bin/sh

cvs_args=""
checkout_args=""
output_dir=""
module=""
branch=HEAD
branch_specified=no
preserve_cvs=no

while test $# -ge 1; do
  case $1 in

    -h|--help)
      cat <<EOF
Usage: cvs2darcs [OPTIONS] [MODULE]
Check out a CVS module (MODULE) and convert to Darcs format.  Output
is a directory MODULE unless -o is specified.

Options:
                       -h, --help: print this help
                    -V, --version: print version/copyright info
     -o <dir>, --output-dir=<dir>: output to directory <dir> [default: MODULE]
   -b <branch>, --branch=<branch>: use CVS branch <branch> [default: HEAD]
               -p, --preserve-cvs: preserve CVS information in output-dir
                   -d, -R, -x, -z: as for 'cvs' command
EOF
      exit 0
      ;;

    -V|--version)
      cat <<EOF
cvs2darcs version 0.8

Copyright (c) 2004 David Roundy
Copyright (c) 2004 Ganesh Sittampalam
Copyright (c) 2004 Steven G. Johnson

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
EOF
      exit 0
      ;;

    -o) output_dir=$2; shift ;;
    -o*) output_dir=`echo "$1" |cut -do -f2-` ;;
    --output-dir=*) output_dir=`echo "$1" |cut -d= -f2-` ;;

    -b) branch=$2; branch_specified=yes; shift ;;
    -b*) branch=`echo "$1" |cut -do -f2-`; branch_specified=yes ;;
    --branch=*) branch=`echo "$1" |cut -d= -f2-`; branch_specified=yes ;;

    -p|--preserve-cvs) preserve_cvs=yes ;;

    -x|-R) cvs_args="$cvs_args $1" ;;
    -d|-z) cvs_args="$cvs_args $1 $2"; shift ;;
    -d*) cvs_args="$cvs_args $1" ;;
    -z*) cvs_args="$cvs_args $1" ;;

    [^-]*) module=$1 ;;

    *) echo "cvs2darcs: invalid argument $1" 1>&2; exit 1 ;;

  esac
  shift
done

if test "x$module" = x; then
  echo "cvs2darcs: no cvs module specified" 1>&2
  exit 1
fi

if test "x$output_dir" = x; then
  output_dir=$module
fi

if test -d "$output_dir" -a -d "$output_dir/CVS"; then
  echo "cvs2darcs: preserving pre-existing CVS directories in $output_dir"
  preserve_cvs=yes
  cvs_args="-d `cat $output_dir/CVS/Root` $cvs_args"
  module=`cat $output_dir/CVS/Repository`
  if test -r "$output_dir/CVS/Tag" -a $branch_specified = no; then
      case `cat $output_dir/CVS/Tag` in
	  T*) branch=`cat $output_dir/CVS/Tag | cut -dT -f2-`
	      echo "cvs2darcs: using branch $branch from CVS/Tag file" ;;
      esac
  fi
elif test -d "$output_dir"; then
  echo "cvs2darcs: $output_dir exists and is not a CVS directory" 1>&2
  exit 1
elif test -f "$output_dir"; then
  echo "cvs2darcs: $output_dir exists and is not a directory" 1>&2
  exit 1
fi

# Find directory with our Perl scripts:
d0=`which $0`; d0=`dirname $d0`; d0=`cd $d0; pwd`
for cvs2darcs_dir in "$d0" "${CVS2DARCS_DIR-/usr/local/share/cvs2darcs}" `pwd`; do
   test -r "$cvs2darcs_dir/cvs_convert.pl" && break
done
if test ! -r "$cvs2darcs_dir/cvs_convert.pl"; then
  echo "cvs2darcs: could not find cvs_convert.pl script" 1>&2
  exit 1
fi

set -e # exit on error

echo "cvs2darcs: cvs $cvs_args checkout $checkout_args -d $output_dir $module"
cvs $cvs_args checkout $checkout_args -d "$output_dir" $module

cd "$output_dir"

if test -d _darcs; then
    echo "cvs2darcs: updating existing darcs repository in $output_dir"
else
    echo "cvs2darcs: initializing darcs repository in $output_dir"
    darcs initialize
fi

if test "x$branch" = xHEAD; then
  echo "cvs2darcs: running $cvs2darcs_dir/cvs_convert.pl"
  perl $cvs2darcs_dir/cvs_convert.pl .
else
  # Recursively import parents of the branch

  tmp=${TMPDIR-/tmp}/cvs2darcs$$

  echo "cvs2darcs: running $cvs2darcs_dir/branch_detect.pl"
  perl $cvs2darcs_dir/branch_detect.pl . | tr -d '()' > $tmp
  cat $tmp

  revisions="$branch."
  curbranch=$branch
  while true; do
    branchline=`egrep "^$curbranch:" $tmp`
    if test "x$branchline" = x;  then
      echo "cvs2darcs: branch $branch was not found by branch_detect" 1>&2
      exit 1
    fi
    case $branchline in
      *INVALID*) echo "cvs2darcs: INVALID branch $curbranch" 1>&2; exit 1 ;;
    esac

    nextbranch=`echo $branchline | cut -d" " -f3`
    lastpatch=`echo $branchline | cut -d" " -f2`
    if test "x$nextbranch" = "xHEAD"; then
      revisions="$nextbranch.$lastpatch $revisions"
      break
    elif test "x$nextbranch" = x -o "x$nextbranch" = "x$curbranch:"; then
      # default parent is HEAD
      revisions="HEAD. $revisions"
      break
    else
      revisions="$nextbranch.$lastpatch $revisions"
    fi
    curbranch=$nextbranch
  done

  for r in $revisions; do
    b=`echo $r |cut -d. -f1`
    p=`echo $r |cut -d. -f2-`
    if test "x$b" = xHEAD; then
      bf=""
    else
      bf="-b $b"
    fi
    if test "x$p" = x; then
      pf=""
    else
      pf="-l $p"
    fi
    echo "cvs2darcs: running $cvs2darcs_dir/cvs_convert.pl $pf $bf"
    perl $cvs2darcs_dir/cvs_convert.pl $pf $bf .
  done

  rm -f $tmp
fi

if test $preserve_cvs = no; then
  echo "cvs2darcs: deleting CVS directories in $output_dir"
  find . -name CVS -type d -print |xargs rm -rf
else
  echo "cvs2darcs: preserving CVS directories in $output_dir, updating to $branch"
  cvs update -r $branch # necessary so that output_dir won't be a new branch
fi

echo "Done converting module $module in directory $output_dir"
