the testsuite was just added to MirBSD
authormirabilos <m@mirbsd.org>
Sat, 22 Oct 2016 15:33:37 +0000 (17:33 +0200)
committermirabilos <m@mirbsd.org>
Sat, 22 Oct 2016 15:33:37 +0000 (17:33 +0200)
lib/test-getdate.sh [new file with mode: 0644]
src/sanity.config.sh.in [new file with mode: 0644]
src/sanity.sh [new file with mode: 0644]

diff --git a/lib/test-getdate.sh b/lib/test-getdate.sh
new file mode 100644 (file)
index 0000000..0057ba6
--- /dev/null
@@ -0,0 +1,344 @@
+#! /bin/sh
+
+# Test that a getdate executable meets its specification.
+#
+# Copyright (C) 2004 Free Software Foundation, Inc.
+#
+# 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, 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.  */
+
+
+# as this uses POSIX behaviour and does not count leap seconds...
+if test -n "$GETDATE_LD_PRELOAD"; then
+       LD_PRELOAD=$GETDATE_LD_PRELOAD
+       export LD_PRELOAD
+fi
+
+###
+### Globals
+###
+LOGFILE=`pwd`/getdate.log
+if test -f "$LOGFILE"; then
+       mv $LOGFILE $LOGFILE~
+fi
+
+
+
+###
+### Functions
+###
+verify ()
+{
+       echo >>getdate-got
+       if cmp getdate-expected getdate-got >getdate.cmp; then
+               echo "PASS: $1" >>$LOGFILE
+       else
+               cat getdate.cmp >>$LOGFILE
+               echo "** expected: " >>$LOGFILE
+               cat getdate-expected >>$LOGFILE
+               echo "** got: " >>$LOGFILE
+               cat getdate-got >>$LOGFILE
+               echo "FAIL: $1" | tee -a $LOGFILE >&2
+               echo "Failed!  See $LOGFILE for more!" >&2
+               exit 1
+       fi
+}
+
+
+
+skip ()
+{
+       echo "SKIP: $1"${2+" ($2)"} >>$LOGFILE
+}
+
+
+
+# Prep for future calls to valid_timezone().
+#
+# This should set $UTZ to three spaces, `GMT', `Unrecognized/Unrecognized', or
+# possibly the empty string, depending on what system we are running on.  With
+# any luck, this will catch any other existing variations as well.  The way it
+# is used later does have the disadvantage of rejecting at least the
+# `Europe/London' timezone for half the year when $UTZ gets set to `GMT', like
+# happens on NetBSD, but, since I haven't come up with any better ideas and
+# since rejecting a timezone just causes a few tests to be skipped, this will
+# have to do for now.
+#
+# UTZ stands for Unrecognized Time Zone.
+UTZ=`TZ=Unrecognized/Unrecognized date +%Z`
+
+# The following function will return true if $1 is a valid timezone.  It will
+# return false and set $skipreason, otherwise.
+#
+# Clobbers $NTZ & $skipreason.
+#
+# SUS2 says `date +%Z' will return `no characters' if `no timezone is
+# determinable'.  It is, unfortunately, not very specific about what
+# `determinable' means.  On GNU/Linux, `date +%Z' returns $TZ when $TZ is not
+# recognized.  NetBSD 1.6.1 "determines" that an unrecognizable value in $TZ
+# really means `GMT'.  On Cray, the standard is ignored and `date +%Z' returns
+# three spaces when $TZ is not recognized.  We test for all three cases, plus
+# the empty string for good measure, though I know of no set of conditions
+# which will actually cause `date +%Z' to return the empty string SUS2
+# specifies.
+#
+# Due to the current nature of this test, this will not work for the
+# three-letter zone codes on some systems.  e.g.:
+#
+#      test `TZ=EST date +%Z` = "EST"
+#
+# should, quite correctly, evaluate to true on most systems, but:
+#
+#      TZ=Asia/Calcutta date +%Z
+#
+# would return `IST' on GNU/Linux, and hopefully any system which understands
+# the `Asia/Calcutta' timezone, and `   ' on Cray.  Similarly:
+#
+#      TZ=Doesnt_Exist/Doesnt_Exist date +%Z
+#
+# returns `Doesnt_Exist/Doesnt_Exist' on GNU/Linux and `   ' on Cray.
+#
+# Unfortunately, the %z date format string (-HHMM format time zone) supported
+# by the GNU `date' command is not part of any standard I know of and,
+# therefore, is probably not portable.
+#
+valid_timezone ()
+{
+       NTZ=`TZ=$1 date +%Z`
+       if test "$NTZ" = "$UTZ" || test "$NTZ" = "$1"; then
+               skipreason="$1 is not a recognized timezone on this system"
+               return 1
+       fi
+       :
+}
+
+
+
+###
+### Tests
+###
+
+# Why are these dates tested?
+#
+# February 29, 2003
+#   Is not a leap year - should be invalid.
+#
+# 2004-12-40
+#   Make sure get_date does not "roll" date forward to January 9th.  Some
+#   versions have been known to do this.
+#
+# Dec-5-1972
+#   This is my birthday.  :)
+#
+# 3/29/1974
+# 1996/05/12 13:57:45
+#   Because.
+#
+# 12-05-12
+#   This will be my 40th birthday.  Ouch.  :)
+#
+# 05/12/96
+#   Because.
+#
+# third tuesday in March, 2078
+#   Wanted this to work.
+#
+# 1969-12-32 2:00:00 UTC
+# 1970-01-01 2:00:00 UTC
+# 1969-12-32 2:00:00 +0400
+# 1970-01-01 2:00:00 +0400
+# 1969-12-32 2:00:00 -0400
+# 1970-01-01 2:00:00 -0400
+#   Playing near the UNIX Epoch boundry condition to make sure date rolling
+#   is also disabled there.
+#
+# 1996-12-12 1 month
+#   Test a relative date.
+
+
+
+# The following tests are currently being skipped for being unportable:
+#
+# Tue Jan 19 03:14:07 2038 +0000
+#   For machines with 31-bit time_t, any date past this date will be an
+#   invalid date. So, any test date with a value greater than this
+#   time is not portable.
+#
+# Feb. 29, 2096 4 years
+#   4 years from this date is _not_ a leap year, so Feb. 29th does not exist.
+#
+# Feb. 29, 2096 8 years
+#   8 years from this date is a leap year, so Feb. 29th does exist,
+#   but on many hosts with 32-bit time_t types time, this test will
+#   fail. So, this is not a portable test.
+#
+
+TZ=UTC0; export TZ
+
+cat >getdate-expected <<EOF
+Enter date, or blank line to exit.
+> Bad format - couldn't convert.
+> Bad format - couldn't convert.
+>      92361600 =      1972-12-05 00:00:00.000000000
+>     133747200 =      1974-03-29 00:00:00.000000000
+>     831909465 =      1996-05-12 13:57:45.000000000
+>    1336780800 =      2012-05-12 00:00:00.000000000
+>     831859200 =      1996-05-12 00:00:00.000000000
+> Bad format - couldn't convert.
+> Bad format - couldn't convert.
+>          7200 =      1970-01-01 02:00:00.000000000
+> Bad format - couldn't convert.
+>         -7200 =      1969-12-31 22:00:00.000000000
+> Bad format - couldn't convert.
+>         21600 =      1970-01-01 06:00:00.000000000
+>     853027200 =      1997-01-12 00:00:00.000000000
+> 
+EOF
+
+./getdate >getdate-got <<EOF
+February 29, 2003
+2004-12-40
+Dec-5-1972
+3/29/1974
+1996/05/12 13:57:45
+12-05-12
+05/12/96
+third tuesday in March, 2078
+1969-12-32 2:00:00 UTC
+1970-01-01 2:00:00 UTC
+1969-12-32 2:00:00 +0400
+1970-01-01 2:00:00 +0400
+1969-12-32 2:00:00 -0400
+1970-01-01 2:00:00 -0400
+1996-12-12 1 month
+EOF
+
+verify getdate-1
+
+
+
+# Why are these dates tested?
+#
+# Ian Abbot reported these odd boundry cases.  After daylight savings time went
+# into effect, non-daylight time zones would cause
+# "Bad format - couldn't convert." errors, even when the non-daylight zone
+# happened to be a universal one, like GMT.
+
+TZ=Europe/London; export TZ
+if valid_timezone $TZ; then
+       cat >getdate-expected <<EOF
+Enter date, or blank line to exit.
+>    1109635200 =      2005-03-01 00:00:00.000000000
+>    1111881600 =      2005-03-27 00:00:00.000000000
+>    1111968000 =      2005-03-28 01:00:00.000000000
+>    1111968000 =      2005-03-28 01:00:00.000000000
+>    1112054400 =      2005-03-29 01:00:00.000000000
+>    1112054400 =      2005-03-29 01:00:00.000000000
+>    1112140800 =      2005-03-30 01:00:00.000000000
+>    1112140800 =      2005-03-30 01:00:00.000000000
+>    1112227200 =      2005-03-31 01:00:00.000000000
+>    1112227200 =      2005-03-31 01:00:00.000000000
+>    1112313600 =      2005-04-01 01:00:00.000000000
+>    1112313600 =      2005-04-01 01:00:00.000000000
+>    1113091200 =      2005-04-10 01:00:00.000000000
+>    1113091200 =      2005-04-10 01:00:00.000000000
+>    1112310000 =      2005-04-01 00:00:00.000000000
+> 
+EOF
+
+       ./getdate >getdate-got <<EOF
+2005-3-1 GMT
+2005-3-27 GMT
+2005-3-28 GMT
+2005-3-28 UTC0
+2005-3-29 GMT
+2005-3-29 UTC0
+2005-3-30 GMT
+2005-3-30 UTC0
+2005-3-31 GMT
+2005-3-31 UTC0
+2005-4-1 GMT
+2005-4-1 UTC0
+2005-4-10 GMT
+2005-4-10 UTC0
+2005-4-1 BST
+EOF
+
+       verify getdate-2
+else
+       skip getdate-2 "$skipreason"
+fi
+
+
+
+# Many of the following cases were also submitted by Ian Abbott, but the same
+# errors are not exhibited.  The original problem had a similar root, but
+# managed to produce errors with GMT, which is considered a "Universal Zone".
+# This was fixed.
+#
+# The deeper problem has to do with "local zone" processing in getdate.y
+# that causes local daylight zones to be excluded when local standard time is
+# in effect and vice versa.  This used to cause trouble with GMT in Britian
+# when British Summer Time was in effect, but this was overridden for the
+# "Universal Timezones" (GMT, UTC, & UT), that might double as a local zone in
+# some locales.  We still see in these tests the local daylight/standard zone
+# exclusion in EST/EDT.  According to Paul Eggert in a message to
+# bug-gnulib@gnu.org on 2005-04-12, this is considered a bug but may not be
+# fixed soon due to its complexity.
+
+TZ=America/New_York; export TZ
+if valid_timezone $TZ; then
+       cat >getdate-expected <<EOF
+Enter date, or blank line to exit.
+>    1109653200 =      2005-03-01 00:00:00.000000000
+>    1109631600 =      2005-02-28 18:00:00.000000000
+>    1112331600 =      2005-04-01 00:00:00.000000000
+> Bad format - couldn't convert.
+>    1114902000 =      2005-04-30 19:00:00.000000000
+>    1114905600 =      2005-04-30 20:00:00.000000000
+>    1114920000 =      2005-05-01 00:00:00.000000000
+>    1114905600 =      2005-04-30 20:00:00.000000000
+> Bad format - couldn't convert.
+>    1117580400 =      2005-05-31 19:00:00.000000000
+>    1117584000 =      2005-05-31 20:00:00.000000000
+>    1117598400 =      2005-06-01 00:00:00.000000000
+>    1117584000 =      2005-05-31 20:00:00.000000000
+> 
+EOF
+
+       ./getdate >getdate-got <<EOF
+2005-3-1 EST
+2005-3-1 BST
+2005-4-1 EST
+2005-5-1 EST
+2005-5-1 BST
+2005-5-1 GMT
+2005-5-1 EDT
+2005-5-1 UTC0
+2005-6-1 EST
+2005-6-1 BST
+2005-6-1 GMT
+2005-6-1 EDT
+2005-6-1 UTC0
+EOF
+
+       verify getdate-3
+else
+       skip getdate-3 "$skipreason"
+fi
+
+
+
+rm getdate-expected getdate-got getdate.cmp
+exit 0
diff --git a/src/sanity.config.sh.in b/src/sanity.config.sh.in
new file mode 100644 (file)
index 0000000..7775124
--- /dev/null
@@ -0,0 +1 @@
+RSH_DFLT=@RSH_DFLT@
diff --git a/src/sanity.sh b/src/sanity.sh
new file mode 100644 (file)
index 0000000..9498f85
--- /dev/null
@@ -0,0 +1,35812 @@
+#! /bin/sh
+:
+# set DISABLE_ANY_RSH=1 to skip rsh and ssh calls
+#
+#      sanity.sh -- a growing testsuite for cvs.
+#
+# The copyright notice said: "Copyright (C) 1992, 1993 Cygnus Support"
+# I'm not adding new copyright notices for new years as our recent 
+# practice has been to include copying terms without copyright notices.
+#
+# 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, 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.
+#
+# Original Author: K. Richard Pixley
+
+# usage:
+usage ()
+{
+    echo "Usage: `basename $0` --help"
+    echo "Usage: `basename $0` [--eklr] [-c CONFIG-FILE] [-f FROM-TEST] \\"
+    echo "                 [-h HOSTNAME] [-s CVS-FOR-CVS-SERVER] CVS-TO-TEST \\"
+    echo "                 [TESTS-TO-RUN...]"
+}
+
+exit_usage ()
+{
+    usage 1>&2
+    exit 2
+}
+
+exit_help ()
+{
+    usage
+    echo
+    echo "-H|--help    display this text"
+    echo "-c CONFIG-FILE"
+    echo "--config=CONFIG_FILE"
+    echo "             use an alternate test suite config file (defaults to"
+    echo "             \`sanity.config.sh' in the same directory as"
+    echo "             CVS-TO-TEST is found in)"
+    echo "-e|--skipfail Treat tests that would otherwise be nonfatally skipped"
+    echo "              for reasons like missing tools as failures, exiting"
+    echo "              with an error message.  Also treat warnings as"
+    echo "             failures."
+    echo "-f FROM-TEST"
+    echo "--from-test=FROM-TEST"
+    echo "             run TESTS-TO-RUN, skipping all tests in the list before"
+    echo "             FROM-TEST"
+    echo "-h HOSTNAME"
+    echo "--hostname HOSTNAME"
+    echo "              Use :ext:HOSTNAME to run remote tests rather than"
+    echo "              :fork:.  Implies --remote and assumes that \$TESTDIR"
+    echo "              resolves to the same directory on both the client and"
+    echo "              the server."
+    echo "-k|--keep    try to keep directories created by individual tests"
+    echo "             around, exiting after the first test which supports"
+    echo "             --keep"
+    echo "-l|--link-root"
+    echo "             test CVS using a symlink to a real CVSROOT"
+    echo "-n|--noredirect"
+    echo "              test a secondary/primary CVS server (writeproxy)"
+    echo "              configuration with the Redirect response disabled"
+    echo "              (implies --proxy)."
+    echo "-p|--proxy   test a secondary/primary CVS server (writeproxy)"
+    echo "              configuration (implies --remote)."
+    echo "-r|--remote  test client/server, as opposed to local, CVS"
+    echo "-s CVS-FOR-CVS-SERVER"
+    echo "--server=CVS-FOR-CVS-SERVER"
+    echo "             use CVS-FOR-CVS-SERVER as the path to the CVS SERVER"
+    echo "             executable to be tested (defaults to CVS-TO-TEST and"
+    echo "             implies --remote)"
+    echo
+    echo "CVS-TO-TEST  the path to the CVS executable to be tested; used as"
+    echo "             the path to the CVS client when CVS-FOR-CVS-SERVER is"
+    echo "             specified"
+    echo "TESTS-TO-RUN the names of the tests to run (defaults to all tests)"
+    exit 2
+}
+
+checklongoptarg()
+{
+    if test "x$1" != xoptional && test -z "$OPTARG"; then
+       echo "option \`--$LONGOPT' requires an argument" >&2
+       exit_usage
+    fi
+}
+
+# See TODO list at end of file.
+
+# required to make this script work properly.
+unset CVSREAD
+
+# We want to invoke a predictable set of i18n behaviors, not whatever
+# the user running this script might have set.
+# In particular:
+#   'sort' and tabs and spaces (LC_COLLATE).
+#   Messages from getopt (LC_MESSAGES) (in the future, CVS itself might 
+#     also alter its messages based on LC_MESSAGES).
+LANG=C
+export LANG
+LC_ALL=C
+export LC_ALL
+
+# And a few tests want a predictable umask.
+umask 0002
+
+#
+# Initialize the test counts.
+#
+passed=0
+skipped=0
+warnings=0
+
+
+
+#
+# read our options
+#
+unset configfile
+unset fromtest
+unset remotehost
+unset rootoptions
+keep=false
+linkroot=false
+noredirect=false
+proxy=false
+remote=false
+servercvs=false
+skipfail=false
+while getopts Hc:ef:h:klnprs:-: option ; do
+    # convert the long opts to short opts
+    if test x$option = x-;  then
+       # remove any argument
+       if echo "$OPTARG" |grep = >/dev/null; then
+           LONGOPT=`echo "$OPTARG" |sed 's/=.*$//'`
+           OPTARG=`echo "$OPTARG" |sed -e 's/^.*=//'`
+       else
+           LONGOPT=$OPTARG
+           OPTARG=
+       fi
+       # Convert LONGOPT to lower case
+       LONGOPT=`echo "$LONGOPT" |sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
+       case "$LONGOPT" in
+           c|co|con|conf|confi|config)
+               option=c
+               checklongoptarg
+               ;;
+           f|fr|fro|from|from-|from-t|from-te|from-tes|from-test)
+               option=f
+               checklongoptarg
+               ;;
+           h)
+               echo "\`--h' is ambiguous.  Could mean \`--help' or \`--hostname'" >&2
+               exit_usage
+               ;;
+           he|hel|help)
+               option=H
+               OPTARG=
+               ;;
+           ho|hos|host|hostn|hostna|hostnam|hostname)
+               option=h
+               checklongoptarg
+               ;;
+           k|ke|kee|keep)
+               option=k
+               OPTARG=
+               ;;
+           l|li|lin|link|link-|link-r]|link-ro|link-roo|link-root)
+               option=l
+               OPTARG=
+               ;;
+           n|no|nor|nore|nored|noredi|noredir|noredire|noredirec|noredirect)
+               option=n
+               OPTARG=
+               ;;
+           p|pr|pro|prox|proxy)
+               option=p
+               OPTARG=
+               ;;
+           r|re|rem|remo|remot|remote)
+               option=r
+               OPTARG=
+               ;;
+           s)
+               echo "\`--s' is ambiguous.  Could mean \`--server' or \`--skipfail'" >&2
+               exit_usage
+               ;;
+           se|ser|serv|serve|server)
+               option=s
+               checklongoptarg
+               ;;
+           sk|ski|skip|skipf|skipfa|skipfai|skipfail)
+               option=e
+               OPTARG=
+               ;;
+           *)
+               option=\?
+               OPTARG=
+       esac
+    fi
+    case "$option" in
+       c)
+           configfile="$OPTARG"
+           ;;
+       e)
+           skipfail=:
+           ;;
+       f)
+           fromtest="$OPTARG"
+           ;;
+       h)
+           # Set a remotehost to run the remote tests on via :ext:
+           # Implies `-r' and assumes that $TESTDIR resolves to the same
+           # directory on the client and the server.
+           remotehost="$OPTARG"
+           remote=:
+           ;;
+       H)
+           exit_help
+           ;;
+       k)
+           # The -k (keep) option will eventually cause all the tests to
+           # leave around the contents of the /tmp directory; right now only
+           # some implement it.  Not originally intended to be useful with
+           # more than one test, but this should work if each test uses a
+           # uniquely named dir (use the name of the test).
+           keep=:
+           ;;
+       l)
+           linkroot=:
+           ;;
+        n)
+           proxy=:
+           noredirect=:
+           remote=:
+           ;;
+        p)
+           proxy=:
+           remote=:
+           ;;
+       r)
+           remote=:
+           ;;
+        s)
+           servercvs="$OPTARG"
+           remote=:
+           ;;
+       \?)
+           exit_usage
+           ;;
+    esac
+done
+
+# boot the arguments we used above
+while test $OPTIND -gt 1 ; do
+    shift
+    OPTIND=`expr $OPTIND - 1`
+done
+
+# Use full path for CVS executable, so that CVS_SERVER gets set properly
+# for remote.
+case $1 in
+"")
+  exit_usage
+  ;;
+/*)
+  testcvs=$1
+  ;;
+*)
+  testcvs=`pwd`/$1
+  ;;
+esac
+shift
+
+# Verify that $testcvs looks like CVS.
+# we can't use test -x since BSD 4.3 doesn't support it.
+if test ! -f $testcvs || test ! -r $testcvs; then
+  echo "No such file or file not readable: $testcvs" >&2
+  exit 1
+fi
+if $testcvs --version </dev/null 2>/dev/null |
+     grep '^Concurrent Versions System' >/dev/null 2>&1; then :; else
+  echo "Not a CVS executable: $testcvs" >&2
+  exit 1
+fi
+
+# If $remotehost is set, warn if $TESTDIR isn't since we are pretty sure
+# that its default value of `/tmp/cvs-sanity' will not resolve to the same
+# directory on two different machines.
+if test -n "$remotehost" && test -z "$TESTDIR"; then
+    echo "WARNING: CVS server hostname is set and \$TESTDIR is not.  If" >&2
+    echo "$remotehost is not the local machine, then it is unlikely that" >&2
+    echo "the default value assigned to \$TESTDIR will resolve to the same" >&2
+    echo "directory on both this client and the CVS server." >&2
+fi
+
+# Read our config file if we can find it.
+#
+# The config file should always be located in the same directory as the CVS
+# executable, unless we are testing an executable outside of the build
+# directory.  In this case, we echo a warning and attempt to assume the most
+# portable configuration.
+if test -z "$configfile"; then
+       configfile=`dirname $testcvs`/sanity.config.sh
+fi
+if test -r "$configfile"; then
+       . "$configfile"
+else
+       echo "WARNING: Failed to locate test suite config file" >&2
+       echo "         \`$configfile'." >&2
+fi
+
+
+
+# Set a default value for $CVS_RSH. The sanity.config.sh file will
+# have the configured value in the RSH_DFLT variable.
+#
+: ${CVS_RSH=${RSH_DFLT:-ssh}}; export CVS_RSH
+
+if test -n "$remotehost"; then
+    # Verify that $CVS_RSH $remotehost works.
+    result=`$CVS_RSH $remotehost 'echo test'`
+    if test $? != 0 || test "x$result" != "xtest"; then
+       echo "\`$CVS_RSH $remotehost' failed." >&2
+       exit 1
+    fi
+fi
+
+case "$servercvs" in
+"")
+  exit_usage
+  ;;
+false)
+  ;;
+/*)
+  ;;
+*)
+  servercvs=`pwd`/$servercvs
+  ;;
+esac
+
+if test false != $servercvs; then
+  # Allow command line to override $CVS_SERVER
+  CVS_SERVER=$servercvs
+else
+  # default $CVS_SERVER to ${testcvs}
+  : ${CVS_SERVER=$testcvs}
+  # With the previous command, effectively defaults $servercvs to $CVS_SERVER,
+  # then $testcvs
+  servercvs=$CVS_SERVER
+fi
+export CVS_SERVER
+servercvs_orig=$servercvs
+
+# Fail in client/server mode if our ${servercvs} does not contain server
+# support.
+if $remote; then
+  if test -n "$remotehost"; then
+    if $CVS_RSH $remotehost "test ! -f ${servercvs} || test ! -r ${servercvs}"
+    then
+      echo "No such file or file not readable: $remotehost:${testcvs}" >&2
+      exit 1
+    fi
+    if $CVS_RSH $remotehost "${servercvs} --version </dev/null 2>/dev/null |
+         grep '^Concurrent Versions System' >/dev/null 2>&1"; then :; else
+      echo "Not a CVS executable: $remotehost:${servercvs}" >&2
+      exit 1
+    fi
+    if $CVS_RSH $remotehost "${servercvs} --version </dev/null |
+         grep '^Concurrent.*(.*server)$' >/dev/null 2>&1"; then :; else
+      echo "CVS executable \`$remotehost:${servercvs}' does not contain server support." >&2
+      exit 1
+    fi
+  else
+    if test ! -f ${servercvs} || test ! -r ${servercvs}; then
+      echo "No such file or file not readable: ${testcvs}" >&2
+      exit 1
+    fi
+    if ${servercvs} --version </dev/null 2>/dev/null |
+         grep '^Concurrent Versions System' >/dev/null 2>&1; then :; else
+      echo "Not a CVS executable: ${servercvs}" >&2
+      exit 1
+    fi
+    if ${servercvs} --version </dev/null |
+         grep '^Concurrent.*(.*server)$' >/dev/null 2>&1; then :; else
+      echo "CVS executable \`${servercvs}' does not contain server support." >&2
+      exit 1
+    fi
+  fi
+fi
+
+# Fail in client/server mode if our ${testcvs} does not contain client
+# support.
+if $remote; then
+  if ${testcvs} --version </dev/null |
+       grep '^Concurrent.*(client.*)$' >/dev/null 2>&1; then :; else
+    echo "CVS executable \`${testcvs}' does not contain client support." >&2
+    exit 1
+  fi
+fi
+
+# For the "fork" tests.
+if ${testcvs} --version </dev/null |
+     grep '^Concurrent.*(.*server)$' >/dev/null 2>&1
+then
+  testcvs_server_support=:
+else
+  testcvs_server_support=false
+fi
+
+
+
+dokeep() 
+{ 
+    if ${keep}; then
+      echo "Keeping ${TESTDIR} for test case \`${what}' and exiting due to --keep"
+      exit 0
+    fi
+}
+
+
+
+###
+### GUTS
+###
+
+# "debugger"
+#set -x
+
+echo 'This test should produce no other output than this message, and a final "OK".'
+echo '(Note that the test can take an hour or more to run and periodically stops'
+echo 'for as long as one minute.  Do not assume there is a problem just because'
+echo 'nothing seems to happen for a long time.  If you cannot live without'
+echo "running status, try the command: \`tail -f check.log' from another window.)"
+
+# Regexp to match what the CVS client will call itself in output that it prints.
+# FIXME: we don't properly quote this--if the name contains . we'll
+# just spuriously match a few things; if the name contains other regexp
+# special characters we are probably in big trouble.
+CPROG=`basename ${testcvs} |sed 's/\.exe$//'`
+# And the regexp for the CVS server when we have one.  In local mode, this
+# defaults to $CPROG since $servercvs already did.
+# FIXCVS: There are a few places in error messages where CVS suggests a command
+# and outputs $SPROG as the suggested executable.  This could hopefully use
+# MT (tagged text - see doc/cvs-client.texi) to request that the client print
+# its own name.
+SPROG=`basename ${servercvs} |sed 's/\.exe$//'`
+
+
+# Match the hostname
+hostname="[-_.a-zA-Z0-9]*"
+
+# Regexp to match a commitid
+commitid="[a-zA-Z0-9]*"
+
+# Regexp to match the name of a temporary file (from cvs_temp_name).
+# This appears in certain diff output.
+tempfile="cvs[-a-zA-Z0-9.%_]*"
+# $tempname set after $TMPDIR, below.
+
+# Regexp to match a date in RFC822 format (as amended by RFC1123).
+RFCDATE="[a-zA-Z0-9 ][a-zA-Z0-9 ]* [0-9:][0-9:]* -0000"
+RFCDATE_EPOCH="1 Jan 1970 00:00:00 -0000"
+
+# Special times used in touch -t commands and the regular expresions
+# to match them. Now that the tests set TZ=UTC0, it
+# should be easier to be more exact in their regexp.
+TOUCH1971="197107040343"
+# This date regexp was 1971/07/0[3-5] [0-9][0-9]:43:[0-9][0-9]
+ISO8601DATE1971="1971-07-04 03:43:[0-9][0-9] [+-]0000"
+
+TOUCH2034="203412251801"
+# This date regexp was 2034/12/2[4-6] [0-9][0-9]:01:[0-9][0-9]
+ISO8601DATE2034="2034-12-25 18:01:[0-9][0-9] [+-]0000"
+
+# Used in admin tests for exporting RCS files.
+# The RAWRCSDATE..... format is for internal ,v files and
+# the ISO8601DATE..... format is to allow for a regular expression in
+# 'cvs log' output patterns. The tests that use this set of specific
+# ${ISO8601DATE.....} variables also force TZ=UTC0 for the test.
+RAWRCSDATE2000A="2000.11.24.15.58.37"
+RAWRCSDATE1996A="96.11.24.15.57.41"
+RAWRCSDATE1996B="96.11.24.15.56.05"
+ISO8601DATE2000A="2000-11-24 15:58:37 [+-]0000"
+ISO8601DATE1996A="1996-11-24 15:57:41 [+-]0000"
+ISO8601DATE1996B="1996-11-24 15:56:05 [+-]0000"
+
+# Regexp to match the date in cvs log command output
+# This format has been enhanced in the future to accept either
+# old-style cvs log output dates or new-style ISO8601 timezone
+# information similar to the ISODATE format. The RCSKEYDATE is
+# similar, but uses '/' instead of '-' to sepearate year/month/day
+# and does not include the optional timezone offset.
+ISO8601DATE="[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-6][0-9]:[0-6][0-9] [-+][0-1][0-9][0-6][0-9]"
+
+# Regexp to match the dates found in rcs keyword strings
+RCSKEYDATE="[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]"
+
+# Regexp to match the date in the delta section of rcs format files.
+# Dates in very old RCS files may not have included the century.
+RCSDELTADATE="[0-9][0-9]*\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]"
+
+# Regexp to match a date in standard Unix format as used by rdiff
+# FIXCVS: There's no reason for rdiff to use a different date format
+# than diff does
+DATE="[a-zA-Z]* [a-zA-Z]* [ 1-3][0-9] [0-9:]* [0-9]*"
+# ISO 8601 format "yyyy-mm-dd hh:mm -0000"
+ISODATE="[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9] [+-][0-9][0-9][0-9][0-9]"
+# %p format is not well defined (nil) and hex digits are common. Using
+# ..* is a bad idea as the tests take a very long time to run due to
+# the complexity of the expressions.  If you run into any other characters
+# that are used in a %p format, add them here.
+PFMT="[0-9a-zA-Z()][0-9a-zA-Z()]*"
+
+# Which directories should Which and find_tool search for executables?
+SEARCHPATH=$PATH:/usr/local/bin:/usr/contrib/bin:/usr/contrib:/usr/gnu/bin:/local/bin:/local/gnu/bin:/gnu/bin:/sw/bin:/usr/pkg/bin
+
+# Do not assume that `type -p cmd` is portable
+# Usage: Which [-a] [-x|-f|-r] prog [$SEARCHPATH:/with/directories:/to/search]
+Which() {
+  # Optional first argument for file type, defaults to -x.
+  # Second argument is the file or directory to be found.
+  # Third argument is the PATH to search.
+  # By default, print only the first file that matches,
+  # -a will cause all matches to be printed.
+  notevery=:
+  if [ "x$1" = "x-a" ]; then notevery=false; shift; fi
+  case "$1" in
+    -*) t=$1; shift ;;
+    *) t=-x ;;
+  esac
+  case "$1" in
+    # FIXME: Someday this may need to be fixed
+    # to deal better with C:\some\path\to\ssh values...
+    /*) test $t $1 && echo $1 ;;
+    *) for d in `IFS=:; echo ${2-$SEARCHPATH}`
+       do
+         test $t $d/$1 && { echo $d/$1; if $notevery; then break; fi; }
+       done
+       ;;
+  esac
+}
+
+
+# On cygwin32, we may not have /bin/sh.
+if test -r /bin/sh; then
+  TESTSHELL="/bin/sh"
+else
+  TESTSHELL=`Which -f sh`
+  if test ! -r "$TESTSHELL"; then
+    TESTSHELL="/bin/sh"
+  fi
+fi
+
+# FIXME: try things (what things? checkins?) without -m.
+#
+# Some of these tests are written to expect -Q.  But testing with
+# -Q is kind of bogus, it is not the way users actually use CVS (usually).
+# So new tests probably should invoke ${testcvs} directly, rather than ${CVS}.
+# and then they've obviously got to do something with the output....
+#
+CVS="${testcvs} -Q"
+
+LOGFILE=`pwd`/check.log
+
+# Save the previous log in case the person running the tests decides
+# they want to look at it.  The extension ".plog" is chosen for consistency
+# with dejagnu.
+test -f check.plog && mv check.plog check.plog~
+test -f check.log && mv check.log check.plog
+
+# Create the log file so check.log can be tailed almost immediately after
+# this script is started.  Otherwise it can take up to a minute or two before
+# the log file gets created when $remotehost is specified on some systems,
+# which makes for a lot of failed `tail -f' attempts.
+touch check.log
+
+# Workaround any X11Forwarding by ssh. Otherwise this text:
+#   Warning: No xauth data; using fake authentication data for X11 forwarding.
+# has been known to end up in the test results below
+# causing the test to fail.
+[ -n "$DISPLAY" ] && unset DISPLAY
+  
+# The default value of /tmp/cvs-sanity for TESTDIR is dubious,
+# because it loses if two people/scripts try to run the tests
+# at the same time.  Some possible solutions:
+# 1.  Use /tmp/cvs-test$$.  One disadvantage is that the old
+#     cvs-test* directories would pile up, because they wouldn't
+#     necessarily get removed.
+# 2.  Have everyone/everything running the testsuite set
+#     TESTDIR to some appropriate directory.
+# 3.  Have the default value of TESTDIR be some variation of
+#     `pwd`/cvs-sanity.  The biggest problem here is that we have
+#     been fairly careful to test that CVS prints in messages the
+#     actual pathnames that we pass to it, rather than a different
+#     pathname for the same directory, as may come out of `pwd`.
+#     So this would be lost if everything was `pwd`-based.  I suppose
+#     if we wanted to get baroque we could start making symlinks
+#     to ensure the two are different.
+if test -n "$remotehost"; then
+        # We need to set $tmp on the server since $TMPDIR is compared against
+       # messages generated by the server.
+       tmp=`$CVS_RSH $remotehost 'cd /tmp; /bin/pwd || pwd' 2>/dev/null`
+       if test $? != 0; then
+           echo "$CVS_RSH $remotehost failed." >&2
+           exit 1
+       fi
+else
+       tmp=`(cd /tmp; /bin/pwd || pwd) 2>/dev/null`
+fi
+
+# Now:
+#      1) Set TESTDIR if it's not set already
+#      2) Remove any old test remnants
+#      3) Create $TESTDIR
+#      4) Normalize TESTDIR with `cd && (/bin/pwd || pwd)`
+#         (This will match CVS output later)
+: ${TESTDIR=$tmp/cvs-sanity}
+# clean any old remnants (we need the chmod because some tests make
+# directories read-only)
+if test -d $TESTDIR; then
+    chmod -R a+wx $TESTDIR
+    rm -rf $TESTDIR
+fi
+# These exits are important.  The first time I tried this, if the `mkdir && cd`
+# failed then the build directory would get blown away.  Some people probably
+# wouldn't appreciate that.
+mkdir $TESTDIR || exit 1
+cd $TESTDIR || exit 1
+# Ensure $TESTDIR is absolute
+if echo "$TESTDIR" |grep '^[^/]'; then
+    # Don't resolve this unless we have to.  This keeps symlinks intact.  This
+    # is important at least when testing using -h $remotehost, because the same
+    # value for $TESTDIR must resolve to the same directory on the client and
+    # the server and we likely used Samba, and possibly symlinks, to do this.
+    TESTDIR=`(/bin/pwd || pwd) 2>/dev/null`
+fi
+
+if test -z "$TESTDIR" || echo "$TESTDIR" |grep '^[^/]'; then
+    echo "Unable to resolve TESTDIR to an absolute directory." >&2
+    exit 1
+fi
+cd $TESTDIR
+
+
+
+: ${TIMING=false}
+if $remote; then
+    # Now override our CVS_RSH in order to forward variables which affect the
+    # test suite through.  This always needs to be done when $remotehost is
+    # set, needs to be done in $proxy mode for the crerepos tests, and needs to
+    # be done in $remote mode for the writeproxy-ssh tests.
+    if $TIMING; then
+       time="/usr/bin/time -ao'$TESTDIR/time.out'"
+    else
+       time=
+    fi
+    cat >$TESTDIR/ssh-wrapper-env <<EOF
+#! $TESTSHELL
+while [ \$# -gt 0 ]
+do
+  case "\$1" in
+    *=*)
+      eval "\$1"
+      var=\`echo "\$1" | sed 's/^\\(.*\\)=.*\$/\\1/'\`
+      export \$var
+      ;;
+    *) break;;
+  esac
+  shift
+done
+exec \${1+"\$@"}
+EOF
+    chmod a+x $TESTDIR/ssh-wrapper-env
+    cat >$TESTDIR/ssh-wrapper <<EOF
+#! $TESTSHELL
+hostname=\$1
+shift
+exec \
+$CVS_RSH \
+        \$hostname \
+        $TESTDIR/ssh-wrapper-env \
+        "CVS_SERVER='\$CVS_SERVER'" \
+        "CVS_SERVER_SLEEP='\$CVS_SERVER_SLEEP'" \
+        "CVS_PARENT_SERVER_SLEEP='\$CVS_PARENT_SERVER_SLEEP'" \
+        "CVS_SERVER_LOG='\$CVS_SERVER_LOG'" \
+        "CVS_SECONDARY_LOG='\$CVS_SECONDARY_LOG'" \
+        "TMPDIR='\$TMPDIR'" \
+        "CVS_RSH='$TESTDIR/ssh-wrapper'" \
+        "CVSUMASK='\$CVSUMASK'" \
+        "CVS_PID='\$CVS_PID'" \
+        $time \
+        \${1+"\$@"}
+EOF
+    chmod a+x $TESTDIR/ssh-wrapper
+    CVS_RSH=$TESTDIR/ssh-wrapper
+fi # $remotehost
+
+
+
+# Now set $TMPDIR if the user hasn't overridden it.
+#
+# We use a $TMPDIR under $TESTDIR by default so that two tests may be run at
+# the same time without bumping heads without requiring the user to specify
+# more than $TESTDIR.  See the test for leftover cvs-serv* directories near the
+# end of this script at the end of "The big loop".
+: ${TMPDIR=$TESTDIR/tmp}
+export TMPDIR
+if test -d $TMPDIR; then :; else
+    mkdir $TMPDIR
+fi
+
+
+# Regexp to match the the full path to a temporary file (from cvs_temp_name).
+# This appears in certain diff output.
+tempname=$TMPDIR/$tempfile
+
+# Make sure various tools work the way we expect, or try to find
+# versions that do.
+: ${AWK=awk}
+: ${EXPR=expr}
+: ${ID=id}
+: ${TR=tr}
+
+# Keep track of tools that are found, but do NOT work as we hope
+# in order to avoid them in future
+badtools=
+set_bad_tool ()
+{
+   badtools=$badtools:$1
+}
+is_bad_tool ()
+{
+   case ":$badtools:" in *:$1:*) return 0 ;; *) return 1 ; esac
+}
+
+version_test ()
+{
+  vercmd=$1
+  verbad=:
+  if RES=`$vercmd --version </dev/null 2>&1`; then
+    if test "X$RES" != "X--version" && test "X$RES" != "X" ; then
+      echo "$RES"
+      verbad=false
+    fi
+  fi
+  if $verbad; then
+    echo "The command \`$vercmd' does not support the --version option."
+  fi
+  # It does not really matter that --version is not supported
+  return 0
+}
+
+# Try to find a tool that satisfies all of the tests.
+# Usage: list:of:colon:separated:alternatives test1 test2 test3 test4...
+# Example: find_tool awk:gawk:nawk awk_tooltest1 awk_tooltest2
+find_tool ()
+{
+  default_TOOL=$1
+  echo find_tool: ${1+"$@"} >>$LOGFILE
+  cmds="`IFS=:; echo $1`"; shift; tooltests="${1+$@}"
+  if test -z "$tooltests"; then tooltests=version_test; fi
+  clist=; for cmd in $cmds; do clist="$clist `Which -a $cmd`"; done
+  # Make sure the default tool is just the first real command name
+  for default_TOOL in $clist `IFS=:; echo $default_TOOL`; do break; done
+  TOOL=""
+  for trytool in $clist ; do
+    pass=:
+    for tooltest in $tooltests; do
+      result=`eval $tooltest $trytool`
+      rc=$?
+      echo "Running $tooltest $trytool" >>$LOGFILE
+      if test -n "$result"; then
+       echo "$result" >>$LOGFILE
+      fi
+      if test "$rc" = "0"; then
+        echo "PASS: $tooltest $trytool" >>$LOGFILE
+      elif test "$rc" = "77"; then
+        echo "MARGINAL: $tooltest $trytool; rc=$rc" >>$LOGFILE
+        TOOL=$trytool
+       pass=false
+      else
+        set_bad_tool $trytool
+        echo "FAIL: $tooltest $trytool; rc=$rc" >>$LOGFILE
+       pass=false
+      fi
+    done
+    if $pass; then
+      echo $trytool
+      return 0
+    fi
+  done
+  if test -n "$TOOL"; then
+    echo "Notice: The default version of \`$default_TOOL' is defective." >>$LOGFILE
+    echo "using \`$TOOL' and hoping for the best." >>$LOGFILE
+    echo "Notice: The default version of \`$default_TOOL' is defective." >&2
+    echo "using \`$TOOL' and hoping for the best." >&2
+    echo $TOOL
+  else
+    echo $default_TOOL
+  fi
+}  
+
+id_tool_test ()
+{
+  id=$1
+  if $id -u >/dev/null 2>&1 && $id -un >/dev/null 2>&1; then
+    return 0
+  else
+    echo "Running these tests requires an \`id' program that understands the"
+    echo "-u and -n flags.  Make sure that such an id (GNU, or many but not"
+    echo "all vendor-supplied versions) is in your path."
+    return 1
+  fi
+}
+
+ID=`find_tool id version_test id_tool_test`
+echo "Using ID=$ID" >>$LOGFILE
+
+# You can't run CVS as root; print a nice error message here instead
+# of somewhere later, after making a mess.
+for pass in false :; do
+  case "`$ID -u 2>/dev/null`" in
+    "0")
+      echo "Test suite does not work correctly when run as root" >&2
+      exit 1
+      ;;
+
+    *)
+      break
+      ;;
+  esac
+done
+
+# Cause NextStep 3.3 users to lose in a more graceful fashion.
+expr_tooltest1 ()
+{
+expr=$1
+if $expr 'abc
+def' : 'abc
+def' >/dev/null; then
+  # good, it works
+  return 0
+else
+  echo 'Running these tests requires an "expr" program that can handle'
+  echo 'multi-line patterns.  Make sure that such an expr (GNU, or many but'
+  echo 'not all vendor-supplied versions) is in your path.'
+  return 1
+fi
+}
+
+# Warn SunOS, SysVr3.2, etc., users that they may be partially losing
+# if we can't find a GNU expr to ease their troubles...
+expr_tooltest2 ()
+{
+expr=$1
+if $expr 'a
+b' : 'a
+c' >/dev/null; then
+  echo 'Warning: you are using a version of expr that does not correctly'
+  echo 'match multi-line patterns.  Some tests may spuriously pass or fail.'
+  echo 'You may wish to make sure GNU expr is in your path.'
+  return 1
+else
+  return 0
+fi
+}
+
+expr_create_bar ()
+{
+echo 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' >${TESTDIR}/foo
+cat ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo >${TESTDIR}/bar
+cat ${TESTDIR}/bar ${TESTDIR}/bar ${TESTDIR}/bar ${TESTDIR}/bar >${TESTDIR}/foo
+cat ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo >${TESTDIR}/bar
+rm -f ${TESTDIR}/foo
+}
+
+expr_tooltest3 ()
+{
+expr=$1
+# More SunOS lossage...
+test ! -f ${TESTDIR}/bar && expr_create_bar
+if $expr "`cat ${TESTDIR}/bar`" : "`cat ${TESTDIR}/bar`" >/dev/null; then
+  : good, it works
+else
+  echo 'Warning: you are using a version of expr that does not correctly'
+  echo 'match large patterns.  Some tests may spuriously pass or fail.'
+  echo 'You may wish to make sure GNU expr is in your path.'
+  return 1
+fi
+if $expr "`cat ${TESTDIR}/bar`x" : "`cat ${TESTDIR}/bar`y" >/dev/null; then
+  echo 'Warning: you are using a version of expr that does not correctly'
+  echo 'match large patterns.  Some tests may spuriously pass or fail.'
+  echo 'You may wish to make sure GNU expr is in your path.'
+  return 1
+fi
+# good, it works
+return 0
+}
+
+# That we should have to do this is total bogosity, but GNU expr
+# version 1.9.4-1.12 uses the emacs definition of "$" instead of the unix
+# (e.g. SunOS 4.1.3 expr) one.  Rumor has it this will be fixed in the
+# next release of GNU expr after 1.12 (but we still have to cater to the old
+# ones for some time because they are in many linux distributions).
+ENDANCHOR="$"
+expr_set_ENDANCHOR ()
+{
+expr=$1
+ENDANCHOR="$"
+if $expr 'abc
+def' : 'abc$' >/dev/null; then
+  ENDANCHOR='\'\'
+   echo "Notice: An ENDANCHOR of dollar does not work."
+   echo "Using a workaround for GNU expr versions 1.9.4 thru 1.12"
+fi
+return 0
+}
+
+# Work around another GNU expr (version 1.10-1.12) bug/incompatibility.
+# "." doesn't appear to match a newline (it does with SunOS 4.1.3 expr).
+# Note that the workaround is not a complete equivalent of .* because
+# the first parenthesized expression in the regexp must match something
+# in order for expr to return a successful exit status.
+# Rumor has it this will be fixed in the
+# next release of GNU expr after 1.12 (but we still have to cater to the old
+# ones for some time because they are in many linux distributions).
+DOTSTAR='.*'
+expr_set_DOTSTAR ()
+{
+expr=$1
+DOTSTAR='.*'
+if $expr 'abc
+def' : "a${DOTSTAR}f" >/dev/null; then
+  : good, it works
+else
+  DOTSTAR='\(.\|
+\)*'
+  echo "Notice: DOTSTAR changed from sane \`.*' value to \`$DOTSTAR\`"
+  echo "to workaround GNU expr version 1.10 thru 1.12 bug where \`.'"
+  echo "does not match a newline."
+fi
+return 0
+}
+
+# Now that we have DOTSTAR, make sure it works with big matches
+expr_tooltest_DOTSTAR ()
+{
+expr=$1
+test ! -f ${TESTDIR}/bar && expr_create_bar
+if $expr "`cat ${TESTDIR}/bar`" : "${DOTSTAR}xyzABC${DOTSTAR}$" >/dev/null; then
+  # good, it works
+  return 0
+else
+  echo 'Warning: you are using a version of expr that does not correctly'
+  echo 'match large patterns.  Some tests may spuriously pass or fail.'
+  echo 'You may wish to make sure GNU expr is in your path.'
+  return 77
+fi
+}
+
+EXPR=`find_tool ${EXPR}:gexpr \
+  version_test expr_tooltest1 expr_tooltest2 expr_tooltest3 \
+expr_set_ENDANCHOR expr_set_DOTSTAR expr_tooltest_DOTSTAR`
+
+# Set the ENDANCHOR and DOTSTAR for the chosen expr version.
+expr_set_ENDANCHOR ${EXPR} >/dev/null
+expr_tooltest_DOTSTAR ${EXPR} >/dev/null
+
+echo "Using EXPR=$EXPR" >>$LOGFILE
+echo "Using ENDANCHOR=$ENDANCHOR" >>$LOGFILE
+echo "Using DOTSTAR=$DOTSTAR" >>$LOGFILE
+
+# Cleanup
+rm -f ${TESTDIR}/bar
+
+# Work around yet another GNU expr (version 1.10) bug/incompatibility.
+# "+" is a special character, yet for unix expr (e.g. SunOS 4.1.3)
+# it is not.  I doubt that POSIX allows us to use \+ and assume it means
+# (non-special) +, so here is another workaround
+# Rumor has it this will be fixed in the
+# next release of GNU expr after 1.12 (but we still have to cater to the old
+# ones for some time because they are in many linux distributions).
+PLUS='+'
+if $EXPR 'a +b' : "a ${PLUS}b" >/dev/null; then
+  : good, it works
+else
+  PLUS='\+'
+fi
+
+# Likewise, for ?
+QUESTION='?'
+if $EXPR 'a?b' : "a${QUESTION}b" >/dev/null; then
+  : good, it works
+else
+  QUESTION='\?'
+fi
+
+# Now test the username to make sure it contains only valid characters
+username=`$ID -un`
+if $EXPR "${username}" : "${username}" >/dev/null; then
+  : good, it works
+else
+  echo "Test suite does not work correctly when run by a username" >&2
+  echo "containing regular expression meta-characters." >&2
+  exit 1
+fi
+
+# Only 8 characters of $username appear in some output.
+if test `echo $username |wc -c` -gt 8; then
+  username8=`echo $username |sed 's/^\(........\).*/\1/'`
+else
+  username8=$username
+fi
+
+# Rarely, we need to match any username, not just the name of the user
+# running this test.  This variable usually shouldn't be used.  $username
+# contains the name of the user actually running this test.
+#
+# I believe this only ever actually gets compared to usernames created by this
+# test.  It used to be compared to the username of the user running this test,
+# but this hasn't been true for a long time.  Regardless, I tried to get the
+# allowed character set right, based on a list in a private email from Mark
+# Baushke, basically the allowed names from Linux systems (plus `.', which is
+# only allowed on Gentoo Linux as of 2005-09-13).
+anyusername="[_a-zA-Z0-9][-_.$a-zA-Z0-9]*"
+
+# now make sure that tr works on NULs
+tr_tooltest1 ()
+{
+tr=$1
+if $EXPR `echo "123" | $tr '2' '\0'` : "123" >/dev/null 2>&1; then
+  echo 'Warning: you are using a version of tr which does not correctly'
+  echo 'handle NUL bytes.  Some tests may spuriously pass or fail.'
+  echo 'You may wish to make sure GNU tr is in your path.'
+  return 77
+fi
+# good, it works
+return 0
+}
+
+TR=`find_tool ${TR}:gtr version_test tr_tooltest1`
+echo "Using TR=$TR" >>$LOGFILE
+
+# MacOS X (10.2.8) has a /bin/ls that does not work correctly in that
+# it will return true even if the wildcard argument does not match any
+# files.
+ls_tooltest ()
+{
+ls=$1
+# Force cleanup
+if test -d $TESTDIR/ls-test; then
+    chmod -R a+wx $TESTDIR/ls-test
+    rm -rf $TESTDIR/ls-test
+fi
+if $ls $TESTDIR/ls-test >/dev/null 2>&1; then
+  echo "Notice: \`$ls' is defective."
+  echo 'This is a version of ls which does not correctly'
+  echo 'return false for files that do not exist. Some tests may'
+  echo 'spuriously pass or fail.'
+  echo 'You may wish to put a an ls from GNU coreutils into your path.'
+  return 77
+else
+  return 0
+fi
+}
+LS=`find_tool ls:gls version_test ls_tooltest`
+echo "Using LS=$LS" >>$LOGFILE
+
+# Awk testing
+
+awk_tooltest1 ()
+{
+awk=$1
+$awk 'BEGIN {printf("one\ntwo\nthree\nfour\nfive\nsix")}' </dev/null >abc
+if $EXPR "`cat abc`" : \
+'one
+two
+three
+four
+five
+six'; then
+  rm abc
+  return 0
+else
+  rm abc
+  echo "Notice: awk BEGIN clause or printf is not be working properly."
+  return 1
+fi
+}
+
+# Format item %c check
+awk_tooltest2 ()
+{
+awk=$1
+$awk 'BEGIN { printf "%c%c%c", 2, 3, 4 }' </dev/null \
+  | ${TR} '\002\003\004' '123' >abc
+if $EXPR "`cat abc`" : "123" ; then
+  : good, found it
+else
+  echo "Notice: awk format %c string may not be working properly."
+  rm abc
+  return 77
+fi
+rm abc
+return 0
+}
+
+AWK=`find_tool gawk:nawk:awk version_test awk_tooltest1 awk_tooltest2`
+echo "Using AWK=$AWK" >>$LOGFILE
+
+
+###
+### Functions used by tests.
+###
+
+# Execute a command on the repository, syncing when done if necessary.
+#
+# Syntax is as `eval'.
+modify_repo ()
+{
+    eval "$*"
+    if $proxy; then
+       # And now resync the secondary.
+       $TESTDIR/sync-secondary "repo modification" modify_repo ALL "$@"
+    fi
+}
+
+# Restore changes to CVSROOT admin files.
+restore_adm ()
+{
+    modify_repo rm -rf $CVSROOT_DIRNAME/CVSROOT
+    modify_repo cp -Rp $TESTDIR/CVSROOT.save $CVSROOT_DIRNAME/CVSROOT
+}
+
+# Test that $RSYNC supports the options we need or try to find a
+# replacement. If $RSYNC works or we replace it, and return 0.
+# Otherwise, set $skipreason and return 77.
+require_rsync ()
+{
+  rsyncworks=false
+  # rsync is NOT a GNU tool, so do NOT use find_tool for name munging.
+  for rsync in ${RSYNC} `Which -a rsync`;
+  do
+
+    if is_bad_tool `Which $rsync` ; then continue ; fi
+    # Make some data to test rsync on.
+    mkdir $TESTDIR/rsync-test
+    mkdir $TESTDIR/rsync-test/Attic && touch $TESTDIR/rsync-test/Attic/6
+    mkdir $TESTDIR/rsync-test/otherdir && touch $TESTDIR/rsync-test/otherdir/7
+    for file in 1 2 3 4 5; do
+      touch $TESTDIR/rsync-test/$file
+    done
+  
+    if test -f "$rsync" && test -r "$rsync" \
+      && $rsync -rglop --delete $TESTDIR/rsync-test/ $TESTDIR/rsync-test-copy \
+             >/dev/null 2>&1 \
+      && $rsync -rglop --delete --include Attic --exclude '*/' \
+             $TESTDIR/rsync-test/ $TESTDIR/rsync-test-copy2 \
+             >/dev/null 2>&1 \
+      && test -f $TESTDIR/rsync-test/5 \
+      && mv $TESTDIR/rsync-test/5 $TESTDIR/rsync-test/Attic/5 \
+      && test -f $TESTDIR/rsync-test-copy/Attic/6 \
+      && $rsync -rglop --delete $TESTDIR/rsync-test/ $TESTDIR/rsync-test-copy \
+             >/dev/null 2>&1 \
+      && $rsync -rglop --delete --include Attic --exclude '*/' \
+             $TESTDIR/rsync-test/ $TESTDIR/rsync-test-copy2 \
+             >/dev/null 2>&1 \
+      && test ! -f $TESTDIR/rsync-test-copy/5 \
+      && test ! -f $TESTDIR/rsync-test-copy2/5 \
+      && test -f $TESTDIR/rsync-test-copy2/Attic/5 \
+      && test ! -f $TESTDIR/rsync-test-copy2/otherdir/7
+    then
+      # good, it works
+      rsyncworks=:
+      RSYNC=$rsync
+    else
+      # Only use Which because of ${RSYNC} in the for loop.
+      set_bad_tool `Which $rsync`
+    fi
+  
+    rm -rf $TESTDIR/rsync-test $TESTDIR/rsync-test-copy \
+       $TESTDIR/rsync-test-copy2
+
+    if $rsyncworks; then
+      return 0
+    else
+      (echo $rsync failed to work properly;\
+       echo "$rsync --version"; $rsync --version) >>$LOGFILE 2>&1
+    fi
+  done
+
+  unset RSYNC
+  skipreason="unusable or no rsync found"
+  return 77
+}
+
+# Test that $1 works as a remote shell.  If so, set $host, $CVS_RSH, &
+# $save_CVS_RSH to match and return 0.  Otherwise, set $skipreason and return
+# 77.
+require_rsh ()
+{
+  if test x"$DISABLE_ANY_RSH" = x"1"; then
+    skipreason="administratively prohibited"
+    return 77
+  fi
+
+  host=${remotehost-"`hostname`"}
+  result=`$1 $host 'echo test'`
+  rc=$?
+  if test $? != 0 || test "x$result" != "xtest"; then
+    skipreason="\`$1 $host' failed rc=$rc result=$result"
+    return 77
+  fi
+
+  save_CVS_RSH=$CVS_RSH
+  CVS_RSH=$1; export CVS_RSH
+  return 0
+}
+
+# Find a usable SSH.  When a usable ssh is found, set $host, $CVS_RSH, and
+# $save_CVS_RSH and return 0.  Otherwise, set $skipreason and return 77.
+require_ssh ()
+{
+  case "$CVS_RSH" in
+    *ssh*|*putty*)
+      tryssh=`Which $CVS_RSH`
+      if [ ! -n "$tryssh" ]; then
+       skipreason="Unable to find CVS_RSH=$CVS_RSH executable"
+       return 77
+      elif [ ! -x "$tryssh" ]; then
+       skipreason="Unable to execute $tryssh program"
+       return 77
+      fi
+      ;;
+    *)
+      # Look in the user's PATH for "ssh"
+      tryssh=`Which ssh`
+      if test ! -r "$tryssh"; then
+       skipreason="Unable to find ssh program"
+       return 77
+      fi
+      ;;
+  esac
+
+  require_rsh "$tryssh"
+  return $?
+}
+
+pass ()
+{
+  echo "PASS: $1" >>${LOGFILE}
+  passed=`expr $passed + 1`
+}
+
+# Like skip(), but don't fail when $skipfail is set.
+skip_always ()
+{
+  echo "SKIP: $1${2+ ($2)}" >>$LOGFILE
+  skipped=`expr $skipped + 1`
+}
+
+skip ()
+{
+  if $skipfail; then
+    # exits
+    fail "$1${2+ ($2)}"
+  fi
+
+  skip_always ${1+"$@"}
+}
+
+# Convenience function for skipping tests run only in remote mode.
+remoteonly ()
+{
+  skip_always $1 "only tested in remote mode"
+}
+
+# Convenience function for skipping tests not run in proxy mode.
+notproxy ()
+{
+  skip_always $1 "not tested in proxy mode"
+}
+
+# Convenience function for skipping tests not run in proxy mode.
+notnoredirect ()
+{
+  skip_always $1 "not tested in proxy-noredirect mode"
+}
+
+warn ()
+{
+  if $skipfail; then
+    fail "$1${2+ ($2)}"
+  else
+    echo "WARNING: $1${2+ ($2)}" >>$LOGFILE
+  fi
+  warnings=`expr $warnings + 1`
+}
+
+fail ()
+{
+  echo "FAIL: $1" | tee -a ${LOGFILE}
+  echo "*** Please see the \`TESTS' and \`check.log' files for more information." >&2
+  # This way the tester can go and see what remnants were left
+  exit 1
+}
+
+verify_tmp_empty ()
+{
+  # Test our temp directory for cvs-serv* directories and cvsXXXXXX temp
+  # files.  We would like to not leave any behind.
+  if $remote && $LS $TMPDIR/cvs-serv* >/dev/null 2>&1; then
+    # A true value means ls found files/directories with these names.
+    # Give the server some time to finish, then retry.
+    sleep 2
+    if $LS $TMPDIR/cvs-serv* >/dev/null 2>&1; then
+      warn "$1" "Found cvs-serv* directories in $TMPDIR."
+      # The above will exit if $skipfail
+      rm -rf $TMPDIR/cvs-serv*
+    fi
+  fi
+  if $LS $TMPDIR/cvs?????? >/dev/null 2>&1; then
+    # A true value means ls found files/directories with these names.
+    warn "$1" "Found cvsXXXXXX temp files in $TMPDIR."
+    # The above will exit if $skipfail
+    rm -f ls $TMPDIR/cvs??????
+  fi
+}
+
+# See dotest and dotest_fail for explanation (this is the parts
+# of the implementation common to the two).
+dotest_internal ()
+{
+  if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : "$3${ENDANCHOR}" >/dev/null; then
+    # Why, I hear you ask, do we write this to the logfile
+    # even when the test passes?  The reason is that the test
+    # may give us the regexp which we were supposed to match,
+    # but sometimes it may be useful to look at the exact
+    # text which was output.  For example, suppose one wants
+    # to grep for a particular warning, and make _sure_ that
+    # CVS never hits it (even in cases where the tests might
+    # match it with .*).  Or suppose one wants to see the exact
+    # date format output in a certain case (where the test will
+    # surely use a somewhat non-specific pattern).
+    cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
+    pass "$1"
+    verify_tmp_empty "$1"
+  # expr can't distinguish between "zero characters matched" and "no match",
+  # so special-case it.
+  elif test -z "$3" && test ! -s ${TESTDIR}/dotest.tmp; then
+    pass "$1"
+    verify_tmp_empty "$1"
+  elif test x"$4" != x; then
+    if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : "$4${ENDANCHOR}" >/dev/null; then
+      cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
+      pass "$1"
+      verify_tmp_empty "$1"
+    else
+      echo "** expected: " >>${LOGFILE}
+      echo "$3" >>${LOGFILE}
+      echo "$3" > ${TESTDIR}/dotest.ex1
+      echo "** or: " >>${LOGFILE}
+      echo "$4" >>${LOGFILE}
+      echo "$4" > ${TESTDIR}/dotest.ex2
+      echo "** got: " >>${LOGFILE}
+      cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
+      fail "$1"
+    fi
+  else
+    echo "** expected: " >>${LOGFILE}
+    echo "$3" >>${LOGFILE}
+    echo "$3" > ${TESTDIR}/dotest.exp
+    echo "** got: " >>${LOGFILE}
+    cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
+    fail "$1"
+  fi
+}
+
+dotest_all_in_one ()
+{
+  if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : \
+         "`cat ${TESTDIR}/dotest.exp`" >/dev/null; then
+    return 0
+  fi
+  return 1
+}
+
+# WARNING: this won't work with REs that match newlines....
+#
+dotest_line_by_line ()
+{
+  line=1
+  while [ $line -le `wc -l <${TESTDIR}/dotest.tmp` ] ; do
+    if $EXPR "`sed -n ${line}p ${TESTDIR}/dotest.tmp`" : \
+       "`sed -n ${line}p ${TESTDIR}/dotest.exp`" >/dev/null; then
+      :
+    elif test -z "`sed -n ${line}p ${TESTDIR}/dotest.tmp`" &&
+       test -z "`sed -n ${line}p ${TESTDIR}/dotest.exp`"; then
+      :
+    else
+      echo "Line $line:" >> ${LOGFILE}
+      echo "**** expected: " >>${LOGFILE}
+      sed -n ${line}p ${TESTDIR}/dotest.exp >>${LOGFILE}
+      echo "**** got: " >>${LOGFILE}
+      sed -n ${line}p ${TESTDIR}/dotest.tmp >>${LOGFILE}
+      unset line
+      return 1
+    fi
+    line=`expr $line + 1`
+  done
+  unset line
+  return 0
+}
+
+# If you are having trouble telling which line of a multi-line
+# expression is not being matched, replace calls to dotest_internal()
+# with calls to this function:
+#
+dotest_internal_debug ()
+{
+  if test -z "$3"; then
+    if test -s ${TESTDIR}/dotest.tmp; then
+      echo "** expected: " >>${LOGFILE}
+      echo "$3" >>${LOGFILE}
+      echo "$3" > ${TESTDIR}/dotest.exp
+      rm -f ${TESTDIR}/dotest.ex2
+      echo "** got: " >>${LOGFILE}
+      cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
+      fail "$1"
+    else
+      pass "$1"
+      verify_tmp_empty "$1"
+    fi
+  else
+    echo "$3" > ${TESTDIR}/dotest.exp
+    if dotest_line_by_line "$1" "$2"; then
+      pass "$1"
+      verify_tmp_empty "$1"
+    else
+      if test x"$4" != x; then
+       mv ${TESTDIR}/dotest.exp ${TESTDIR}/dotest.ex1
+       echo "$4" > ${TESTDIR}/dotest.exp
+       if dotest_line_by_line "$1" "$2"; then
+         pass "$1"
+         verify_tmp_empty "$1"
+       else
+         mv ${TESTDIR}/dotest.exp ${TESTDIR}/dotest.ex2
+         echo "** expected: " >>${LOGFILE}
+         echo "$3" >>${LOGFILE}
+         echo "** or: " >>${LOGFILE}
+         echo "$4" >>${LOGFILE}
+         echo "** got: " >>${LOGFILE}
+         cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
+         fail "$1"
+       fi
+      else
+       echo "** expected: " >>${LOGFILE}
+       echo "$3" >>${LOGFILE}
+       echo "** got: " >>${LOGFILE}
+       cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
+       fail "$1"
+      fi
+    fi
+  fi
+}
+
+# This function allows the test output to be filtered before being verified.
+# The dotest_* functions all call this function, which runs the command
+# in the env var $TEST_FILTER on its argument if $TEST_FILTER is set.  If
+# $TEST_FILTER is not set, this function does nothing.
+#
+# I found this primarily useful when running the test suite on a CVS
+# executable linked with memory and function profilers which can generate
+# spurious output.
+run_filter ()
+{
+  if test -n "$TEST_FILTER"; then
+    # Make sure there is an EOL
+    echo >>$1
+    sed '${/^$/d}' <$1 >$1.filter1
+    # Run the filter
+    eval "$TEST_FILTER" <$1.filter1 >$1.filter2
+    diff -u $1 $1.filter2 \
+           >$1.diff
+    mv $1.filter2 $1
+    rm $1.filter1
+  fi
+}
+
+# Usage:
+#  dotest TESTNAME COMMAND OUTPUT [OUTPUT2]
+# TESTNAME is the name used in the log to identify the test.
+# COMMAND is the command to run; for the test to pass, it exits with
+# exitstatus zero.
+# OUTPUT is a regexp which is compared against the output (stdout and
+# stderr combined) from the test.  It is anchored to the start and end
+# of the output, so should start or end with ".*" if that is what is desired.
+# Trailing newlines are stripped from the command's actual output before
+# matching against OUTPUT.
+# If OUTPUT2 is specified and the output matches it, then it is also
+# a pass (partial workaround for the fact that some versions of expr
+# lack \|).
+dotest ()
+{
+  #echo dotest >$TESTDIR/_dotest.fun
+  #pwd >$TESTDIR/_dotest.cwd
+  #printf '%s\n' "$2" >$TESTDIR/_dotest.cmd
+  rm -f $TESTDIR/dotest.ex? 2>&1
+  eval "$2" >$TESTDIR/dotest.tmp 2>&1
+  status=$?
+  run_filter $TESTDIR/dotest.tmp
+  if test "$status" != 0; then
+    cat $TESTDIR/dotest.tmp >>$LOGFILE
+    echo "exit status was $status" >>${LOGFILE}
+    fail "$1"
+  fi
+  dotest_internal "$@"
+}
+
+# Like dotest except only 2 args and result must exactly match stdin
+dotest_lit ()
+{
+  #echo dotest_lit >$TESTDIR/_dotest.fun
+  #pwd >$TESTDIR/_dotest.cwd
+  #printf '%s\n' "$2" >$TESTDIR/_dotest.cmd
+  rm -f $TESTDIR/dotest.ex? 2>&1
+  eval "$2" >$TESTDIR/dotest.tmp 2>&1
+  status=$?
+  run_filter $TESTDIR/dotest.tmp
+  if test "$status" != 0; then
+    cat $TESTDIR/dotest.tmp >>$LOGFILE
+    echo "exit status was $status" >>$LOGFILE
+    fail "$1"
+  fi
+  cat >$TESTDIR/dotest.exp
+  if cmp $TESTDIR/dotest.exp $TESTDIR/dotest.tmp >/dev/null 2>&1; then
+    pass "$1"
+    verify_tmp_empty "$1"
+  else
+    echo "** expected: " >>$LOGFILE
+    cat $TESTDIR/dotest.exp >>$LOGFILE
+    echo "** got: " >>$LOGFILE
+    cat $TESTDIR/dotest.tmp >>$LOGFILE
+    fail "$1"
+  fi
+}
+
+# Like dotest except exitstatus should be nonzero.
+dotest_fail ()
+{
+  #echo dotest_fail >$TESTDIR/_dotest.fun
+  #pwd >$TESTDIR/_dotest.cwd
+  #printf '%s\n' "$2" >$TESTDIR/_dotest.cmd
+  rm -f $TESTDIR/dotest.ex? 2>&1
+  eval "$2" >$TESTDIR/dotest.tmp 2>&1
+  status=$?
+  run_filter $TESTDIR/dotest.tmp
+  if test "$status" = 0; then
+    cat $TESTDIR/dotest.tmp >>$LOGFILE
+    echo "exit status was $status" >>$LOGFILE
+    fail "$1"
+  fi
+  dotest_internal "$@"
+}
+
+# Like dotest except output is sorted.
+dotest_sort ()
+{
+  #echo dotest_sort >$TESTDIR/_dotest.fun
+  #pwd >$TESTDIR/_dotest.cwd
+  #printf '%s\n' "$2" >$TESTDIR/_dotest.cmd
+  rm -f $TESTDIR/dotest.ex? 2>&1
+  eval "$2" >$TESTDIR/dotest.tmp1 2>&1
+  status=$?
+  run_filter $TESTDIR/dotest.tmp1
+  if test "$status" != 0; then
+    cat $TESTDIR/dotest.tmp1 >>$LOGFILE
+    echo "exit status was $status" >>$LOGFILE
+    fail "$1"
+  fi
+  $TR '        ' ' ' < $TESTDIR/dotest.tmp1 | sort > $TESTDIR/dotest.tmp
+  dotest_internal "$@"
+}
+
+# Like dotest_fail except output is sorted.
+dotest_fail_sort ()
+{
+  #echo dotest_fail_sort >$TESTDIR/_dotest.fun
+  #pwd >$TESTDIR/_dotest.cwd
+  #printf '%s\n' "$2" >$TESTDIR/_dotest.cmd
+  rm -f $TESTDIR/dotest.ex? 2>&1
+  eval "$2" >$TESTDIR/dotest.tmp1 2>&1
+  status=$?
+  run_filter $TESTDIR/dotest.tmp1
+  if test "$status" = 0; then
+    cat $TESTDIR/dotest.tmp1 >>$LOGFILE
+    echo "exit status was $status" >>$LOGFILE
+    fail "$1"
+  fi
+  $TR '        ' ' ' < $TESTDIR/dotest.tmp1 | sort > $TESTDIR/dotest.tmp
+  dotest_internal "$@"
+}
+
+# A function for fetching the timestamp of a revison of a file
+getrlogdate () {
+    ${testcvs} -n rlog -N ${1+"$@"} |
+    while read token value; do
+       case "$token" in
+       date:)
+           echo $value | sed "s,;.*,,"
+           break;
+            ;;
+       esac
+    done
+}
+
+# Avoid picking up any stray .cvsrc, etc., from the user running the tests
+mkdir home
+HOME=$TESTDIR/home; export HOME
+
+# Make sure this variable is not defined to anything that would
+# change the format of rcs dates.  Otherwise people using e.g.,
+# RCSINIT=-zLT get lots of spurious failures.
+RCSINIT=; export RCSINIT
+
+# Remaining arguments are the names of tests to run.
+#
+# The testsuite is broken up into (hopefully manageably-sized)
+# independently runnable tests, so that one can quickly get a result
+# from a cvs or testsuite change, and to facilitate understanding the
+# tests.
+
+if test x"$*" = x; then
+       # Basic/miscellaneous functionality
+       tests="version basica basicb basicc basic1 deep basic2 ls"
+       tests="$tests parseroot parseroot2 parseroot3 files spacefiles"
+       tests="${tests} commit-readonly commit-add-missing"
+       tests="${tests} status"
+       tests="${tests} suck"
+       # Branching, tagging, removing, adding, multiple directories
+       tests="${tests} rdiff rdiff-short"
+       tests="${tests} rdiff2 diff diffnl death death2"
+       tests="${tests} rm-update-message rmadd rmadd2 rmadd3 resurrection"
+       tests="${tests} dirs dirs2 branches branches2 branches3"
+       tests="${tests} branches4 tagc tagf tag-space"
+       tests="${tests} rcslib multibranch import importb importc importX"
+       tests="$tests importX2 import-CVS import-quirks"
+       tests="${tests} update-p import-after-initial branch-after-import"
+       tests="${tests} join join2 join3 join4 join5 join6 join7"
+       tests="${tests} join-readonly-conflict join-admin join-admin-2"
+       tests="${tests} join-rm"
+       tests="${tests} new newb conflicts conflicts2 conflicts3"
+       tests="${tests} clean"
+       tests="${tests} keywordexpand"
+       # Checking out various places (modules, checkout -d, &c)
+       tests="${tests} modules modules2 modules3 modules4 modules5 modules6"
+       tests="${tests} modules7 mkmodules co-d"
+       tests="${tests} cvsadm emptydir abspath abspath2 toplevel toplevel2"
+        tests="${tests} rstar-toplevel trailingslashes checkout_repository"
+       # Log messages, error messages.
+       tests="${tests} mflag editor env errmsg1 errmsg2 adderrmsg opterrmsg"
+       tests="${tests} errmsg3"
+       tests="${tests} close-stdout"
+       tests="$tests debug-log-nonfatal"
+       # Watches, binary files, history browsing, &c.
+       tests="${tests} devcom devcom2 devcom3 watch4 watch5 watch6-0 watch6"
+        tests="${tests} edit-check"
+       tests="${tests} unedit-without-baserev"
+       tests="${tests} ignore ignore-on-branch binfiles binfiles2 binfiles3"
+       tests="${tests} mcopy binwrap binwrap2"
+       tests="${tests} binwrap3 mwrap info taginfo posttag"
+       tests="$tests config config2 config3 config4"
+       tests="${tests} serverpatch log log2 logopt ann ann-id"
+       # Repository Storage (RCS file format, CVS lock files, creating
+       # a repository without "cvs init", &c).
+       tests="${tests} crerepos rcs rcs2 rcs3 rcs4 rcs5"
+       tests="$tests lockfiles backuprecover"
+       tests="${tests} sshstdio"
+       # More history browsing, &c.
+       tests="${tests} history"
+       tests="${tests} big modes modes2 modes3 stamps"
+       # PreservePermissions stuff: permissions, symlinks et al.
+       # tests="${tests} perms symlinks symlinks2 hardlinks"
+       # More tag and branch tests, keywords.
+       tests="${tests} sticky keyword keywordlog keywordname keyword2"
+       tests="${tests} head tagdate multibranch2 tag8k"
+       # "cvs admin", reserved checkouts.
+       tests="${tests} admin reserved"
+       # Nuts and bolts of diffing/merging (diff library, &c)
+       tests="${tests} diffmerge1 diffmerge2"
+       # Release of multiple directories
+       tests="${tests} release"
+       tests="${tests} recase"
+       # Multiple root directories and low-level protocol tests.
+       tests="${tests} multiroot multiroot2 multiroot3 multiroot4"
+       tests="${tests} rmroot reposmv pserver server server2 client"
+       tests="${tests} dottedroot fork commit-d template"
+       tests="${tests} writeproxy writeproxy-noredirect writeproxy-ssh"
+       tests="${tests} writeproxy-ssh-noredirect"
+else
+       tests="$*"
+fi
+
+# Now check the -f argument for validity.
+if test -n "$fromtest"; then
+       # Don't allow spaces - they are our delimiters in tests
+       count=0
+       for sub in $fromtest; do
+         count=`expr $count + 1`
+       done
+       if test $count != 1; then
+               echo "No such test \`$fromtest'." >&2
+               exit 2
+       fi
+       # make sure it is in $tests
+       case " $tests " in
+               *" $fromtest "*)
+                       ;;
+               *)
+                       echo "No such test \`$fromtest'." >&2
+                       exit 2
+                       ;;
+       esac
+fi
+
+
+
+# a simple function to compare directory contents
+#
+# Returns: 0 for same, 1 for different
+#
+directory_cmp ()
+{
+       OLDPWD=`pwd`
+       DIR_1=$1
+       DIR_2=$2
+
+       cd $DIR_1
+       find . -print | fgrep -v /CVS | sort > $TESTDIR/dc$$d1
+
+       # go back where we were to avoid symlink hell...
+       cd $OLDPWD
+       cd $DIR_2
+       find . -print | fgrep -v /CVS | sort > $TESTDIR/dc$$d2
+
+       if diff $TESTDIR/dc$$d1 $TESTDIR/dc$$d2 >/dev/null 2>&1
+       then
+               :
+       else
+               return 1
+       fi
+       cd $OLDPWD
+       while read a
+       do
+               if test -f $DIR_1/"$a" ; then
+                       cmp -s $DIR_1/"$a" $DIR_2/"$a"
+                       if test $? -ne 0 ; then
+                               return 1
+                       fi
+               fi
+       done < $TESTDIR/dc$$d1
+       rm -f $TESTDIR/dc$$*
+       return 0
+}
+
+
+
+#
+# The following 4 functions are used by the diffmerge1 test case.  They set up,
+# respectively, the four versions of the files necessary:
+#
+#      1.  Ancestor revisions.
+#      2.  "Your" changes.
+#      3.  "My" changes.
+#      4.  Expected merge result.
+#
+
+# Create ancestor revisions for diffmerge1
+diffmerge_create_older_files() {
+         # This test case was supplied by Noah Friedman:
+         cat >testcase01 <<EOF
+// Button.java
+
+package random.application;
+
+import random.util.*;
+
+public class Button
+{
+  /* Instantiates a Button with origin (0, 0) and zero width and height.
+   * You must call an initializer method to properly initialize the Button.
+   */
+  public Button ()
+  {
+    super ();
+
+    _titleColor = Color.black;
+    _disabledTitleColor = Color.gray;
+    _titleFont = Font.defaultFont ();
+  }
+
+  /* Convenience constructor for instantiating a Button with
+   * bounds x, y, width, and height.  Equivalent to
+   *     foo = new Button ();
+   *     foo.init (x, y, width, height);
+   */
+  public Button (int x, int y, int width, int height)
+  {
+    this ();
+    init (x, y, width, height);
+  }
+}
+EOF
+
+         # This test case was supplied by Jacob Burckhardt:
+         cat >testcase02 <<EOF
+a
+a
+a
+a
+a
+EOF
+
+         # This test case was supplied by Karl Tomlinson who also wrote the
+         # patch which lets CVS correctly handle this and several other cases:
+         cat >testcase03 <<EOF
+x
+s
+a
+b
+s
+y
+EOF
+
+         # This test case was supplied by Karl Tomlinson:
+         cat >testcase04 <<EOF
+s
+x
+m
+m
+x
+s
+v
+s
+x
+m
+m
+x
+s
+EOF
+
+         # This test case was supplied by Karl Tomlinson:
+         cat >testcase05 <<EOF
+s
+x
+m
+m
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+s
+s
+s
+s
+s
+s
+s
+s
+s
+s
+v
+EOF
+
+         # This test case was supplied by Jacob Burckhardt:
+         cat >testcase06 <<EOF
+g
+
+
+
+
+
+
+
+
+
+
+
+i
+EOF
+
+         # This test is supposed to verify that the horizon lines are the same
+         # for both 2-way diffs, but unfortunately, it does not fail with the
+         # old version of cvs.  However, Karl Tomlinson still thought it would
+         # be good to test it anyway:
+         cat >testcase07 <<EOF
+h
+f
+
+
+
+
+
+
+
+
+
+g
+r
+
+
+
+i
+
+
+
+
+
+
+
+
+
+
+i
+EOF
+
+         # This test case was supplied by Jacob Burckhardt:
+         cat >testcase08 <<EOF
+Both changes move this line to the end of the file.
+
+no
+changes
+here
+
+First change will delete this line.
+
+First change will also delete this line.
+
+    no
+    changes
+    here
+
+Second change will change it here.
+
+        no
+        changes
+        here
+EOF
+
+         # This test case was supplied by Jacob Burckhardt.  Note that I do not
+         # think cvs has ever failed with this case, but I include it anyway,
+         # since I think it is a hard case.  It is hard because Peter Miller's
+         # fmerge utility fails on it:
+         cat >testcase09 <<EOF
+m
+a
+{
+}
+b
+{
+}
+EOF
+
+         # This test case was supplied by Martin Dorey and simplified by Jacob
+         # Burckhardt:
+         cat >testcase10 <<EOF
+
+    petRpY ( MtatRk );
+    fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
+
+    MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
+    OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
+
+    Bloke_GttpfIRte_MtpeaL ( &acI );
+MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
+{
+    fV ( Y < 16 )
+    {
+        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
+                                                      Y * jfle_Uecopd_MfJe_fY_Mectopk,
+                                jfle_Uecopd_MfJe_fY_Mectopk,
+                                nRVVep ) );
+    }
+    elke
+    {
+        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
+                                                 ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
+                                jfle_Uecopd_MfJe_fY_Mectopk,
+                                nRVVep ) );
+    }
+
+}
+
+
+/****************************************************************************
+*                                                                           *
+*   Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY )                      *
+*                                                                           *
+****************************************************************************/
+
+MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
+{
+MTGTXM MtatRk = Zy;
+
+    MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
+
+    petRpY ( MtatRk );
+
+}
+    HfkQipfte ( waYdle,                 /*  waYdle                         */
+                waYdleFok,              /*  ZVVket VpoL ktapt oV dfkQ      */
+                (coYkt RfYt8*) nRVVep,  /*  nRVVep                         */
+                0,                      /*  MRrepVlRoRk KfxoYfkL           */
+                beYgtz                  /*  nEtek to Apfte                 */
+              );
+
+    petRpY ( Zy );
+}
+EOF
+}
+
+# Create "your" revisions for diffmerge1
+diffmerge_create_your_files() {
+         # remove the Button() method
+         cat >testcase01 <<\EOF
+// Button.java
+
+package random.application;
+
+import random.util.*;
+
+public class Button
+{
+  /* Instantiates a Button with origin (0, 0) and zero width and height.
+   * You must call an initializer method to properly initialize the Button.
+   */
+  public Button ()
+  {
+    super ();
+
+    _titleColor = Color.black;
+    _disabledTitleColor = Color.gray;
+    _titleFont = Font.defaultFont ();
+  }
+}
+EOF
+
+         cat >testcase02 <<\EOF
+y
+a
+a
+a
+a
+EOF
+
+         cat >testcase03 <<\EOF
+x
+s
+a
+b
+s
+b
+s
+y
+EOF
+
+         cat >testcase04 <<\EOF
+s
+m
+s
+v
+s
+m
+s
+EOF
+
+         cat >testcase05 <<\EOF
+v
+s
+m
+s
+s
+s
+s
+s
+s
+s
+s
+s
+s
+v
+EOF
+
+         # Test case 6 and test case 7 both use the same input files, but they
+         # order the input files differently.  In one case, a certain file is
+         # used as the older file, but in the other test case, that same file
+         # is used as the file which has changes.  I could have put echo
+         # commands here, but since the echo lines would be the same as those
+         # in the previous function, I decided to save space and avoid repeating
+         # several lines of code.  Instead, I merely swap the files:
+         mv testcase07 tmp
+         mv testcase06 testcase07
+         mv tmp testcase06
+
+         # Make the date newer so that cvs thinks that the files are changed:
+         touch testcase06 testcase07
+
+         cat >testcase08 <<\EOF
+no
+changes
+here
+
+First change has now added this in.
+
+    no
+    changes
+    here
+
+Second change will change it here.
+
+        no
+        changes
+        here
+
+Both changes move this line to the end of the file.
+EOF
+
+         cat >testcase09 <<\EOF
+
+m
+a
+{
+}
+b
+{
+}
+c
+{
+}
+EOF
+
+         cat >testcase10 <<\EOF
+
+    fV ( BzQkV_URYYfYg ) (*jfle_Uecopdk)[0].jfle_Uecopd_KRLIep = ZpfgfYal_jUK;
+
+    petRpY ( MtatRk );
+    fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
+
+    fV ( jfle_Uecopd_KRLIep < 16 )
+    {
+        MtatRk = Uead_Ktz_qjT_jfle_Uecopd ( jfle_Uecopd_KRLIep, (uofd*)nRVVep );
+    }
+    elke
+    {
+        MtatRk = ZreY_GttpfIRte_MtpeaL ( qjT_jfle_Uecopdk, qjT_jfle_Uecopd_BoRYt, HGTG_TvFD, KXbb, KXbb, &acI );
+        fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
+
+        MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
+        OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
+
+    Bloke_GttpfIRte_MtpeaL ( &acI );
+MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
+{
+MTGTXM MtatRk = Zy;
+
+    fV ( Y < 16 )
+    {
+        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
+                                                      Y * jfle_Uecopd_MfJe_fY_Mectopk,
+                                jfle_Uecopd_MfJe_fY_Mectopk,
+                                nRVVep ) );
+    }
+    elke
+    {
+        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
+                                                 ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
+                                jfle_Uecopd_MfJe_fY_Mectopk,
+                                nRVVep ) );
+    }
+
+    petRpY ( MtatRk );
+
+}
+
+
+/****************************************************************************
+*                                                                           *
+*   Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY )                      *
+*                                                                           *
+****************************************************************************/
+
+MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
+{
+MTGTXM MtatRk = Zy;
+
+    MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
+
+    petRpY ( MtatRk );
+
+}
+    HfkQipfte ( waYdle,                 /*  waYdle                         */
+                waYdleFok,              /*  ZVVket VpoL ktapt oV dfkQ      */
+                (coYkt RfYt8*) nRVVep,  /*  nRVVep                         */
+                0,                      /*  MRrepVlRoRk KfxoYfkL           */
+                beYgtz                  /*  nEtek to Apfte                 */
+              );
+
+    petRpY ( Zy );
+}
+
+EOF
+}
+
+# Create "my" revisions for diffmerge1
+diffmerge_create_my_files() {
+          # My working copy still has the Button() method, but I
+         # comment out some code at the top of the class.
+         cat >testcase01 <<\EOF
+// Button.java
+
+package random.application;
+
+import random.util.*;
+
+public class Button
+{
+  /* Instantiates a Button with origin (0, 0) and zero width and height.
+   * You must call an initializer method to properly initialize the Button.
+   */
+  public Button ()
+  {
+    super ();
+
+    // _titleColor = Color.black;
+    // _disabledTitleColor = Color.gray;
+    // _titleFont = Font.defaultFont ();
+  }
+
+  /* Convenience constructor for instantiating a Button with
+   * bounds x, y, width, and height.  Equivalent to
+   *     foo = new Button ();
+   *     foo.init (x, y, width, height);
+   */
+  public Button (int x, int y, int width, int height)
+  {
+    this ();
+    init (x, y, width, height);
+  }
+}
+EOF
+
+         cat >testcase02 <<\EOF
+a
+a
+a
+a
+m
+EOF
+
+         cat >testcase03 <<\EOF
+x
+s
+c
+s
+b
+s
+y
+EOF
+
+         cat >testcase04 <<\EOF
+v
+s
+x
+m
+m
+x
+s
+v
+s
+x
+m
+m
+x
+s
+v
+EOF
+
+         # Note that in test case 5, there are no changes in the "mine"
+         # section, which explains why there is no command here which writes to
+         # file testcase05.
+
+         # no changes for testcase06
+
+         # The two branches make the same changes:
+         cp ../yours/testcase07 .
+
+         cat >testcase08 <<\EOF
+no
+changes
+here
+
+First change will delete this line.
+
+First change will also delete this line.
+
+    no
+    changes
+    here
+
+Second change has now changed it here.
+
+        no
+        changes
+        here
+
+Both changes move this line to the end of the file.
+EOF
+
+         cat >testcase09 <<\EOF
+m
+a
+{
+}
+b
+{
+}
+c
+{
+}
+EOF
+
+         cat >testcase10 <<\EOF
+
+    petRpY ( MtatRk );
+    fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
+
+    MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
+    OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
+
+    Bloke_GttpfIRte_MtpeaL ( &acI );
+MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
+{
+    fV ( Y < 16 )
+    {
+        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
+                                                      Y * jfle_Uecopd_MfJe_fY_Mectopk,
+                                jfle_Uecopd_MfJe_fY_Mectopk,
+                                nRVVep ) );
+    }
+    elke
+    {
+        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
+                                                 ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
+                                jfle_Uecopd_MfJe_fY_Mectopk,
+                                nRVVep ) );
+    }
+
+}
+
+
+/****************************************************************************
+*                                                                           *
+*   Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY )                      *
+*                                                                           *
+****************************************************************************/
+
+MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
+{
+MTGTXM MtatRk = Zy;
+
+    MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
+
+    petRpY ( MtatRk );
+
+}
+    HfkQipfte ( waYdle,                 /*  waYdle                         */
+                waYdleFok,              /*  ZVVket VpoL ktapt oV dfkQ      */
+                (coYkt RfYt8*) nRVVep,  /*  nRVVep                         */
+                beYgtz                  /*  nEtek to Apfte                 */
+              );
+
+    petRpY ( Zy );
+}
+
+EOF
+}
+
+# Create expected results of merge for diffmerge1
+diffmerge_create_expected_files() {
+         cat >testcase01 <<\EOF
+// Button.java
+
+package random.application;
+
+import random.util.*;
+
+public class Button
+{
+  /* Instantiates a Button with origin (0, 0) and zero width and height.
+   * You must call an initializer method to properly initialize the Button.
+   */
+  public Button ()
+  {
+    super ();
+
+    // _titleColor = Color.black;
+    // _disabledTitleColor = Color.gray;
+    // _titleFont = Font.defaultFont ();
+  }
+}
+EOF
+
+         cat >testcase02 <<\EOF
+y
+a
+a
+a
+m
+EOF
+
+         cat >testcase03 <<\EOF
+x
+s
+c
+s
+b
+s
+b
+s
+y
+EOF
+
+         cat >testcase04 <<\EOF
+v
+s
+m
+s
+v
+s
+m
+s
+v
+EOF
+
+         # Since there are no changes in the "mine" section, just take exactly
+         # the version in the "yours" section:
+         cp ../yours/testcase05 .
+
+         cp ../yours/testcase06 .
+
+         # Since the two branches make the same changes, the result should be
+         # the same as both branches.  Here, I happen to pick yours to copy from,
+         # but I could have also picked mine, since the source of the copy is
+         # the same in either case.  However, the mine has already been
+         # altered by the update command, so don't use it.  Instead, use the
+         # yours section which has not had an update on it and so is unchanged:
+         cp ../yours/testcase07 .
+
+         cat >testcase08 <<\EOF
+no
+changes
+here
+
+First change has now added this in.
+
+    no
+    changes
+    here
+
+Second change has now changed it here.
+
+        no
+        changes
+        here
+
+Both changes move this line to the end of the file.
+EOF
+
+         cat >testcase09 <<\EOF
+
+m
+a
+{
+}
+b
+{
+}
+c
+{
+}
+EOF
+
+         cat >testcase10 <<\EOF
+
+    fV ( BzQkV_URYYfYg ) (*jfle_Uecopdk)[0].jfle_Uecopd_KRLIep = ZpfgfYal_jUK;
+
+    petRpY ( MtatRk );
+    fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
+
+    fV ( jfle_Uecopd_KRLIep < 16 )
+    {
+        MtatRk = Uead_Ktz_qjT_jfle_Uecopd ( jfle_Uecopd_KRLIep, (uofd*)nRVVep );
+    }
+    elke
+    {
+        MtatRk = ZreY_GttpfIRte_MtpeaL ( qjT_jfle_Uecopdk, qjT_jfle_Uecopd_BoRYt, HGTG_TvFD, KXbb, KXbb, &acI );
+        fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
+
+        MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
+        OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
+
+    Bloke_GttpfIRte_MtpeaL ( &acI );
+MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
+{
+MTGTXM MtatRk = Zy;
+
+    fV ( Y < 16 )
+    {
+        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
+                                                      Y * jfle_Uecopd_MfJe_fY_Mectopk,
+                                jfle_Uecopd_MfJe_fY_Mectopk,
+                                nRVVep ) );
+    }
+    elke
+    {
+        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
+                                                 ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
+                                jfle_Uecopd_MfJe_fY_Mectopk,
+                                nRVVep ) );
+    }
+
+    petRpY ( MtatRk );
+
+}
+
+
+/****************************************************************************
+*                                                                           *
+*   Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY )                      *
+*                                                                           *
+****************************************************************************/
+
+MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
+{
+MTGTXM MtatRk = Zy;
+
+    MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
+
+    petRpY ( MtatRk );
+
+}
+    HfkQipfte ( waYdle,                 /*  waYdle                         */
+                waYdleFok,              /*  ZVVket VpoL ktapt oV dfkQ      */
+                (coYkt RfYt8*) nRVVep,  /*  nRVVep                         */
+                beYgtz                  /*  nEtek to Apfte                 */
+              );
+
+    petRpY ( Zy );
+}
+
+EOF
+}
+
+
+
+# Echo a new CVSROOT based on $1, $remote, and $remotehost
+newroot() {
+  if $remote; then
+    if test -n "$remotehost"; then
+      echo :ext$rootoptions:$remotehost$1
+    else
+      echo :fork$rootoptions:$1
+    fi
+  else
+    echo $1
+  fi
+}
+
+
+
+# Set up CVSROOT (the crerepos tests will test operating without CVSROOT set).
+#
+# Currently we test :fork: and :ext: (see crerepos test).  There is a
+# known difference between the two in modes-15 (see comments there).
+#
+# :ext: can be tested against a remote machine if:
+#
+#    1. $remotehost is set using the `-h' option to this script.
+#    2. ${CVS_RSH=rsh} $remotehost works.
+#    3. The path to $TESTDIR is the same on both machines (symlinks are okay)
+#    4. The path to $testcvs is the same on both machines (symlinks are okay)
+#       or $CVS_SERVER is overridden in this script's environment to point to
+#       a working CVS exectuable on the remote machine.
+#
+# Testing :pserver: would be hard (inetd issues).  (How about using tcpserver
+# and some high port number?  DRP)
+
+if $linkroot; then
+    mkdir ${TESTDIR}/realcvsroot
+    ln -s realcvsroot ${TESTDIR}/cvsroot
+fi
+CVSROOT_DIRNAME=${TESTDIR}/cvsroot
+CVSROOT=`newroot $CVSROOT_DIRNAME`; export CVSROOT
+
+
+
+###
+### Initialize the repository
+###
+dotest init-1 "$testcvs init"
+
+# We might need to allow "cvs admin" access.
+mkdir wnt
+cd wnt
+dotest init-1a "$testcvs -q co CVSROOT" "[UP] CVSROOT${DOTSTAR}"
+cd CVSROOT
+sed -e's/^#UserAdminOptions=/UserAdminOptions=/' <config >tmpconfig
+mv tmpconfig config
+dotest init-1b "$testcvs -q ci -m allow-cvs-admin" "" \
+".*/CVSROOT/config,v  <--  config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+$SPROG commit: Rebuilding administrative file database"
+cd ../..
+rm -r wnt
+
+# Now hide the primary root behind a secondary if requested.
+if $proxy; then
+    # Save the primary root.
+    PRIMARY_CVSROOT=$CVSROOT
+    PRIMARY_CVSROOT_DIRNAME=$CVSROOT_DIRNAME
+    # Where the secondary root will be
+    SECONDARY_CVSROOT_DIRNAME=$TESTDIR/secondary_cvsroot
+    if $noredirect; then
+       rootoptions=";Redirect=no"
+       SECONDARY_CVSROOT=`newroot $PRIMARY_CVSROOT_DIRNAME`
+    else
+       SECONDARY_CVSROOT=`newroot $SECONDARY_CVSROOT_DIRNAME`
+    fi
+    # Now set the global CVSROOT to use the secondary.
+    CVSROOT=$SECONDARY_CVSROOT; export CVSROOT
+
+    require_rsync
+    if test $? -eq 77; then
+       echo "Unable to test in proxy mode: $skipreason" >&2
+       skip all "missing or broken rsync command."
+       exit 0
+    fi
+
+    if $noredirect; then
+       # Wrap the CVS server to allow --primary-root to be set by the
+       # secondary.
+       cat <<EOF >$TESTDIR/secondary-wrapper
+#! $TESTSHELL
+CVS_SERVER=$TESTDIR/primary-wrapper
+export CVS_SERVER
+
+# No need to check the PID of the last client since we are testing with
+# Redirect disabled.
+proot_arg="--allow-root=$SECONDARY_CVSROOT_DIRNAME"
+exec $CVS_SERVER \$proot_arg "\$@"
+EOF
+       cat <<EOF >$TESTDIR/primary-wrapper
+#! $TESTSHELL
+if test -n "$CVS_SERVER_LOG"; then
+  CVS_SERVER_LOG=`dirname "$CVS_SERVER_LOG"`/cvsprimarylog
+  export CVS_SERVER_LOG
+fi
+exec $CVS_SERVER "\$@"
+EOF
+
+       CVS_SERVER_secondary=$TESTDIR/secondary-wrapper
+       CVS_SERVER=$CVS_SERVER_secondary
+
+       chmod a+x $TESTDIR/secondary-wrapper \
+                 $TESTDIR/primary-wrapper
+    fi
+
+    # Script to sync the secondary root.
+    cat >$TESTDIR/sync-secondary <<EOF
+#! $TESTSHELL
+# date >>$TESTDIR/update-log
+
+ps=\$1
+cmd=\$2
+dir=\$3
+shift
+shift
+shift
+
+# echo "updating from \$ps for command \\\`\$cmd' in dir \\\`\$dir'" \${1+"\$@"} \\
+#      >>$TESTDIR/update-log
+
+# If multiple CVS executables could attempt to access the repository, we would
+# Need to lock for this sync and sleep
+case "\$dir" in
+  ALL)
+    # This is a hack to allow a few of the tests to play with the
+    # UseNewInfoFmtStrings key in CVSROOT/config.  It's inefficient, but there
+    # aren't many tests than need it and the alternative is an awful lot of
+    # special casing.
+    $RSYNC -rglop --delete --exclude '#cvs.*' \\
+           $PRIMARY_CVSROOT_DIRNAME/ \\
+           $SECONDARY_CVSROOT_DIRNAME
+    ;;
+
+  *)
+    # For the majority of the tests we will only sync the directories that
+    # were written to.
+    case "\$cmd" in
+      add|import)
+       # For \`add', we need a recursive update due to quirks in rsync syntax,
+       # but it shouldn't affect efficiency since any new dir should be empty.
+       #
+       # For \`import', a recursive update is necessary since subdirs may have
+       # been added underneath the root dir we were passed. 
+        $RSYNC -rglop \\
+              $PRIMARY_CVSROOT_DIRNAME/"\$dir" \\
+              $SECONDARY_CVSROOT_DIRNAME/\`dirname -- "\$dir"\`
+        ;;
+
+      tag)
+       # \`tag' may have changed CVSROOT/val-tags too.
+        $RSYNC -glop \\
+               $PRIMARY_CVSROOT_DIRNAME/CVSROOT/val-tags \\
+               $SECONDARY_CVSROOT_DIRNAME/CVSROOT
+       # Otherwise it is identical to other write commands.
+        $RSYNC -rglop --delete \\
+               --include Attic --include CVS \
+               --exclude '#cvs.*' --exclude '*/' \\
+               $PRIMARY_CVSROOT_DIRNAME/"\$dir"/ \\
+               $SECONDARY_CVSROOT_DIRNAME/"\$dir"
+        ;;
+
+      *)
+       # By default, sync just what changed.
+        $RSYNC -rglop --delete \\
+               --include Attic --include CVS \
+               --exclude '#cvs.*' --exclude '*/' \\
+               $PRIMARY_CVSROOT_DIRNAME/"\$dir"/ \\
+               $SECONDARY_CVSROOT_DIRNAME/"\$dir"
+        ;;
+    esac # \$cmd
+
+    # And keep the history file up to date for all commands.
+    $RSYNC -glop \\
+           $PRIMARY_CVSROOT_DIRNAME/CVSROOT/history \\
+           $SECONDARY_CVSROOT_DIRNAME/CVSROOT
+    ;; # \$dir = *
+esac # \$dir
+
+# Avoid timestamp comparison issues with rsync.
+sleep 2
+EOF
+    chmod a+x $TESTDIR/sync-secondary
+
+    # And now init the secondary.
+    $TESTDIR/sync-secondary "- no, before - create secondary root" \
+                            sanity-setup ALL
+
+    # Initialize the primary repository
+    mkdir proxy-init; cd proxy-init
+    dotest proxy-init-1 "$testcvs -Qd$PRIMARY_CVSROOT co CVSROOT"
+    cd CVSROOT
+    cat >>config <<EOF
+PrimaryServer=$PRIMARY_CVSROOT
+EOF
+    cat >>loginfo <<EOF
+ALL $TESTDIR/sync-secondary loginfo %c %p %{sVv}
+EOF
+    cat >>postadmin <<EOF
+ALL $TESTDIR/sync-secondary postadmin %c %p
+EOF
+    cat >>posttag <<EOF
+ALL $TESTDIR/sync-secondary posttag %c %p %o %b %t %{sVv}
+EOF
+    cat >>postwatch <<EOF
+ALL $TESTDIR/sync-secondary postwatch %c %p
+EOF
+    dotest proxy-init-2 \
+"$testcvs -Q ci -mconfigure-writeproxy"
+
+    # Save these files for later reference
+    cp config $TESTDIR/config-clean
+    cp loginfo $TESTDIR/loginfo-clean
+    cp postadmin $TESTDIR/postadmin-clean
+    cp posttag $TESTDIR/posttag-clean
+    cp postwatch $TESTDIR/postwatch-clean
+
+    # done in here
+    cd ../..
+    rm -rf proxy-init
+else # !$proxy
+    # Set this even when not testing $proxy to match messages, like $SPROG.
+    SECONDARY_CVSROOT_DIRNAME=$CVSROOT_DIRNAME
+fi # $proxy
+
+# Save a copy of the initial repository so that it may be restored after the
+# tests that alter it.
+cp -Rp $CVSROOT_DIRNAME/CVSROOT $TESTDIR/CVSROOT.save
+
+
+###
+### The tests
+###
+dotest init-2 "$testcvs init"
+
+# We might need to allow "cvs admin" access.
+mkdir wnt
+cd wnt
+dotest init-2a "$testcvs -q co CVSROOT" "[UP] CVSROOT${DOTSTAR}"
+cd CVSROOT
+sed -e's/^#UserAdminOptions=/UserAdminOptions=/' <config >tmpconfig
+mv tmpconfig config
+dotest init-2b "$testcvs -q ci -m allow-cvs-admin" "" \
+".*/CVSROOT/config,v  <--  config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+$SPROG commit: Rebuilding administrative file database"
+cd ../..
+rm -r wnt
+
+
+###
+### The big loop
+###
+for what in $tests; do
+       if test -n "$fromtest" ; then
+           if test $fromtest = $what ; then
+               unset fromtest
+           else
+               continue
+           fi
+       fi
+       case $what in
+
+       version)
+         # We've had cases where the version command started dumping core,
+         # so we might as well test it
+         dotest version-1 "${testcvs} --version" \
+'
+Concurrent Versions System (CVS) [0-9.]*.*
+
+Copyright (C) [0-9]* Free Software Foundation, Inc.
+
+Portions contributed by Thorsten Glaser for the MirOS Project.
+Senior active maintainers include Larry Jones, Derek R. Price,
+and Mark D. Baushke.  Please see the AUTHORS and README files from the CVS
+distribution kit for a complete list of contributors and copyrights.
+
+CVS may be copied only under the terms of the GNU General Public License,
+a copy of which can be found with the CVS distribution kit.
+
+Specify the --help option for further information about CVS'
+
+# Maybe someday...
+#        if $proxy; then
+#              dotest version-2r "${testcvs} version" \
+#'Client: Concurrent Versions System (CVS) [0-9p.]* (client.*)
+#Server: Concurrent Versions System (CVS) [0-9p.]* (.*server)
+#Secondary Server: Concurrent Versions System (CVS) [0-9p.]* (.*server)'
+         if $remote; then
+               dotest version-2r "${testcvs} version" \
+'Client: Concurrent Versions System (CVS) [0-9p.]*\(-Mir[^ ]*\)* (client.*)
+Server: Concurrent Versions System (CVS) [0-9p.]*\(-Mir[^ ]*\)* (.*server)'
+         else
+               dotest version-2 "${testcvs} version" \
+'Concurrent Versions System (CVS) [0-9.]*.*'
+         fi
+         ;;
+
+
+
+       basica)
+         # Similar in spirit to some of the basic1, and basic2
+         # tests, but hopefully a lot faster.  Also tests operating on
+         # files two directories down *without* operating on the parent dirs.
+
+         # Tests basica-0a and basica-0b provide the equivalent of the:
+         #    mkdir ${CVSROOT_DIRNAME}/first-dir
+         # used by many of the tests.  It is "more official" in the sense
+         # that is does everything through CVS; the reason most of the
+         # tests don't use it is mostly historical.
+         mkdir 1; cd 1
+         dotest basica-0a "$testcvs -q co -l ."
+         mkdir first-dir
+         dotest basica-0b "$testcvs add first-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
+         cd ..
+         rm -r 1
+
+         dotest basica-1 "$testcvs -q co first-dir" ''
+         cd first-dir
+
+         # Test a few operations, to ensure they gracefully do
+         # nothing in an empty directory.
+         dotest basica-1a0 "$testcvs -q update"
+         dotest basica-1a1 "$testcvs -q diff -c"
+         dotest basica-1a2 "$testcvs -q status"
+         dotest basica-1a3 "$testcvs -q update ."
+         dotest basica-1a4 "$testcvs -q update ./"
+
+         mkdir sdir
+         # Remote CVS gives the "cannot open CVS/Entries" error, which is
+         # clearly a bug, but not a simple one to fix.
+         dotest basica-1a10 "$testcvs -n add sdir" \
+"Directory $CVSROOT_DIRNAME/first-dir/sdir put under version control" \
+"$SPROG add: cannot open CVS/Entries for reading: No such file or directory
+Directory $CVSROOT_DIRNAME/first-dir/sdir put under version control"
+         dotest_fail basica-1a11 \
+           "test -d $CVSROOT_DIRNAME/first-dir/sdir"
+         dotest basica-2 "$testcvs add sdir" \
+"Directory $CVSROOT_DIRNAME/first-dir/sdir put under version control"
+         cd sdir
+         mkdir ssdir
+         dotest basica-3 "$testcvs add ssdir" \
+"Directory $CVSROOT_DIRNAME/first-dir/sdir/ssdir put under version control"
+         cd ssdir
+         echo ssfile >ssfile
+
+         # Trying to commit it without a "cvs add" should be an error.
+         # The "use `cvs add' to create an entry" message is the one
+         # that I consider to be more correct, but local cvs prints the
+         # "nothing known" message and noone has gotten around to fixing it.
+         dotest_fail basica-notadded "${testcvs} -q ci ssfile" \
+"${CPROG} commit: use .${CPROG} add. to create an entry for \`ssfile'
+${CPROG}"' \[commit aborted\]: correct above errors first!' \
+"${CPROG}"' commit: nothing known about `ssfile'\''
+'"${CPROG}"' \[commit aborted\]: correct above errors first!'
+
+         dotest basica-4 "${testcvs} add ssfile" \
+"${SPROG}"' add: scheduling file `ssfile'\'' for addition
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+         dotest_fail basica-4a "${testcvs} tag tag0 ssfile" \
+"${SPROG} tag: nothing known about ssfile
+${SPROG} "'\[tag aborted\]: correct the above errors first!'
+         cd ../..
+         dotest basica-5 "${testcvs} -q ci -m add-it" \
+"$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  sdir/ssdir/ssfile
+initial revision: 1\.1"
+         dotest_fail basica-5a \
+           "${testcvs} -q tag BASE sdir/ssdir/ssfile" \
+"${SPROG} tag: Attempt to add reserved tag name BASE
+${SPROG} \[tag aborted\]: failed to set tag BASE to revision 1\.1 in ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v"
+         dotest basica-5b "${testcvs} -q tag NOT_RESERVED" \
+'T sdir/ssdir/ssfile'
+
+         dotest basica-6 "${testcvs} -q update" ''
+         echo "ssfile line 2" >>sdir/ssdir/ssfile
+         dotest_fail basica-6.2 "${testcvs} -q diff -c" \
+"Index: sdir/ssdir/ssfile
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+retrieving revision 1\.1
+diff -c -r1\.1 ssfile
+\*\*\* sdir/ssdir/ssfile       ${RFCDATE}      1\.1
+--- sdir/ssdir/ssfile  ${RFCDATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+--- 1,2 ----
+  ssfile
+${PLUS} ssfile line 2"
+         dotest_fail basica-6.3 "${testcvs} -q diff -c -rBASE" \
+"Index: sdir/ssdir/ssfile
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+retrieving revision 1\.1
+diff -c -r1\.1 ssfile
+\*\*\* sdir/ssdir/ssfile       ${RFCDATE}      1\.1
+--- sdir/ssdir/ssfile  ${RFCDATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+--- 1,2 ----
+  ssfile
+${PLUS} ssfile line 2"
+         dotest_fail basica-6.4 "${testcvs} -q diff -c -rBASE -C3isacrowd" \
+"Index: sdir/ssdir/ssfile
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+retrieving revision 1\.1
+diff -c -C 3isacrowd -r1\.1 ssfile
+${SPROG} diff: invalid context length argument"
+         dotest basica-7 "${testcvs} -q ci -m modify-it" \
+"$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  sdir/ssdir/ssfile
+new revision: 1\.2; previous revision: 1\.1"
+         dotest_fail basica-nonexist "${testcvs} -q ci nonexist" \
+"${CPROG}"' commit: nothing known about `nonexist'\''
+'"${CPROG}"' \[commit aborted\]: correct above errors first!'
+         dotest basica-8 "${testcvs} -q update ." ''
+
+         # Test the -f option to ci
+         cd sdir/ssdir
+         dotest basica-8a0 "${testcvs} -q ci -m not-modified ssfile" ''
+         dotest basica-8a "${testcvs} -q ci -f -m force-it" \
+"$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: 1\.3; previous revision: 1\.2"
+         dotest basica-8a1 "${testcvs} -q ci -m bump-it -r 2.0" \
+"$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: 2\.0; previous revision: 1\.3"
+         dotest basica-8a1a "${testcvs} -q ci -m bump-it -r 2.9" \
+"${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: 2\.9; previous revision: 2\.0"
+         # Test string-based revion number increment rollover
+         dotest basica-8a1b "${testcvs} -q ci -m bump-it -f -r 2" \
+"${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: 2\.10; previous revision: 2\.9"
+         dotest basica-8a1c "${testcvs} -q ci -m bump-it -r 2.99" \
+"${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: 2\.99; previous revision: 2\.10"
+         # Test string-based revion number increment rollover
+         dotest basica-8a1d "${testcvs} -q ci -m bump-it -f -r 2" \
+"${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: 2\.100; previous revision: 2\.99"
+         dotest basica-8a1e "${testcvs} -q ci -m bump-it -r 2.1099" \
+"${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: 2\.1099; previous revision: 2\.100"
+         # Test string-based revion number increment rollover
+         dotest basica-8a1f "${testcvs} -q ci -m bump-it -f -r 2" \
+"${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: 2\.1100; previous revision: 2\.1099"
+         # -f should not be necessary, but it should be harmless.
+         # Also test the "-r 3" (rather than "-r 3.0") usage.
+         dotest basica-8a2 "${testcvs} -q ci -m bump-it -f -r 3" \
+"$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: 3\.1; previous revision: 2\.1100"
+
+         # Test using -r to create a branch
+         dotest_fail basica-8a3 "${testcvs} -q ci -m bogus -r 3.0.0" \
+"$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+$SPROG commit: $CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v: can't find branch point 3\.0
+$SPROG commit: could not check in ssfile"
+         dotest basica-8a4 "${testcvs} -q ci -m valid -r 3.1.2" \
+"$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: 3\.1\.2\.1; previous revision: 3\.1"
+         # now get rid of the sticky tag and go back to the trunk
+         dotest basica-8a5 "${testcvs} -q up -A ./" "[UP] ssfile"
+
+         cd ../..
+         dotest basica-8b "${testcvs} -q diff -r1.2 -r1.3"
+
+         dotest basica-8b1 "${testcvs} -q diff -r1.2 -r1.3 -C 3isacrowd"
+
+         # The .* here will normally be "No such file or directory",
+         # but if memory serves some systems (AIX?) have a different message.
+:        dotest_fail basica-9 \
+           "${testcvs} -q -d ${TESTDIR}/nonexist update" \
+"${SPROG}: cannot access cvs root ${TESTDIR}/nonexist: .*"
+         dotest_fail basica-9a \
+           "${testcvs} -q -d ${TESTDIR}/nonexist update" \
+"${CPROG} \[update aborted\]: ${TESTDIR}/nonexist/CVSROOT: .*"
+
+         dotest basica-10 "${testcvs} annotate" \
+'
+Annotations for sdir/ssdir/ssfile
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+1\.1          .'"$username8"' *[0-9a-zA-Z-]*.: ssfile
+1\.2          .'"$username8"' *[0-9a-zA-Z-]*.: ssfile line 2'
+
+         # Test resurrecting with strange revision numbers
+         cd sdir/ssdir
+         dotest basica-r1 "${testcvs} rm -f ssfile" \
+"${SPROG} remove: scheduling .ssfile. for removal
+${SPROG} remove: use .${SPROG} commit. to remove this file permanently"
+         dotest basica-r2 "${testcvs} -q ci -m remove" \
+"$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: delete; previous revision: 3\.1"
+         dotest basica-r3 "${testcvs} -q up -p -r 3.1 ./ssfile >ssfile" ""
+         dotest basica-r4 "${testcvs} add ssfile" \
+"${SPROG} add: Re-adding file .ssfile. after dead revision 3\.2\.
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest basica-r5 "${testcvs} -q ci -m resurrect" \
+"$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
+new revision: 3\.3; previous revision: 3\.2"
+         cd ../..
+
+         # As long as we have a file with a few revisions, test
+         # a few "cvs admin -o" invocations.
+         cd sdir/ssdir
+         dotest_fail basica-o1 "${testcvs} admin -o 1.2::1.2" \
+"${CPROG} admin: while processing more than one file:
+${CPROG} \[admin aborted\]: attempt to specify a numeric revision"
+         dotest basica-o2 "${testcvs} admin -o 1.2::1.2 ssfile" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+done"
+         dotest basica-o2a "${testcvs} admin -o 1.1::NOT_RESERVED ssfile" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+done"
+         dotest_fail basica-o2b "${testcvs} admin -o 1.1::NOT_EXIST ssfile" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+${SPROG} admin: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v: Revision NOT_EXIST doesn't exist.
+${SPROG} admin: RCS file for .ssfile. not modified\."
+         dotest basica-o3 "${testcvs} admin -o 1.2::1.3 ssfile" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+done"
+         dotest basica-o4 "${testcvs} admin -o 3.1:: ssfile" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+deleting revision 3\.3
+deleting revision 3\.2
+done"
+         dotest basica-o5 "${testcvs} admin -o ::1.1 ssfile" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+done"
+         dotest basica-o5a "${testcvs} -n admin -o 1.2::3.1 ssfile" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+deleting revision 2\.1100
+deleting revision 2\.1099
+deleting revision 2\.100
+deleting revision 2\.99
+deleting revision 2\.10
+deleting revision 2\.9
+deleting revision 2\.0
+deleting revision 1\.3
+done"
+         dotest basica-o6 "${testcvs} admin -o 1.2::3.1 ssfile" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+deleting revision 2\.1100
+deleting revision 2\.1099
+deleting revision 2\.100
+deleting revision 2\.99
+deleting revision 2\.10
+deleting revision 2\.9
+deleting revision 2\.0
+deleting revision 1\.3
+done"
+         dotest basica-o6a "${testcvs} admin -o 3.1.2: ssfile" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+deleting revision 3\.1\.2\.1
+done"
+         dotest basica-o7 "${testcvs} log -N ssfile" "
+RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
+Working file: ssfile
+head: 3\.1
+branch:
+locks: strict
+access list:
+keyword substitution: kv
+total revisions: 3;    selected revisions: 3
+description:
+----------------------------
+revision 3\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}0 -0;  commitid: ${commitid};
+bump-it
+----------------------------
+revision 1\.2
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}1 -0;  commitid: ${commitid};
+modify-it
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+add-it
+============================================================================="
+         dotest basica-o8 "${testcvs} -q update -p -r 1.1 ./ssfile" "ssfile"
+         cd ../..
+
+         cd ..
+
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         rm -r first-dir
+         ;;
+
+
+
+       basicb)
+         # More basic tests, including non-branch tags and co -d.
+         mkdir 1; cd 1
+         dotest basicb-0a "${testcvs} -q co -l ." ''
+         touch topfile
+         dotest basicb-0b "${testcvs} add topfile" \
+"${SPROG} add: scheduling file .topfile. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest basicb-0c "${testcvs} -q ci -m add-it topfile" \
+"$CVSROOT_DIRNAME/topfile,v  <--  topfile
+initial revision: 1\.1"
+         cd ..
+         rm -r 1
+         mkdir 2; cd 2
+         dotest basicb-0d "${testcvs} -q co -l ." "U topfile"
+         # Now test the ability to run checkout on an existing working
+         # directory without having it lose its mind.  I don't know
+         # whether this is tested elsewhere in sanity.sh.  A more elaborate
+         # test might also have modified files, make sure it works if
+         # the modules file was modified to add new directories to the
+         # module, and such.
+         dotest basicb-0d0 "${testcvs} -q co -l ." ""
+         mkdir first-dir
+         dotest basicb-0e "${testcvs} add first-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
+         cd ..
+         rm -r 2
+
+         dotest basicb-1 "${testcvs} -q co first-dir" ''
+
+         # The top-level CVS directory is not created by default.
+         # I'm leaving basicb-1a and basicb-1b untouched, mostly, in
+         # case we decide that the default should be reversed...
+
+         dotest_fail basicb-1a "test -d CVS" ''
+
+         dotest basicb-1c "cat first-dir/CVS/Repository" "first-dir"
+
+         cd first-dir
+         # Note that the name Emptydir is chosen to test that CVS just
+         # treats it like any other directory name.  It should be
+         # special only when it is directly in $CVSROOT/CVSROOT.
+         mkdir Emptydir sdir2
+         dotest basicb-2 "${testcvs} add Emptydir sdir2" \
+"Directory ${CVSROOT_DIRNAME}/first-dir/Emptydir put under version control
+Directory ${CVSROOT_DIRNAME}/first-dir/sdir2 put under version control"
+         cd Emptydir
+         echo sfile1 starts >sfile1
+         dotest basicb-2a10 "${testcvs} -n add sfile1" \
+"${SPROG} add: scheduling file .sfile1. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest basicb-2a11 "${testcvs} status sfile1" \
+"${SPROG} status: use \`${SPROG} add' to create an entry for \`sfile1'
+===================================================================
+File: sfile1                   Status: Unknown
+
+   Working revision:   No entry for sfile1
+   Repository revision:        No revision control file"
+         dotest basicb-3 "${testcvs} add sfile1" \
+"${SPROG} add: scheduling file .sfile1. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest basicb-3a1 "${testcvs} status sfile1" \
+"===================================================================
+File: sfile1                   Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+
+         cd ../sdir2
+         echo sfile2 starts >sfile2
+         dotest basicb-4 "${testcvs} add sfile2" \
+"${SPROG} add: scheduling file .sfile2. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest basicb-4a "${testcvs} -q ci CVS" \
+"${CPROG} commit: warning: directory CVS specified in argument
+${CPROG} commit: but CVS uses CVS for its own purposes; skipping CVS directory"
+         cd ..
+         dotest basicb-5 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/Emptydir/sfile1,v  <--  Emptydir/sfile1
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/sdir2/sfile2,v  <--  sdir2/sfile2
+initial revision: 1\.1"
+         echo sfile1 develops >Emptydir/sfile1
+         dotest basicb-6 "${testcvs} -q ci -m modify" \
+"$CVSROOT_DIRNAME/first-dir/Emptydir/sfile1,v  <--  Emptydir/sfile1
+new revision: 1\.2; previous revision: 1\.1"
+         dotest basicb-7 "${testcvs} -q tag release-1" 'T Emptydir/sfile1
+T sdir2/sfile2'
+         echo not in time for release-1 >sdir2/sfile2
+         dotest basicb-8 "${testcvs} -q ci -m modify-2" \
+"$CVSROOT_DIRNAME/first-dir/sdir2/sfile2,v  <--  sdir2/sfile2
+new revision: 1\.2; previous revision: 1\.1"
+         # See if CVS can correctly notice when an invalid numeric
+         # revision is specified.
+         # Commented out until we get around to fixing CVS
+:        dotest basicb-8a0 "${testcvs} diff -r 1.5 -r 1.7 sfile2" 'error msg'
+         cd ..
+
+         # Test that we recurse into the correct directory when checking
+         # for existing files, even if co -d is in use.
+         touch first-dir/extra
+         dotest basicb-cod-1 "${testcvs} -q co -d first-dir1 first-dir" \
+'U first-dir1/Emptydir/sfile1
+U first-dir1/sdir2/sfile2'
+         rm -r first-dir1
+
+         rm -r first-dir
+
+         # FIXME? basicb-9 used to check things out like this:
+         #   U newdir/Emptydir/sfile1
+         #   U newdir/sdir2/sfile2
+         # but that's difficult to do.  The whole "shorten" thing
+         # is pretty bogus, because it will break on things
+         # like "cvs co foo/bar baz/quux".  Unless there's some
+         # pretty detailed expansion and analysis of the command-line
+         # arguments, we shouldn't do "shorten" stuff at all.
+
+         dotest basicb-9 \
+"${testcvs} -q co -d newdir -r release-1 first-dir/Emptydir first-dir/sdir2" \
+'U newdir/first-dir/Emptydir/sfile1
+U newdir/first-dir/sdir2/sfile2'
+
+         # basicb-9a and basicb-9b: see note about basicb-1a
+
+         dotest_fail basicb-9a "test -d CVS" ''
+
+         dotest basicb-9c "cat newdir/CVS/Repository" "\."
+         dotest basicb-9d "cat newdir/first-dir/CVS/Repository" \
+"${CVSROOT_DIRNAME}/first-dir" \
+"first-dir"
+         dotest basicb-9e "cat newdir/first-dir/Emptydir/CVS/Repository" \
+"${CVSROOT_DIRNAME}/first-dir/Emptydir" \
+"first-dir/Emptydir"
+         dotest basicb-9f "cat newdir/first-dir/sdir2/CVS/Repository" \
+"${CVSROOT_DIRNAME}/first-dir/sdir2" \
+"first-dir/sdir2"
+
+         dotest basicb-10 "cat newdir/first-dir/Emptydir/sfile1 newdir/first-dir/sdir2/sfile2" \
+"sfile1 develops
+sfile2 starts"
+
+         rm -r newdir
+
+         # Hmm, this might be a case for CVSNULLREPOS, but CVS doesn't
+         # seem to deal with it...
+         if false; then
+         dotest basicb-11 "${testcvs} -q co -d sub1/sub2 first-dir" \
+"U sub1/sub2/Emptydir/sfile1
+U sub1/sub2/sdir2/sfile2"
+         cd sub1
+         dotest basicb-12 "${testcvs} -q update ./." ''
+         touch xx
+         dotest basicb-13 "${testcvs} add xx" fixme
+         cd ..
+         rm -r sub1
+         # to test: sub1/sub2/sub3
+         fi # end of tests commented out.
+
+         # Create a second directory.
+         mkdir 1
+         cd 1
+         dotest basicb-14 "${testcvs} -q co -l ." 'U topfile'
+         mkdir second-dir
+         dotest basicb-15 "${testcvs} add second-dir" \
+"Directory ${CVSROOT_DIRNAME}/second-dir put under version control"
+         cd second-dir
+         touch aa
+         dotest basicb-16 "${testcvs} add aa" \
+"${SPROG} add: scheduling file .aa. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest basicb-17 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/second-dir/aa,v  <--  aa
+initial revision: 1\.1"
+         cd ..
+
+         # Try to remove all revisions in a file.
+         dotest_fail basicb-o1 "${testcvs} admin -o1.1 topfile" \
+"RCS file: ${CVSROOT_DIRNAME}/topfile,v
+deleting revision 1\.1
+${SPROG} \[admin aborted\]: attempt to delete all revisions"
+         dotest basicb-o2 "${testcvs} -q update -d first-dir" \
+"U first-dir/Emptydir/sfile1
+U first-dir/sdir2/sfile2"
+         dotest_fail basicb-o3 \
+"${testcvs} admin -o1.1:1.2 first-dir/sdir2/sfile2" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir2/sfile2,v
+deleting revision 1\.2
+deleting revision 1\.1
+${SPROG} \[admin aborted\]: attempt to delete all revisions"
+         cd ..
+         rm -r 1
+
+         mkdir 1; cd 1
+         # Note that -H is an invalid option.
+         # I suspect that the choice between "illegal" and "invalid"
+         # depends on the user's environment variables, the phase
+         # of the moon (weirdness with optind), and who knows what else.
+         # I've been seeing "illegal"...
+         # And I switched it to "invalid". -DRP
+         # POSIX 1003.2 specifies the format should be 'illegal option'
+         # many other folks are still using the older 'invalid option'
+         # lib/getopt.c will use POSIX when __posixly_correct
+         # otherwise the other, so accept both of them. -- mdb
+         # Added optional single quotes. -- mirabilos
+         # The above is actually untrue, POSIX only documents some older
+         # texts that can be used and explicitly leaves open the format
+         # of these messages. Also, GNU getopt is broken and does not
+         # use __progname in the first place. *sigh* -- mirabilos
+         dotest_fail basicb-21 "${testcvs} -q admin -H" \
+"admin: invalid option -- '*H'*
+${CPROG} \[admin aborted\]: specify ${CPROG} -H admin for usage information" \
+"cvs: illegal option -- '*H'*
+${CPROG} \[admin aborted\]: specify ${CPROG} -H admin for usage information"
+         cd ..
+         rmdir 1
+
+         if $keep; then
+           echo Keeping ${TESTDIR} and exiting due to --keep
+           exit 0
+         fi
+
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir \
+                            $CVSROOT_DIRNAME/second-dir
+         modify_repo rm -f $CVSROOT_DIRNAME/topfile,v
+         ;;
+
+
+
+       basicc)
+         # More tests of basic/miscellaneous functionality.
+         mkdir 1; cd 1
+         dotest_fail basicc-1 "$testcvs diff" \
+"$CPROG diff: in directory \.:
+$CPROG \[diff aborted\]: there is no version here; run .$CPROG checkout. first"
+         dotest basicc-2 "$testcvs -q co -l ."
+         mkdir first-dir second-dir
+         dotest basicc-3 "${testcvs} add first-dir second-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control
+Directory ${CVSROOT_DIRNAME}/second-dir put under version control"
+         # Old versions of CVS often didn't create this top-level CVS
+         # directory in the first place.  I think that maybe the only
+         # way to get it to work currently is to let CVS create it,
+         # and then blow it away (don't complain if it does not
+         # exist).  But that is perfectly valid; people who are used
+         # to the old behavior especially may be interested.
+         # FIXME: this test is intended for the TopLevelAdmin=yes case;
+         # should adjust/move it accordingly.
+         rm -rf CVS
+         dotest basicc-4 "echo *" "first-dir second-dir"
+         dotest basicc-5 "${testcvs} update" \
+"${SPROG} update: Updating first-dir
+${SPROG} update: Updating second-dir" \
+"${SPROG} update: Updating \.
+${SPROG} update: Updating first-dir
+${SPROG} update: Updating second-dir"
+
+         cd first-dir
+         dotest basicc-6 "${testcvs} release -d" ""
+         dotest basicc-7 "test -d ../first-dir" ""
+         # The Linux 2.2 kernel lets you delete ".".  That's OK either way,
+         # the point is that CVS must not mess with anything *outside* "."
+         # the way that CVS 1.10 and older tried to.
+         dotest basicc-8 "${testcvs} -Q release -d ." \
+"" "${CPROG} release: deletion of directory \. failed: .*"
+         dotest basicc-9 "test -d ../second-dir" ""
+         # For CVS to make a syntactic check for "." wouldn't suffice.
+         # On Linux 2.2 systems, the cwd may be gone, so we recreate it
+          # to allow basicc-11 to actually happen 
+         if test ! -d ../first-dir; then
+           # Apparently `cd ..' doesn't work with Linux 2.2 & Bash 2.05b.
+           cd $TESTDIR/1
+           mkdir ./first-dir
+            cd ./first-dir
+         fi
+         dotest basicc-11 "${testcvs} -Q release -d ./." \
+"" "${CPROG} release: deletion of directory \./\. failed: .*"
+         dotest basicc-11a "test -d ../second-dir" ""
+
+         cd ../..
+
+         mkdir 2; cd 2
+         dotest basicc-12 "${testcvs} -Q co ." ""
+         # actual entries can be in either Entries or Entries.log, do
+         # an update to get them consolidated into Entries
+         dotest basicc-12a "${testcvs} -Q up" ""
+         dotest basicc-12b "cat CVS/Entries" \
+"D/CVSROOT////
+D/first-dir////
+D/second-dir////"
+         dotest basicc-13 "echo *" "CVS CVSROOT first-dir second-dir"
+         dotest basicc-14 "${testcvs} -Q release first-dir second-dir" ""
+         # a normal release shouldn't affect the Entries file
+         dotest basicc-14b "cat CVS/Entries" \
+"D/CVSROOT////
+D/first-dir////
+D/second-dir////"
+         # FIXCVS: but release -d probably should
+         dotest basicc-15 "${testcvs} -Q release -d first-dir second-dir" ""
+         dotest basicc-16 "echo *" "CVS CVSROOT"
+         dotest basicc-17 "cat CVS/Entries" \
+"D/CVSROOT////
+D/first-dir////
+D/second-dir////"
+         # FIXCVS: if not, update should notice the missing directories
+         # and update Entries accordingly
+         dotest basicc-18 "${testcvs} -Q up" ""
+         dotest basicc-19 "cat CVS/Entries" \
+"D/CVSROOT////
+D/first-dir////
+D/second-dir////"
+
+         cd ..
+         rm -r 1 2
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir \
+                            $CVSROOT_DIRNAME/second-dir
+         ;;
+
+
+
+       basic1)
+         # first dive - add a files, first singly, then in a group.
+         modify_repo mkdir $CVSROOT_DIRNAME/first-dir
+         mkdir basic1; cd basic1
+         # check out an empty directory
+         dotest basic1-1 "${testcvs} -q co first-dir" ''
+
+         cd first-dir
+         echo file2 >file2
+         echo file3 >file3
+         echo file4 >file4
+         echo file5 >file5
+
+         dotest basic1-14-add-add "${testcvs} add file2 file3 file4 file5" \
+"${SPROG} add: scheduling file \`file2' for addition
+${SPROG} add: scheduling file \`file3' for addition
+${SPROG} add: scheduling file \`file4' for addition
+${SPROG} add: scheduling file \`file5' for addition
+${SPROG} add: use .${SPROG} commit. to add these files permanently"
+         dotest basic1-15-add-add \
+"${testcvs} -q update file2 file3 file4 file5" \
+"A file2
+A file3
+A file4
+A file5"
+         dotest basic1-16-add-add "${testcvs} -q update" \
+"A file2
+A file3
+A file4
+A file5"
+         dotest basic1-17-add-add "${testcvs} -q status" \
+"===================================================================
+File: file2                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file3                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file4                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file5                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+         dotest basic1-18-add-add "${testcvs} -q log" \
+"${SPROG} log: file2 has been added, but not committed
+${SPROG} log: file3 has been added, but not committed
+${SPROG} log: file4 has been added, but not committed
+${SPROG} log: file5 has been added, but not committed"
+         cd ..
+         dotest basic1-21-add-add "${testcvs} -q update" \
+"A first-dir/file2
+A first-dir/file3
+A first-dir/file4
+A first-dir/file5"
+         # FIXCVS?  Shouldn't this read first-dir/file2 instead of file2?
+         dotest basic1-22-add-add "${testcvs} log first-dir" \
+"${SPROG} log: Logging first-dir
+${SPROG} log: file2 has been added, but not committed
+${SPROG} log: file3 has been added, but not committed
+${SPROG} log: file4 has been added, but not committed
+${SPROG} log: file5 has been added, but not committed"
+         dotest basic1-23-add-add "${testcvs} status first-dir" \
+"${SPROG} status: Examining first-dir
+===================================================================
+File: file2                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file3                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file4                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file5                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+         dotest basic1-24-add-add "${testcvs} update first-dir" \
+"${SPROG} update: Updating first-dir
+A first-dir/file2
+A first-dir/file3
+A first-dir/file4
+A first-dir/file5"
+         dotest basic1-27-add-add "${testcvs} co first-dir" \
+"${SPROG} checkout: Updating first-dir
+A first-dir/file2
+A first-dir/file3
+A first-dir/file4
+A first-dir/file5"
+         cd first-dir
+         dotest basic1-14-add-ci \
+"$testcvs commit -m test file2 file3 file4 file5" \
+"$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file3,v  <--  file3
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file5,v  <--  file5
+initial revision: 1\.1"
+         dotest basic1-15-add-ci \
+"${testcvs} -q update file2 file3 file4 file5" ''
+         dotest basic1-16-add-ci "${testcvs} -q update" ''
+         dotest basic1-17-add-ci "${testcvs} -q status" \
+"===================================================================
+File: file2                    Status: Up-to-date
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file2,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file3                    Status: Up-to-date
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file3,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file4                    Status: Up-to-date
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file4,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file5                    Status: Up-to-date
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file5,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+         # The "log" tests and friends probably already test the output 
+         # from log quite adequately.
+         # Note: using dotest fails here.  It seems to be related
+         # to the output being sufficiently large (Red Hat 4.1).
+         # dotest basic1-18-add-ci "${testcvs} log" "${DOTSTAR}"
+         if ${testcvs} -q log >>${LOGFILE}; then
+           pass basic1-18-add-ci
+         else
+           pass basic1-18-add-ci
+         fi
+         cd ..
+         dotest basic1-21-add-ci "${testcvs} -q update" ''
+         # See test basic1-18-add-ci for explanation of non-use of dotest.
+         if ${testcvs} -q log first-dir >>${LOGFILE}; then
+           pass basic1-22-add-ci
+         else
+           pass basic1-22-add-ci
+         fi
+         # At least for the moment I am going to consider 17-add-ci
+         # an adequate test of the output here.
+         # See test basic1-18-add-ci for explanation of non-use of dotest.
+         if ${testcvs} -q status first-dir >>${LOGFILE}; then
+           pass basic1-23-add-ci
+         else
+           pass basic1-23-add-ci
+         fi
+         dotest basic1-24-add-ci "${testcvs} -q update first-dir" ''
+         dotest basic1-27-add-ci "${testcvs} -q co first-dir" ''
+
+         cd first-dir
+         rm file2 file3 file4 file5
+         dotest basic1-14-rm-rm "${testcvs} rm file2 file3 file4 file5" \
+"${SPROG} remove: scheduling .file2. for removal
+${SPROG} remove: scheduling .file3. for removal
+${SPROG} remove: scheduling .file4. for removal
+${SPROG} remove: scheduling .file5. for removal
+${SPROG} remove: use .${SPROG} commit. to remove these files permanently"
+         # 15-rm-rm was commented out.  Why?
+         dotest basic1-15-rm-rm \
+"${testcvs} -q update file2 file3 file4 file5" \
+"R file2
+R file3
+R file4
+R file5"
+         dotest basic1-16-rm-rm "${testcvs} -q update" \
+"R file2
+R file3
+R file4
+R file5"
+         dotest basic1-17-rm-rm "${testcvs} -q status" \
+"===================================================================
+File: no file file2            Status: Locally Removed
+
+   Working revision:   -1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file2,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: no file file3            Status: Locally Removed
+
+   Working revision:   -1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file3,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: no file file4            Status: Locally Removed
+
+   Working revision:   -1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file4,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: no file file5            Status: Locally Removed
+
+   Working revision:   -1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file5,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+         # Would be nice to test that real logs appear (with dead state
+         # and all), either here or someplace like log2 tests.
+         if ${testcvs} -q log >>${LOGFILE}; then
+           pass basic1-18-rm-rm
+         else
+           fail basic1-18-rm-rm
+         fi
+         cd ..
+         dotest basic1-21-rm-rm "${testcvs} -q update" \
+"R first-dir/file2
+R first-dir/file3
+R first-dir/file4
+R first-dir/file5"
+         if ${testcvs} -q log first-dir >>${LOGFILE}; then
+           pass basic1-22-rm-rm
+         else
+           fail basic1-22-rm-rm
+         fi
+         if ${testcvs} -q status first-dir >>${LOGFILE}; then
+           pass basic1-23-rm-rm
+         else
+           fail basic1-23-rm-rm
+         fi
+         dotest basic1-24-rm-rm "${testcvs} -q update first-dir" \
+"R first-dir/file2
+R first-dir/file3
+R first-dir/file4
+R first-dir/file5"
+         dotest basic1-27-rm-rm "${testcvs} -q co first-dir" \
+"R first-dir/file2
+R first-dir/file3
+R first-dir/file4
+R first-dir/file5"
+         cd first-dir
+         dotest basic1-14-rm-ci "${testcvs} -q commit -m test" \
+"$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+new revision: delete; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file3,v  <--  file3
+new revision: delete; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+new revision: delete; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file5,v  <--  file5
+new revision: delete; previous revision: 1\.1"
+         dotest basic1-15-rm-ci \
+"${testcvs} -q update file2 file3 file4 file5" ''
+         dotest basic1-16-rm-ci "${testcvs} -q update" ''
+         dotest basic1-17-rm-ci "${testcvs} -q status" ''
+         # Would be nice to test that real logs appear (with dead state
+         # and all), either here or someplace like log2 tests.
+         if ${testcvs} -q log >>${LOGFILE}; then
+           pass basic1-18-rm-ci
+         else
+           fail basic1-18-rm-ci
+         fi
+         cd ..
+         dotest basic1-21-rm-ci "${testcvs} -q update" ''
+         if ${testcvs} -q log first-dir >>${LOGFILE}; then
+           pass basic1-22-rm-ci
+         else
+           fail basic1-22-rm-ci
+         fi
+         if ${testcvs} -q status first-dir >>${LOGFILE}; then
+           pass basic1-23-rm-ci
+         else
+           fail basic1-23-rm-ci
+         fi
+         dotest basic1-24-rm-ci "${testcvs} -q update first-dir" ''
+         dotest basic1-27-rm-ci "${testcvs} -q co first-dir" ''
+         cd first-dir
+         # All the files are removed, so nothing gets tagged.
+         dotest basic1-28 "${testcvs} -q tag first-dive" ''
+         cd ..
+         cd ..
+
+         if $keep; then
+           echo Keeping ${TESTDIR} and exiting due to --keep
+           exit 0
+         fi
+
+         rm -r basic1
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       deep)
+         # Test the ability to operate on directories nested rather deeply.
+         modify_repo mkdir $CVSROOT_DIRNAME/first-dir
+         dotest deep-1 "${testcvs} -q co first-dir" ''
+         cd first-dir
+         for i in dir1 dir2 dir3 dir4 dir5 dir6 dir7 dir8; do
+           mkdir $i
+           dotest deep-2-$i "${testcvs} add $i" \
+"Directory ${CVSROOT_DIRNAME}/first-dir/dir1[/dir0-9]* put under version control"
+           cd $i
+           echo file1 >file1
+           dotest deep-3-$i "${testcvs} add file1" \
+"${SPROG}"' add: scheduling file `file1'\'' for addition
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+         done
+         cd ../../../../../../../../..
+         dotest_lit deep-4 "$testcvs -q ci -m add-them first-dir" <<HERE
+$CVSROOT_DIRNAME/first-dir/dir1/file1,v  <--  first-dir/dir1/file1
+initial revision: 1.1
+$CVSROOT_DIRNAME/first-dir/dir1/dir2/file1,v  <--  first-dir/dir1/dir2/file1
+initial revision: 1.1
+$CVSROOT_DIRNAME/first-dir/dir1/dir2/dir3/file1,v  <--  first-dir/dir1/dir2/dir3/file1
+initial revision: 1.1
+$CVSROOT_DIRNAME/first-dir/dir1/dir2/dir3/dir4/file1,v  <--  first-dir/dir1/dir2/dir3/dir4/file1
+initial revision: 1.1
+$CVSROOT_DIRNAME/first-dir/dir1/dir2/dir3/dir4/dir5/file1,v  <--  first-dir/dir1/dir2/dir3/dir4/dir5/file1
+initial revision: 1.1
+$CVSROOT_DIRNAME/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/file1,v  <--  first-dir/dir1/dir2/dir3/dir4/dir5/dir6/file1
+initial revision: 1.1
+$CVSROOT_DIRNAME/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/file1,v  <--  first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/file1
+initial revision: 1.1
+$CVSROOT_DIRNAME/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/file1,v  <--  first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/file1
+initial revision: 1.1
+HERE
+
+         cd first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8
+         rm file1
+         dotest deep-4a0 "$testcvs rm file1" \
+"$SPROG remove: scheduling .file1. for removal
+$SPROG remove: use .$SPROG commit. to remove this file permanently"
+         dotest deep-4a1 "$testcvs -q ci -m rm-it" \
+"$CVSROOT_DIRNAME/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/file1,v  <--  file1
+new revision: delete; previous revision: 1\.1"
+         cd ../../..
+         dotest deep-4a2 "${testcvs} -q update -P dir6/dir7" ''
+         # Should be using "test -e", but it's not portable enough -
+         # Solaris 2.5 does not have it.
+         dotest_fail deep-4a3 "test -d dir6/dir7/dir8" ''
+
+         # Test that if we remove the working directory, CVS does not
+         # recreate it.  (I realize that this behavior is what the
+         # users expect, but in the longer run we might want to
+         # re-think it.  The corresponding behavior for a file is that
+         # CVS *will* recreate it, and we might want to make it so
+         # that "cvs release -d" is the way to delete the directory
+         # and have it stay gone -kingdon, Oct1996).
+         rm -r dir6
+         dotest deep-4b0a "${testcvs} -q diff"
+         dotest deep-4b0b "${testcvs} -q ci"
+         dotest deep-4b1 "${testcvs} -q update"
+         dotest deep-4b2 "${testcvs} -q update -d -P" \
+'U dir6/file1
+U dir6/dir7/file1'
+
+         # Test what happens if one uses -P when there are files removed
+         # but not committed.
+         cd dir6/dir7
+         dotest deep-rm1 "${testcvs} rm -f file1" \
+"${SPROG} remove: scheduling .file1. for removal
+${SPROG} remove: use .${SPROG} commit. to remove this file permanently"
+         cd ..
+         dotest deep-rm2 "${testcvs} -q update -d -P" 'R dir7/file1'
+         dotest deep-rm3 "test -d dir7" ''
+         dotest deep-rm4 "$testcvs -q ci -m rm-it" \
+"$CVSROOT_DIRNAME/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/file1,v  <--  dir7/file1
+new revision: delete; previous revision: 1\.1"
+         dotest deep-rm5 "${testcvs} -q update -d -P" ''
+         dotest_fail deep-rm6 "test -d dir7" ''
+
+         # Test rm -f -R.
+         cd ../..
+         dotest deep-rm7 "${testcvs} rm -f -R dir5" \
+"${SPROG} remove: Removing dir5
+${SPROG} remove: scheduling .dir5/file1. for removal
+${SPROG} remove: Removing dir5/dir6
+${SPROG} remove: scheduling .dir5/dir6/file1. for removal
+${SPROG} remove: use .${SPROG} commit. to remove these files permanently"
+         dotest deep-rm8 "${testcvs} -q ci -m rm-it" \
+"$CVSROOT_DIRNAME/first-dir/dir1/dir2/dir3/dir4/dir5/file1,v  <--  dir5/file1
+new revision: delete; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/file1,v  <--  dir5/dir6/file1
+new revision: delete; previous revision: 1\.1"
+         dotest deep-rm9 "${testcvs} -q update -d -P" ''
+         dotest_fail deep-rm10 "test -d dir5"
+
+         cd ../../../../..
+
+         if echo "yes" | $testcvs release -d first-dir >>$LOGFILE 2>&1; then
+           pass deep-5
+         else
+           fail deep-5
+         fi
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       basic2)
+               # Test rtag, import, history, various miscellaneous operations
+
+               # NOTE: this section has reached the size and
+               # complexity where it is getting to be a good idea to
+               # add new tests to a new section rather than
+               # continuing to piggyback them onto the tests here.
+
+               # First empty the history file
+               modify_repo rm -rf $CVSROOT_DIRNAME/CVSROOT/history
+               modify_repo touch $CVSROOT_DIRNAME/CVSROOT/history
+
+               modify_repo mkdir $CVSROOT_DIRNAME/first-dir
+               dotest basic2-1 "$testcvs -q co first-dir"
+               for i in first-dir dir1 dir2 ; do
+                       if test ! -d $i ; then
+                               mkdir $i
+                               dotest basic2-2-$i "${testcvs} add $i" \
+"Directory ${CVSROOT_DIRNAME}/.*/$i put under version control"
+                       fi
+
+                       cd $i
+
+                       for j in file6 file7; do
+                               echo $j > $j
+                       done
+
+                       dotest basic2-3-$i "${testcvs} add file6 file7" \
+"${SPROG} add: scheduling file .file6. for addition
+${SPROG} add: scheduling file .file7. for addition
+${SPROG} add: use .${SPROG} commit. to add these files permanently"
+
+               done
+               cd ../../..
+               dotest basic2-4 "${testcvs} update first-dir" \
+"${SPROG} update: Updating first-dir
+A first-dir/file6
+A first-dir/file7
+${SPROG} update: Updating first-dir/dir1
+A first-dir/dir1/file6
+A first-dir/dir1/file7
+${SPROG} update: Updating first-dir/dir1/dir2
+A first-dir/dir1/dir2/file6
+A first-dir/dir1/dir2/file7"
+
+               # fixme: doesn't work right for added files.
+               dotest basic2-5 "${testcvs} log first-dir" \
+"${SPROG} log: Logging first-dir
+${SPROG} log: file6 has been added, but not committed
+${SPROG} log: file7 has been added, but not committed
+${SPROG} log: Logging first-dir/dir1
+${SPROG} log: file6 has been added, but not committed
+${SPROG} log: file7 has been added, but not committed
+${SPROG} log: Logging first-dir/dir1/dir2
+${SPROG} log: file6 has been added, but not committed
+${SPROG} log: file7 has been added, but not committed"
+
+               dotest basic2-6 "${testcvs} status first-dir" \
+"${SPROG} status: Examining first-dir
+===================================================================
+File: file6                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file7                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+${SPROG} status: Examining first-dir/dir1
+===================================================================
+File: file6                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file7                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+${SPROG} status: Examining first-dir/dir1/dir2
+===================================================================
+File: file6                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file7                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+
+# XXX why is this commented out???
+#              if ${CVS} diff -u first-dir   >> ${LOGFILE} || test $? = 1 ; then
+#                  pass 34
+#              else
+#                  fail 34
+#              fi
+
+               dotest basic2-8 "${testcvs} -q ci -m 'second dive' first-dir" \
+"$CVSROOT_DIRNAME/first-dir/file6,v  <--  first-dir/file6
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file7,v  <--  first-dir/file7
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/dir1/file6,v  <--  first-dir/dir1/file6
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/dir1/file7,v  <--  first-dir/dir1/file7
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/dir1/dir2/file6,v  <--  first-dir/dir1/dir2/file6
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/dir1/dir2/file7,v  <--  first-dir/dir1/dir2/file7
+initial revision: 1\.1"
+
+               dotest basic2-9 "${testcvs} tag second-dive first-dir" \
+"${SPROG} tag: Tagging first-dir
+T first-dir/file6
+T first-dir/file7
+${SPROG} tag: Tagging first-dir/dir1
+T first-dir/dir1/file6
+T first-dir/dir1/file7
+${SPROG} tag: Tagging first-dir/dir1/dir2
+T first-dir/dir1/dir2/file6
+T first-dir/dir1/dir2/file7"
+
+               # third dive - in bunch o' directories, add bunch o' files,
+               # delete some, change some.
+
+               for i in first-dir dir1 dir2 ; do
+                       cd $i
+
+                       # modify a file
+                       echo file6 >>file6
+
+                       # delete a file
+                       rm file7
+
+                       dotest basic2-10-$i "${testcvs} rm file7" \
+"${SPROG} remove: scheduling .file7. for removal
+${SPROG} remove: use .${SPROG} commit. to remove this file permanently"
+
+                       # and add a new file
+                       echo file14 >file14
+
+                       dotest basic2-11-$i "${testcvs} add file14" \
+"${SPROG} add: scheduling file .file14. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+               done
+
+               cd ../../..
+               dotest basic2-12 "${testcvs} update first-dir" \
+"${SPROG} update: Updating first-dir
+A first-dir/file14
+M first-dir/file6
+R first-dir/file7
+${SPROG} update: Updating first-dir/dir1
+A first-dir/dir1/file14
+M first-dir/dir1/file6
+R first-dir/dir1/file7
+${SPROG} update: Updating first-dir/dir1/dir2
+A first-dir/dir1/dir2/file14
+M first-dir/dir1/dir2/file6
+R first-dir/dir1/dir2/file7"
+
+               # FIXME: doesn't work right for added files
+               dotest basic2-13 "${testcvs} log first-dir" \
+"${SPROG} log: Logging first-dir
+${SPROG} log: file14 has been added, but not committed
+
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file6,v
+Working file: first-dir/file6
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+       second-dive: 1\.1
+keyword substitution: kv
+total revisions: 1;    selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+second dive
+=============================================================================
+
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file7,v
+Working file: first-dir/file7
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+       second-dive: 1\.1
+keyword substitution: kv
+total revisions: 1;    selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+second dive
+=============================================================================
+${SPROG} log: Logging first-dir/dir1
+${SPROG} log: file14 has been added, but not committed
+
+RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/file6,v
+Working file: first-dir/dir1/file6
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+       second-dive: 1\.1
+keyword substitution: kv
+total revisions: 1;    selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+second dive
+=============================================================================
+
+RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/file7,v
+Working file: first-dir/dir1/file7
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+       second-dive: 1\.1
+keyword substitution: kv
+total revisions: 1;    selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+second dive
+=============================================================================
+${SPROG} log: Logging first-dir/dir1/dir2
+${SPROG} log: file14 has been added, but not committed
+
+RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file6,v
+Working file: first-dir/dir1/dir2/file6
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+       second-dive: 1\.1
+keyword substitution: kv
+total revisions: 1;    selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+second dive
+=============================================================================
+
+RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file7,v
+Working file: first-dir/dir1/dir2/file7
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+       second-dive: 1\.1
+keyword substitution: kv
+total revisions: 1;    selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+second dive
+============================================================================="
+
+               dotest basic2-14 "${testcvs} status first-dir" \
+"${SPROG} status: Examining first-dir
+===================================================================
+File: file14                   Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file6                    Status: Locally Modified
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file6,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: no file file7            Status: Locally Removed
+
+   Working revision:   -1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file7,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+${SPROG} status: Examining first-dir/dir1
+===================================================================
+File: file14                   Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file6                    Status: Locally Modified
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/dir1/file6,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: no file file7            Status: Locally Removed
+
+   Working revision:   -1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/dir1/file7,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+${SPROG} status: Examining first-dir/dir1/dir2
+===================================================================
+File: file14                   Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file6                    Status: Locally Modified
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file6,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: no file file7            Status: Locally Removed
+
+   Working revision:   -1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file7,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)${DOTSTAR}"
+
+# XXX why is this commented out?
+#              if ${CVS} diff -u first-dir  >> ${LOGFILE} || test $? = 1 ; then
+#                  pass 42
+#              else
+#                  fail 42
+#              fi
+
+               dotest basic2-16 "${testcvs} ci -m 'third dive' first-dir" \
+"${CPROG} commit: Examining first-dir
+${CPROG} commit: Examining first-dir/dir1
+${CPROG} commit: Examining first-dir/dir1/dir2
+${CVSROOT_DIRNAME}/first-dir/file14,v  <--  first-dir/file14
+initial revision: 1\.1
+${CVSROOT_DIRNAME}/first-dir/file6,v  <--  first-dir/file6
+new revision: 1\.2; previous revision: 1\.1
+${CVSROOT_DIRNAME}/first-dir/file7,v  <--  first-dir/file7
+new revision: delete; previous revision: 1\.1
+${CVSROOT_DIRNAME}/first-dir/dir1/file14,v  <--  first-dir/dir1/file14
+initial revision: 1\.1
+${CVSROOT_DIRNAME}/first-dir/dir1/file6,v  <--  first-dir/dir1/file6
+new revision: 1\.2; previous revision: 1\.1
+${CVSROOT_DIRNAME}/first-dir/dir1/file7,v  <--  first-dir/dir1/file7
+new revision: delete; previous revision: 1\.1
+${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file14,v  <--  first-dir/dir1/dir2/file14
+initial revision: 1\.1
+${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file6,v  <--  first-dir/dir1/dir2/file6
+new revision: 1\.2; previous revision: 1\.1
+${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file7,v  <--  first-dir/dir1/dir2/file7
+new revision: delete; previous revision: 1\.1"
+               dotest basic2-17 "${testcvs} -q update first-dir" ''
+
+               dotest basic2-18 "${testcvs} tag third-dive first-dir" \
+"${SPROG} tag: Tagging first-dir
+T first-dir/file14
+T first-dir/file6
+${SPROG} tag: Tagging first-dir/dir1
+T first-dir/dir1/file14
+T first-dir/dir1/file6
+${SPROG} tag: Tagging first-dir/dir1/dir2
+T first-dir/dir1/dir2/file14
+T first-dir/dir1/dir2/file6"
+
+               dotest basic2-19 "echo yes | ${testcvs} release -d first-dir" \
+"You have \[0\] altered files in this repository\.
+Are you sure you want to release (and delete) directory .first-dir.: "
+
+               # end of third dive
+               dotest_fail basic2-20 "test -d first-dir" ""
+
+               # now try some rtags
+
+               # rtag HEADS
+               dotest basic2-21 "${testcvs} rtag rtagged-by-head first-dir" \
+"${SPROG} rtag: Tagging first-dir
+${SPROG} rtag: Tagging first-dir/dir1
+${SPROG} rtag: Tagging first-dir/dir1/dir2"
+
+               dotest basic2-21b "${testcvs} co -p -r rtagged-by-head first-dir/file6" \
+"===================================================================
+Checking out first-dir/file6
+RCS:  $CVSROOT_DIRNAME/first-dir/file6,v
+VERS: 1\.2
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+file6
+file6"
+               # see what happens when val-tags is removed
+               modify_repo mv $CVSROOT_DIRNAME/CVSROOT/val-tags \
+                               $CVSROOT_DIRNAME/CVSROOT/val-tags.save
+               # The output for this used to be something like:
+               # "${SPROG} checkout: cannot open CVS/Entries for reading: No such file or directory
+               # ${SPROG} \[checkout aborted\]: no such tag \`rtagged-by-head'"
+
+               dotest basic2-21c \
+"${testcvs} co -p -r rtagged-by-head first-dir/file6" \
+"===================================================================
+Checking out first-dir/file6
+RCS:  $CVSROOT_DIRNAME/first-dir/file6,v
+VERS: 1\.2
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+file6
+file6"
+               modify_repo mv $CVSROOT_DIRNAME/CVSROOT/val-tags.save \
+                               $CVSROOT_DIRNAME/CVSROOT/val-tags
+
+               # tag by tag
+               dotest basic2-22 "${testcvs} rtag -r rtagged-by-head rtagged-by-tag first-dir" \
+"${SPROG} rtag: Tagging first-dir
+${SPROG} rtag: Tagging first-dir/dir1
+${SPROG} rtag: Tagging first-dir/dir1/dir2"
+
+               # tag by revision
+               dotest basic2-23 "${testcvs} rtag -r1.1 rtagged-by-revision first-dir" \
+"${SPROG} rtag: Tagging first-dir
+${SPROG} rtag: Tagging first-dir/dir1
+${SPROG} rtag: Tagging first-dir/dir1/dir2"
+
+               # rdiff by revision
+               dotest basic2-24 "${testcvs} rdiff -r1.1 -rrtagged-by-head first-dir" \
+"${SPROG} rdiff: Diffing first-dir
+Index: first-dir/file6
+diff -c first-dir/file6:1\.1 first-dir/file6:1\.2
+\*\*\* first-dir/file6:1\.1    ${DATE}
+--- first-dir/file6    ${DATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+--- 1,2 ----
+  file6
+${PLUS} file6
+Index: first-dir/file7
+diff -c first-dir/file7:1\.1 first-dir/file7:removed
+\*\*\* first-dir/file7:1.1     ${DATE}
+--- first-dir/file7    ${DATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+- file7
+--- 0 ----
+${SPROG} rdiff: Diffing first-dir/dir1
+Index: first-dir/dir1/file6
+diff -c first-dir/dir1/file6:1\.1 first-dir/dir1/file6:1\.2
+\*\*\* first-dir/dir1/file6:1\.1       ${DATE}
+--- first-dir/dir1/file6       ${DATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+--- 1,2 ----
+  file6
+${PLUS} file6
+Index: first-dir/dir1/file7
+diff -c first-dir/dir1/file7:1\.1 first-dir/dir1/file7:removed
+\*\*\* first-dir/dir1/file7:1\.1       ${DATE}
+--- first-dir/dir1/file7       ${DATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+- file7
+--- 0 ----
+${SPROG} rdiff: Diffing first-dir/dir1/dir2
+Index: first-dir/dir1/dir2/file6
+diff -c first-dir/dir1/dir2/file6:1\.1 first-dir/dir1/dir2/file6:1\.2
+\*\*\* first-dir/dir1/dir2/file6:1\.1  ${DATE}
+--- first-dir/dir1/dir2/file6  ${DATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+--- 1,2 ----
+  file6
+${PLUS} file6
+Index: first-dir/dir1/dir2/file7
+diff -c first-dir/dir1/dir2/file7:1\.1 first-dir/dir1/dir2/file7:removed
+\*\*\* first-dir/dir1/dir2/file7:1\.1  ${DATE}
+--- first-dir/dir1/dir2/file7  ${DATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+- file7
+--- 0 ----"
+               dotest basic2-24a "${testcvs} rdiff -l -r1.1 -rrtagged-by-head first-dir" \
+"${SPROG} rdiff: Diffing first-dir
+Index: first-dir/file6
+diff -c first-dir/file6:1\.1 first-dir/file6:1\.2
+\*\*\* first-dir/file6:1\.1    ${DATE}
+--- first-dir/file6    ${DATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+--- 1,2 ----
+  file6
+${PLUS} file6
+Index: first-dir/file7
+diff -c first-dir/file7:1\.1 first-dir/file7:removed
+\*\*\* first-dir/file7:1.1     ${DATE}
+--- first-dir/file7    ${DATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+- file7
+--- 0 ----"
+               # now export by rtagged-by-head and rtagged-by-tag and compare.
+               dotest basic2-25 "${testcvs} export -r rtagged-by-head -d 1dir first-dir" \
+"${SPROG} export: Updating 1dir
+U 1dir/file14
+U 1dir/file6
+${SPROG} export: Updating 1dir/dir1
+U 1dir/dir1/file14
+U 1dir/dir1/file6
+${SPROG} export: Updating 1dir/dir1/dir2
+U 1dir/dir1/dir2/file14
+U 1dir/dir1/dir2/file6"
+               dotest_fail basic2-25a "test -d 1dir/CVS"
+               dotest_fail basic2-25b "test -d 1dir/dir1/CVS"
+               dotest_fail basic2-25c "test -d 1dir/dir1/dir2/CVS"
+
+               dotest basic2-26 "${testcvs} export -r rtagged-by-tag first-dir" \
+"${SPROG} export: Updating first-dir
+U first-dir/file14
+U first-dir/file6
+${SPROG} export: Updating first-dir/dir1
+U first-dir/dir1/file14
+U first-dir/dir1/file6
+${SPROG} export: Updating first-dir/dir1/dir2
+U first-dir/dir1/dir2/file14
+U first-dir/dir1/dir2/file6"
+               dotest_fail basic2-26a "test -d first-dir/CVS"
+               dotest_fail basic2-26b "test -d first-dir/dir1/CVS"
+               dotest_fail basic2-26c "test -d first-dir/dir1/dir2/CVS"
+
+               dotest basic2-27 "directory_cmp 1dir first-dir"
+               rm -r 1dir first-dir
+
+               # checkout by revision vs export by rtagged-by-revision and compare.
+               mkdir export-dir
+               dotest basic2-28 "${testcvs} export -rrtagged-by-revision -d export-dir first-dir" \
+"${SPROG} export: Updating export-dir
+U export-dir/file14
+U export-dir/file6
+U export-dir/file7
+${SPROG} export: Updating export-dir/dir1
+U export-dir/dir1/file14
+U export-dir/dir1/file6
+U export-dir/dir1/file7
+${SPROG} export: Updating export-dir/dir1/dir2
+U export-dir/dir1/dir2/file14
+U export-dir/dir1/dir2/file6
+U export-dir/dir1/dir2/file7"
+               dotest_fail basic2-28a "test -d export-dir/CVS"
+               dotest_fail basic2-28b "test -d export-dir/dir1/CVS"
+               dotest_fail basic2-28c "test -d export-dir/dir1/dir2/CVS"
+
+               dotest basic2-29 "${testcvs} co -r1.1 first-dir" \
+"${SPROG} checkout: Updating first-dir
+U first-dir/file14
+U first-dir/file6
+U first-dir/file7
+${SPROG} checkout: Updating first-dir/dir1
+U first-dir/dir1/file14
+U first-dir/dir1/file6
+U first-dir/dir1/file7
+${SPROG} checkout: Updating first-dir/dir1/dir2
+U first-dir/dir1/dir2/file14
+U first-dir/dir1/dir2/file6
+U first-dir/dir1/dir2/file7"
+
+               # directory copies are done in an oblique way in order to avoid a bug in sun's tmp filesystem.
+               mkdir first-dir.cpy ; (cd first-dir ; tar cf - . | (cd ../first-dir.cpy ; tar xf -))
+
+               dotest basic2-30 "directory_cmp first-dir export-dir"
+
+               # interrupt, while we've got a clean 1.1 here, let's import it
+               # into a couple of other modules.
+               cd export-dir
+               dotest_sort basic2-31 \
+"$testcvs import -m first-import second-dir first-immigration immigration1 immigration1_0" \
+"
+
+N second-dir/dir1/dir2/file14
+N second-dir/dir1/dir2/file6
+N second-dir/dir1/dir2/file7
+N second-dir/dir1/file14
+N second-dir/dir1/file6
+N second-dir/dir1/file7
+N second-dir/file14
+N second-dir/file6
+N second-dir/file7
+No conflicts created by this import
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/second-dir/dir1
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/second-dir/dir1/dir2"
+               cd ..
+
+               dotest basic2-32 "${testcvs} export -r HEAD second-dir" \
+"${SPROG} export: Updating second-dir
+U second-dir/file14
+U second-dir/file6
+U second-dir/file7
+${SPROG} export: Updating second-dir/dir1
+U second-dir/dir1/file14
+U second-dir/dir1/file6
+U second-dir/dir1/file7
+${SPROG} export: Updating second-dir/dir1/dir2
+U second-dir/dir1/dir2/file14
+U second-dir/dir1/dir2/file6
+U second-dir/dir1/dir2/file7"
+
+               dotest basic2-33 "directory_cmp first-dir second-dir"
+
+               rm -r second-dir
+
+               rm -r export-dir first-dir
+               mkdir first-dir
+               (cd first-dir.cpy ; tar cf - . | (cd ../first-dir ; tar xf -))
+
+               # update the top, cancelling sticky tags, retag, update other copy, compare.
+               cd first-dir
+               dotest basic2-34 "${testcvs} update -A -l *file*" \
+"[UP] file6
+${SPROG} update: \`file7' is no longer in the repository"
+
+               # If we don't delete the tag first, cvs won't retag it.
+               # This would appear to be a feature.
+               dotest basic2-35 "${testcvs} tag -l -d rtagged-by-revision" \
+"${SPROG} tag: Untagging \.
+D file14
+D file6"
+               dotest basic2-36 "${testcvs} tag -l rtagged-by-revision" \
+"${SPROG} tag: Tagging \.
+T file14
+T file6"
+
+               cd ..
+               mv first-dir 1dir
+               mv first-dir.cpy first-dir
+               cd first-dir
+
+               dotest basic2-37 "${testcvs} -q diff -u" ''
+
+               dotest basic2-38 "${testcvs} update" \
+"${SPROG} update: Updating .
+${SPROG} update: Updating dir1
+${SPROG} update: Updating dir1/dir2"
+
+               cd ..
+
+               #### FIXME: is this expected to work???  Need to investigate
+               #### and fix or remove the test.
+#              dotest basic2-39 "directory_cmp 1dir first-dir"
+
+               rm -r 1dir first-dir
+
+               # Test the cvs history command.
+               #
+               # Just skip these in write proxy mode for now.  We should only
+               # see write commands and maybe the last few reads in the
+               # secondary history file the way we currently sync, but I'm not
+               # going to try and test this yet.
+               if $proxy; then :; else
+
+               # The reason that there are two patterns rather than using
+               # \(${TESTDIR}\|<remote>\) is that we are trying to
+               # make this portable.  Perhaps at some point we should
+               # ditch that notion and require GNU expr (or dejagnu or....)
+               # since it seems to be so painful.
+
+               dotest basic2-64 "${testcvs} his -x TOFWUPCGMAR -a" \
+"O [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir           =first-dir= ${TESTDIR}/\*
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6     first-dir           == ${TESTDIR}
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7     first-dir           == ${TESTDIR}
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6     first-dir/dir1      == ${TESTDIR}
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7     first-dir/dir1      == ${TESTDIR}
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6     first-dir/dir1/dir2 == ${TESTDIR}
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7     first-dir/dir1/dir2 == ${TESTDIR}
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14    first-dir           == ${TESTDIR}
+M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6     first-dir           == ${TESTDIR}
+R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7     first-dir           == ${TESTDIR}
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14    first-dir/dir1      == ${TESTDIR}
+M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6     first-dir/dir1      == ${TESTDIR}
+R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7     first-dir/dir1      == ${TESTDIR}
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14    first-dir/dir1/dir2 == ${TESTDIR}
+M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6     first-dir/dir1/dir2 == ${TESTDIR}
+R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7     first-dir/dir1/dir2 == ${TESTDIR}
+F [0-9-]* [0-9:]* ${PLUS}0000 ${username}                     =first-dir= ${TESTDIR}/\*
+T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-head:A\]
+T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-tag:rtagged-by-head\]
+T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-revision:1\.1\]
+O [0-9-]* [0-9:]* ${PLUS}0000 ${username} \[1\.1\] first-dir           =first-dir= ${TESTDIR}/\*
+U [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6     first-dir           == ${TESTDIR}/first-dir
+W [0-9-]* [0-9:]* ${PLUS}0000 ${username}     file7     first-dir           == ${TESTDIR}/first-dir" \
+"O [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir           =first-dir= <remote>/\*
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6     first-dir           == <remote>
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7     first-dir           == <remote>
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6     first-dir/dir1      == <remote>
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7     first-dir/dir1      == <remote>
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6     first-dir/dir1/dir2 == <remote>
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7     first-dir/dir1/dir2 == <remote>
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14    first-dir           == <remote>
+M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6     first-dir           == <remote>
+R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7     first-dir           == <remote>
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14    first-dir/dir1      == <remote>
+M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6     first-dir/dir1      == <remote>
+R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7     first-dir/dir1      == <remote>
+A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14    first-dir/dir1/dir2 == <remote>
+M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6     first-dir/dir1/dir2 == <remote>
+R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7     first-dir/dir1/dir2 == <remote>
+F [0-9-]* [0-9:]* ${PLUS}0000 ${username}                     =first-dir= <remote>/\*
+T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-head:A\]
+T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-tag:rtagged-by-head\]
+T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-revision:1\.1\]
+O [0-9-]* [0-9:]* ${PLUS}0000 ${username} \[1\.1\] first-dir           =first-dir= <remote>/\*
+P [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6     first-dir           == <remote>
+W [0-9-]* [0-9:]* ${PLUS}0000 ${username}     file7     first-dir           == <remote>"
+         fi
+
+         dokeep
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir \
+                            $CVSROOT_DIRNAME/second-dir
+         ;;
+
+
+
+       ls)
+         # Test the ls & rls commands.  There are some tests of
+         # Interaction of ls, rls, and branches in branches2.
+         mkdir ls; cd ls
+         dotest ls-init-1 "$testcvs -Q co -dtop ."
+         cd top
+         dotest ls-1 "$testcvs ls CVSROOT" \
+"checkoutlist
+commitinfo
+config
+cvswrappers
+loginfo
+modules
+notify
+postadmin
+postproxy
+posttag
+postwatch
+preproxy
+rcsinfo
+taginfo
+verifymsg"
+         dotest ls-2 "$testcvs ls -R" \
+"\.:
+CVSROOT
+
+CVSROOT:
+checkoutlist
+commitinfo
+config
+cvswrappers
+loginfo
+modules
+notify
+postadmin
+postproxy
+posttag
+postwatch
+preproxy
+rcsinfo
+taginfo
+verifymsg"
+         # This used to cause a fatal error.
+         modify_repo mkdir $CVSROOT_DIRNAME/notcheckedout
+         dotest ls-3 "$testcvs ls -RP" \
+"\.:
+CVSROOT
+notcheckedout
+
+CVSROOT:
+checkoutlist
+commitinfo
+config
+cvswrappers
+loginfo
+modules
+notify
+postadmin
+postproxy
+posttag
+postwatch
+preproxy
+rcsinfo
+taginfo
+verifymsg"
+
+         # Make sure the previous command did not create the notcheckedout
+         # directory.
+         dotest_fail ls-4 "test -d notcheckedout"
+
+         dotest ls-5 "$testcvs ls -R" \
+"\.:
+CVSROOT
+notcheckedout
+
+CVSROOT:
+checkoutlist
+commitinfo
+config
+cvswrappers
+loginfo
+modules
+notify
+postadmin
+postproxy
+posttag
+postwatch
+preproxy
+rcsinfo
+taginfo
+verifymsg
+
+notcheckedout:"
+         dotest_fail ls-6 "test -d notcheckedout"
+
+         # Several test for ls -d, which shows dead revisions
+
+         # Set up the dead files
+         mkdir cemetery
+         dotest ls-d-init-1 "$testcvs -Q add cemetery"
+         cd cemetery
+         touch dead living
+         dotest ls-d-init-2 "$testcvs -Q add dead living"
+         dotest ls-d-init-3 "$testcvs -Q ci -mm dead living"
+         dotest ls-d-init-4 "$testcvs -Q tag -b branch"
+         dotest ls-d-init-5 "$testcvs -Q up -A"
+         rm dead
+         dotest ls-d-init-6 "$testcvs -Q rm dead"
+         dotest ls-d-init-7 "$testcvs -Q ci -mm dead"
+         dotest ls-d-init-8 "$testcvs -Q up -r branch"
+         rm dead
+         dotest ls-d-init-9 "$testcvs -Q rm dead"
+         dotest ls-d-init-10 "$testcvs -Q ci -mm dead"
+
+         # Possible output
+         output_living="living"
+         output_dead="dead
+living"
+
+         # The basic test is to make sure that dead revisions are shown if and
+         # only if -d is speficified (and that live revisions are always
+         # shown).  The following test cases cover all combinations of these
+         # factors:
+         #
+         #    + Working directory is on branch or trunk
+         #    + ls or rls
+         #    + implicit branch, explicit trunk, or explicit branch
+         #    + -d present or absent
+
+         # Working directory on trunk
+         $testcvs -Q up -A
+
+         ## ls
+         dotest ls-d-1 "$testcvs ls" "$output_living"
+         dotest ls-d-2 "$testcvs ls -d" "$output_dead"
+
+         dotest ls-d-3 "$testcvs ls -rHEAD" "$output_living"
+         dotest ls-d-4 "$testcvs ls -drHEAD" "$output_dead"
+
+         dotest ls-d-5 "$testcvs ls -rbranch" "$output_living"
+         dotest ls-d-6 "$testcvs ls -drbranch" "$output_dead"
+
+         ## rls
+         dotest ls-d-7 "$testcvs rls cemetery" \
+"$SPROG rls: Listing module: \`cemetery'
+$output_living"
+         dotest ls-d-8 "$testcvs rls -d cemetery" \
+"$SPROG rls: Listing module: \`cemetery'
+$output_dead"
+
+         dotest ls-d-9 "$testcvs -q rls -rHEAD cemetery" "$output_living"
+         dotest ls-d-10 "$testcvs -q rls -drHEAD cemetery" "$output_dead"
+
+         dotest ls-d-11 "$testcvs -q rls -rbranch cemetery" "$output_living"
+         dotest ls-d-12 "$testcvs -q rls -drbranch cemetery" "$output_dead"
+
+         # Working directory on branch
+         $testcvs -Q up -r branch
+
+         ## ls
+         dotest ls-d-13 "$testcvs ls" "$output_living"
+         dotest ls-d-14 "$testcvs ls -d" "$output_dead"
+
+         dotest ls-d-15 "$testcvs ls -r HEAD" "$output_living"
+         dotest ls-d-16 "$testcvs ls -d -r HEAD" "$output_dead"
+
+         dotest ls-d-17 "$testcvs ls -r branch" "$output_living"
+         dotest ls-d-18 "$testcvs ls -d -r branch" "$output_dead"
+
+         ## rls
+         dotest ls-d-19 "$testcvs -q rls cemetery" "$output_living"
+         dotest ls-d-20 "$testcvs -q rls -d cemetery" "$output_dead"
+
+         dotest ls-d-21 "$testcvs -q rls -rHEAD cemetery" "$output_living"
+         dotest ls-d-22 "$testcvs -q rls -drHEAD cemetery" "$output_dead"
+
+         dotest ls-d-23 "$testcvs -q rls -rbranch cemetery" "$output_living"
+         dotest ls-d-24 "$testcvs -q rls -drbranch cemetery" "$output_dead"
+
+         # Some tests to cover specifying a file name as an option
+         # Combinations of factors:
+         #
+         #  + file in CVS/Entries or not
+         #  + current directory or subdirectory
+         #  + file dead or not
+
+         # Switch back to the trunk
+         $testcvs -Q up -A
+
+         ## file in CVS/Entries
+         dotest ls-filename-1 "$testcvs ls dead"
+
+         # ls'ing a file that already exists once caused an assertion failure.
+         dotest ls-filename-2 "$testcvs ls living" "living"
+
+         cd ..
+         dotest ls-filename-3 "$testcvs ls cemetery/dead"
+
+         # ls'ing a file that already exists once caused an assertion failure.
+         dotest ls-filename-4 "$testcvs ls cemetery/living" "cemetery/living"
+         cd cemetery
+
+         ## file not in CVS/Entries
+         echo D > CVS/Entries
+
+         dotest ls-filename-5 "$testcvs ls dead"
+
+         # ls'ing a file that already exists once caused an assertion failure.
+         dotest ls-filename-6 "$testcvs ls living" "living"
+
+         cd ..
+         dotest ls-filename-7 "$testcvs ls cemetery/dead"
+
+         # ls'ing a file that already exists once caused an assertion failure.
+         dotest ls-filename-8 "$testcvs ls cemetery/living" "cemetery/living"
+
+         cd cemetery
+
+         # Test the -D date option to cvs ls
+
+         # try and list a file before it's created, during an old revision, in
+         # a period when it was dead and in the future
+         time_prebirth=`date '+%Y-%m-%d %H:%M:%S'` ; sleep 2
+         touch dated
+         dotest ls-D-init-1 "$testcvs -Q add dated"
+         dotest ls-D-init-2 "$testcvs -Q ci -mm dated"
+         time_newborn=`date '+%Y-%m-%d %H:%M:%S'` ; sleep 2
+         echo mm >> dated
+         dotest ls-D-init-2 "$testcvs -Q ci -mm dated"
+         time_predeath=`date '+%Y-%m-%d %H:%M:%S'` ; sleep 2
+         rm dated
+         dotest ls-D-init-3 "$testcvs -Q rm dated"
+         dotest ls-D-init-4 "$testcvs -Q ci -mm dated"
+         time_postdeath=`date '+%Y-%m-%d %H:%M:%S'`
+
+         dotest ls-D-1 "$testcvs ls -D '$time_prebirth' -e dated"
+
+         # ls'ing a file that already exists once caused an assertion failure.
+         dotest ls-D-2 "$testcvs ls -D '$time_newborn' -e dated" \
+"/dated/1\.1/.*"
+
+         # ls'ing a file that already exists once caused an assertion failure.
+         dotest ls-D-3 "$testcvs ls -D '$time_predeath' -e dated" \
+"/dated/1.2/.*"
+
+         dotest ls-D-4 "$testcvs ls -D '$time_postdeath' -e dated"
+
+         dokeep
+         cd ../../..
+         rm -r ls
+         modify_repo rm -rf $CVSROOT_DIRNAME/notcheckedout \
+                            $CVSROOT_DIRNAME/cemetery
+         unset output_living output_dead
+         ;;
+
+
+
+       parseroot)
+         mkdir 1; cd 1
+         # Test odd cases involving CVSROOT.  At the moment, that means we
+         # are testing roots with '/'s on the end, which CVS should parse off.
+         CVSROOT_save=${CVSROOT}
+         CVSROOT="${CVSROOT}/////"
+         dotest parseroot-1 "${testcvs} -q co CVSROOT/modules" \
+"U CVSROOT/modules"
+         dotest parseroot-2 "${testcvs} -q ci -fmnull-change CVSROOT/modules" \
+"$CVSROOT_DIRNAME/CVSROOT/modules,v  <--  CVSROOT/modules
+new revision: 1\.2; previous revision: 1\.1
+$SPROG commit: Rebuilding administrative file database"
+
+         if $remote; then
+           # I only test these when testing remote in case CVS was compiled
+           # without client support.
+
+           # logout does not try to contact the server.
+           CVSROOT=":pserver;proxy=localhost;proxyport=8080:localhost/dev/null"
+           dotest parseroot-3r "$testcvs -d'$CVSROOT' logout" \
+"Logging out of :pserver:$username@localhost:2401/dev/null
+$CPROG logout: Entry not found."
+           CVSROOT=":pserver;proxyport=8080:localhost/dev/null"
+           dotest_fail parseroot-4r "$testcvs -d'$CVSROOT' logout" \
+"$CPROG logout: Proxy port specified in CVSROOT without proxy host\.
+$CPROG \[logout aborted\]: Bad CVSROOT: \`:pserver;proxyport=8080:localhost/dev/null'\."
+           CVSROOT=":pserver;optionnoarg:localhost/dev/null"
+           dotest_fail parseroot-5r "$testcvs -d'$CVSROOT' logout" \
+"$CPROG logout: Option (\`optionnoarg') has no argument in CVSROOT\.
+$CPROG \[logout aborted\]: Bad CVSROOT: \`:pserver;optionnoarg:localhost/dev/null'\."
+           CVSROOT=":pserver;notanoption=anything:localhost/dev/null"
+           dotest_fail parseroot-6r "$testcvs -d'$CVSROOT' logout" \
+"$CPROG logout: Unknown option (\`notanoption') in CVSROOT\.
+$CPROG \[logout aborted\]: Bad CVSROOT: \`:pserver;notanoption=anything:localhost/dev/null'\."
+           CVSROOT=":local;proxy=localhost:/dev/null"
+           dotest_fail parseroot-7r "$testcvs -d'$CVSROOT' logout" \
+"$CPROG logout: CVSROOT proxy specification is only valid for gserver and
+$CPROG logout: pserver connection methods\.
+$CPROG \[logout aborted\]: Bad CVSROOT: \`:local;proxy=localhost:/dev/null'\."
+           CVSROOT="::pserver@anonymous@test.org:/cvs"
+           dotest_fail parseroot-8r "$testcvs -d'$CVSROOT' co test" \
+"$CPROG checkout: Unknown method (\`') in CVSROOT\.
+$CPROG \[checkout aborted\]: Bad CVSROOT: \`$CVSROOT'\."
+         fi
+
+         dokeep
+
+         # Clean up
+         CVSROOT=$CVSROOT_save
+         cd ..
+         rm -r 1
+         ;;
+
+
+
+       files)
+         # Test of how we specify files on the command line
+         # (recurse.c and that sort of thing).  Vaguely similar to
+         # tests like basic* and deep.  See modules and such tests
+         # for what happens when we throw in modules and co -d, &c.
+
+         # This particular test is fairly carefully crafted, to spot
+         # one particular issue with remote.
+         mkdir 1; cd 1
+         dotest files-1 "${testcvs} -q co -l ." ""
+         mkdir first-dir
+         dotest files-2 "${testcvs} add first-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
+         cd first-dir
+         touch tfile
+         dotest files-3 "${testcvs} add tfile" \
+"${SPROG} add: scheduling file .tfile. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest files-4 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/tfile,v  <--  tfile
+initial revision: 1\.1"
+         dotest files-5 "${testcvs} -q tag -b C" "T tfile"
+         dotest files-6 "${testcvs} -q update -r C" ""
+         mkdir dir
+         dotest files-7 "${testcvs} add dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir/dir put under version control
+--> Using per-directory sticky tag .C'"
+         cd dir
+         touch .file
+         dotest files-7b "${testcvs} add .file" \
+"${SPROG} add: scheduling file .\.file' for addition on branch .C.
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         mkdir sdir
+         dotest files-7c "${testcvs} add sdir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir/dir/sdir put under version control
+--> Using per-directory sticky tag .C'"
+         cd sdir
+         mkdir ssdir
+         dotest files-8 "${testcvs} add ssdir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir/dir/sdir/ssdir put under version control
+--> Using per-directory sticky tag .C'"
+         cd ssdir
+         touch .file
+         dotest files-9 "${testcvs} add .file" \
+"${SPROG} add: scheduling file .\.file' for addition on branch .C.
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         cd ../..
+         dotest files-10 "${testcvs} -q ci -m test" \
+"$CVSROOT_DIRNAME/first-dir/dir/Attic/\.file,v  <--  \.file
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/dir/sdir/ssdir/Attic/\.file,v  <--  sdir/ssdir/\.file
+new revision: 1\.1\.2\.1; previous revision: 1\.1"
+         dotest files-11 \
+"${testcvs} commit -m test -f ./.file ./sdir/ssdir/.file" \
+"${CVSROOT_DIRNAME}/first-dir/dir/Attic/\.file,v  <--  \.file
+new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
+${CVSROOT_DIRNAME}/first-dir/dir/sdir/ssdir/Attic/\.file,v  <--  \./sdir/ssdir/\.file
+new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1"
+         if $remote; then
+           # FIXCVS:
+           # This is a bug, looks like that toplevel_repos cruft in
+           # client.c is coming back to haunt us.
+           # May want to think about the whole issue, toplevel_repos
+           # has always been crufty and trying to patch it up again
+           # might be a mistake.
+           dotest files-12r \
+"$testcvs commit -f -m test ./sdir/ssdir/.file ./.file" \
+"$CVSROOT_DIRNAME/first-dir/dir/sdir/ssdir/Attic/\.file,v  <--  \./sdir/ssdir/\.file
+new revision: 1\.1\.2\.3; previous revision: 1\.1\.2\.2"
+
+           # Sync up the version numbers so that the rest of the
+           # tests don't need to expect different numbers based
+           # local or remote.
+           dotest files-12rworkaround \
+"$testcvs commit -f -m test .file" \
+"$CVSROOT_DIRNAME/first-dir/dir/Attic/\.file,v  <--  \.file
+new revision: 1\.1\.2\.3; previous revision: 1\.1\.2\.2"
+         else
+           dotest files-12 \
+"${testcvs} commit -f -m test ./sdir/ssdir/.file ./.file" \
+"${CVSROOT_DIRNAME}/first-dir/dir/sdir/ssdir/Attic/\.file,v  <--  \./sdir/ssdir/\.file
+new revision: 1\.1\.2\.3; previous revision: 1\.1\.2\.2
+${CVSROOT_DIRNAME}/first-dir/dir/Attic/\.file,v  <--  \.file
+new revision: 1\.1\.2\.3; previous revision: 1\.1\.2\.2"
+         fi
+         dotest files-13 \
+"${testcvs} commit -fmtest ./sdir/../sdir/ssdir/..///ssdir/.file" \
+"${CVSROOT_DIRNAME}/first-dir/dir/sdir/ssdir/Attic/\.file,v  <--  \./sdir/\.\./sdir/ssdir/\.\.///ssdir/\.file
+new revision: 1\.1\.2\.4; previous revision: 1\.1\.2\.3"
+         dotest files-14 \
+"${testcvs} commit -fmtest ../../first-dir/dir/.file" \
+"${CVSROOT_DIRNAME}/first-dir/dir/Attic/\.file,v  <--  \.\./\.\./first-dir/dir/\.file
+new revision: 1\.1\.2\.4; previous revision: 1\.1\.2\.3"
+
+         dokeep
+         cd ../../..
+         rm -r 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       spacefiles)
+         # More filename tests, in particular spaces in file names.
+         # (it might be better to just change a few of the names in
+         # basica or some other test instead, always good to keep the
+         # testsuite concise).
+
+         mkdir 1; cd 1
+         dotest spacefiles-1 "${testcvs} -q co -l ." ""
+         touch ./-c
+         dotest spacefiles-2 "${testcvs} add -- -c" \
+"${SPROG} add: scheduling file .-c. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest spacefiles-3 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/-c,v  <--  -c
+initial revision: 1\.1"
+         mkdir 'first dir'
+         dotest spacefiles-4 "${testcvs} add 'first dir'" \
+"Directory ${CVSROOT_DIRNAME}/first dir put under version control"
+         mkdir ./-b
+         dotest spacefiles-5 "${testcvs} add -- -b" \
+"Directory ${CVSROOT_DIRNAME}/-b put under version control"
+         cd 'first dir'
+         touch 'a file'
+         dotest spacefiles-6 "${testcvs} add 'a file'" \
+"${SPROG} add: scheduling file .a file. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest spacefiles-7 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first dir/a file,v  <--  a file
+initial revision: 1\.1"
+         dotest spacefiles-8 "${testcvs} -q tag new-tag" "T a file"
+         cd ../..
+
+         mkdir 2; cd 2
+         dotest spacefiles-10 "${testcvs} co -- -b" \
+"${SPROG} checkout: Updating -b"
+         dotest spacefiles-11 "${testcvs} -q co -- -c" "U \./-c"
+         rm ./-c
+         dotest spacefiles-13 "${testcvs} -q co 'first dir'" \
+"U first dir/a file"
+         cd ..
+
+         mkdir 3; cd 3
+         dotest spacefiles-14 "${testcvs} -q co 'first dir/a file'" \
+"U first dir/a file"
+         cd ..
+
+         rm -r 1 2 3
+         modify_repo rm -rf "'$CVSROOT_DIRNAME/first dir'" \
+                            $CVSROOT_DIRNAME/-b $CVSROOT_DIRNAME/-c,v
+         ;;
+
+
+
+       commit-readonly)
+         mkdir 1; cd 1
+         module=x
+
+         : > junk
+         dotest commit-readonly-1 "$testcvs -Q import -m . $module X Y" ''
+         dotest commit-readonly-2 "$testcvs -Q co $module" ''
+         cd $module
+
+         file=m
+
+         # Include an rcs keyword to be expanded.
+         echo '$Id''$' > $file
+
+         dotest commit-readonly-3 "$testcvs add $file" \
+"$SPROG add: scheduling file .$file. for addition
+$SPROG add: use .$SPROG commit. to add this file permanently"
+         dotest commit-readonly-4 "$testcvs -Q ci -m . $file"
+
+         echo line2 >> $file
+         # Make the file read-only.
+         chmod a-w $file
+
+         dotest commit-readonly-5 "$testcvs -Q ci -m . $file"
+
+         dokeep
+         cd ../..
+         rm -rf 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/"$module"
+         ;;
+
+
+
+       status)
+               # This tests for a bug in the status command which failed to
+               # notice resolved conflicts.
+               mkdir status; cd status
+               dotest status-init-1 "$testcvs -q co -l ."
+               mkdir first-dir
+               dotest status-init-2 "${testcvs} add first-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
+               cd first-dir
+               echo a line >tfile
+               dotest status-init-3 "${testcvs} add tfile" \
+"${SPROG} add: scheduling file .tfile. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+               dotest status-init-4 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/tfile,v  <--  tfile
+initial revision: 1\.1"
+               cd ..
+               dotest status-init-5 "${testcvs} -q co -dsecond-dir first-dir" \
+"U second-dir/tfile"
+               cd second-dir
+               echo some junk >>tfile
+               dotest status-init-6 "${testcvs} -q ci -maline" \
+"$CVSROOT_DIRNAME/first-dir/tfile,v  <--  tfile
+new revision: 1\.2; previous revision: 1\.1"
+               cd ../first-dir
+               echo force a conflict >>tfile
+               dotest status-init-7 "${testcvs} -q up" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/tfile,v
+retrieving revision 1\.1
+retrieving revision 1\.2
+Merging differences between 1\.1 and 1\.2 into tfile
+rcsmerge: warning: conflicts during merge
+${SPROG} update: conflicts found in tfile
+C tfile"
+
+               # Now note our status
+               dotest status-1 "${testcvs} status tfile" \
+"===================================================================
+File: tfile                    Status: Unresolved Conflict
+
+   Working revision:   1\.2.*
+   Repository revision:        1\.2    ${CVSROOT_DIRNAME}/first-dir/tfile,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+
+               # touch the file, leaving conflict markers in place
+               # and note our status
+               touch tfile
+               dotest status-2 "${testcvs} status tfile" \
+"===================================================================
+File: tfile                    Status: File had conflicts on merge
+
+   Working revision:   1\.2.*
+   Repository revision:        1\.2    ${CVSROOT_DIRNAME}/first-dir/tfile,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+
+               # resolve the conflict
+               echo resolution >tfile
+               dotest status-3 "${testcvs} status tfile" \
+"===================================================================
+File: tfile                    Status: Locally Modified
+
+   Working revision:   1\.2.*
+   Repository revision:        1\.2    ${CVSROOT_DIRNAME}/first-dir/tfile,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+
+               # Check that there are no problems just using CVS/Root too.
+               save_CVSROOT=$CVSROOT
+               unset CVSROOT
+               dotest status-3a "${testcvs} status tfile" \
+"===================================================================
+File: tfile                    Status: Locally Modified
+
+   Working revision:   1\.2.*
+   Repository revision:        1\.2    ${CVSROOT_DIRNAME}/first-dir/tfile,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+               CVSROOT=$save_CVSROOT
+               export CVSROOT
+
+               # FIXCVS:
+               # Update is supposed to re-Register() the file when it
+               # finds resolved conflicts:
+               dotest status-4 "grep 'Result of merge' CVS/Entries" \
+"/tfile/1\.2/Result of merge${PLUS}[a-zA-Z0-9 :]*//"
+
+                cd ..
+                mkdir fourth-dir
+                dotest status-init-8 "$testcvs add fourth-dir" \
+"Directory $CVSROOT_DIRNAME/fourth-dir put under version control"
+                cd fourth-dir
+                echo yet another line >t3file
+                dotest status-init-9 "$testcvs add t3file" \
+"$SPROG add: scheduling file .t3file. for addition
+$SPROG add: use .$SPROG commit. to add this file permanently"
+                dotest status-init-10 "$testcvs -q ci -m add" \
+"$CVSROOT_DIRNAME/fourth-dir/t3file,v  <--  t3file
+initial revision: 1\.1"
+                cd ../first-dir
+                mkdir third-dir
+                dotest status-init-11 "$testcvs add third-dir" \
+"Directory $CVSROOT_DIRNAME/first-dir/third-dir put under version control"
+                cd third-dir
+                echo another line >t2file
+                dotest status-init-12 "$testcvs add t2file" \
+"$SPROG add: scheduling file .t2file. for addition
+$SPROG add: use .$SPROG commit. to add this file permanently"
+                dotest status-init-13 "$testcvs -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/third-dir/t2file,v  <--  t2file
+initial revision: 1\.1"
+                dotest status-5 "$testcvs status ../tfile" \
+"===================================================================
+File: tfile                    Status: Locally Modified
+
+   Working revision:   1\.2.*
+   Repository revision:        1\.2    $CVSROOT_DIRNAME/first-dir/tfile,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+                dotest status-6 "$testcvs status ../../fourth-dir/t3file" \
+"===================================================================
+File: t3file                   Status: Up-to-date
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    $CVSROOT_DIRNAME/fourth-dir/t3file,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+
+               dokeep
+               cd ../../..
+               rm -rf status
+               modify_repo rm -rf $CVSROOT_DIRNAME/first-dir \
+                                  $CVSROOT_DIRNAME/fourth-dir
+               ;;
+
+
+
+       commit-readonlyfs)
+         mkdir 1; cd 1
+         module=x
+         : > junk
+         dotest commit-readonlyfs-1 "${testcvs} -Q import -m . $module X Y" ''
+         if $remote; then
+           dotest_fail commit-readonlyfs-2r1 "${testcvs} -Q -R co $module" \
+"${CPROG} \[checkout aborted\]: Read-only repository feature unavailable with remote roots (cvsroot = ${CVSROOT_DIRNAME})"
+           dotest commit-readonlyfs-2r2 "${testcvs} -Q co $module" ''
+          else
+           dotest commit-readonlyfs-2 "${testcvs} -Q -R co $module" ''
+           rm -rf $module
+           dotest commit-readonlyfs-2r3 "${testcvs} -q -R co $module" \
+"U $module/junk"
+           rm -rf $module
+           dotest commit-readonlyfs-2r4 "${testcvs} -R co $module" \
+"${SPROG}: WARNING: Read-only repository access mode selected via \`cvs -R'\.
+Using this option to access a repository which some users write to may
+cause intermittent sandbox corruption\.
+${SPROG} checkout: Updating $module
+U $module/junk"
+          fi
+         cd $module
+         echo test > junk
+         if $remote; then
+           dotest_fail commit-readonlyfs-3r "${testcvs} -Q -R ci -m. junk" \
+"${SPROG} \[commit aborted\]: Read-only repository feature unavailable with remote roots (cvsroot = ${CVSROOT_DIRNAME})"
+         else
+           dotest_fail commit-readonlyfs-3 "${testcvs} -Q -R ci -m. junk" \
+"${SPROG} commit: write lock failed\.
+WARNING: Read-only repository access mode selected via \`cvs -R'\.
+Attempting to write to a read-only filesystem is not allowed\.
+${SPROG} \[commit aborted\]: lock failed - giving up"
+          fi
+
+         dokeep
+         cd ../..
+         rm -rf 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/"$module"
+         ;;
+
+
+
+       rdiff)
+               # Test rdiff
+               # XXX for now this is just the most essential test...
+               cd ${TESTDIR}
+
+               mkdir testimport
+               cd testimport
+               echo '$''Id$' > foo
+               echo '$''Name$' >> foo
+               echo '$''Id$' > bar
+               echo '$''Name$' >> bar
+               dotest_sort rdiff-1 \
+                 "${testcvs} import -I ! -m test-import-with-keyword trdiff TRDIFF T1" \
+'
+
+N trdiff/bar
+N trdiff/foo
+No conflicts created by this import'
+               dotest rdiff-2 \
+                 "${testcvs} co -ko trdiff" \
+"${SPROG} checkout: Updating trdiff
+U trdiff/bar
+U trdiff/foo"
+               cd trdiff
+               echo something >> foo
+               dotest rdiff-3 \
+                 "${testcvs} ci -m added-something foo" \
+"${CVSROOT_DIRNAME}/trdiff/foo,v  <--  foo
+new revision: 1\.2; previous revision: 1\.1"
+               echo '#ident    "@(#)trdiff:$''Name$:$''Id$"' > new
+               echo "new file" >> new
+               dotest rdiff-4 \
+                 "${testcvs} add -m new-file-description new" \
+"${SPROG} add: scheduling file \`new' for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+               dotest rdiff-5 \
+                 "${testcvs} commit -m added-new-file new" \
+"${CVSROOT_DIRNAME}/trdiff/new,v  <--  new
+initial revision: 1\.1"
+               dotest rdiff-6 \
+                 "${testcvs} tag local-v0" \
+"${SPROG} tag: Tagging .
+T bar
+T foo
+T new"
+               dotest rdiff-7 \
+                 "${testcvs} status -v foo" \
+"===================================================================
+File: foo                      Status: Up-to-date
+
+   Working revision:   1\.2.*
+   Repository revision:        1\.2    ${CVSROOT_DIRNAME}/trdiff/foo,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     -ko
+
+   Existing Tags:
+       local-v0                        (revision: 1\.2)
+       T1                              (revision: 1\.1\.1\.1)
+       TRDIFF                          (branch: 1\.1\.1)"
+
+               cd ..
+               rm -r trdiff
+
+               dotest rdiff-8 \
+                 "${testcvs} rdiff -r T1 -r local-v0 trdiff" \
+"${SPROG}"' rdiff: Diffing trdiff
+Index: trdiff/foo
+diff -c trdiff/foo:1\.1\.1\.1 trdiff/foo:1\.2
+\*\*\* trdiff/foo:1\.1\.1\.1   '"${DATE}"'
+--- trdiff/foo '"${DATE}"'
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1,2 \*\*\*\*
+! \$''Id: foo,v 1\.1\.1\.1 [0-9/]* [0-9:]* '"${username}"' Exp \$
+! \$''Name: T1 \$
+--- 1,3 ----
+! \$''Id: foo,v 1\.2 [0-9/]* [0-9:]* '"${username}"' Exp \$
+! \$''Name: local-v0 \$
+! something
+Index: trdiff/new
+diff -c /dev/null trdiff/new:1\.1
+\*\*\* /dev/null       '"${DATE}"'
+--- trdiff/new '"${DATE}"'
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 0 \*\*\*\*
+--- 1,2 ----
+'"${PLUS}"' #ident     "@(#)trdiff:\$''Name: local-v0 \$:\$''Id: new,v 1\.1 [0-9/]* [0-9:]* '"${username}"' Exp \$"
+'"${PLUS}"' new file'
+
+               dokeep
+               cd ..
+               rm -r testimport
+               modify_repo rm -rf $CVSROOT_DIRNAME/trdiff
+               ;;
+
+
+
+       rdiff-short)
+         # Test that the short patch behaves as expected
+         #   1) Added file.
+         #   2) Removed file.
+         #   3) Different revision number with no difference.
+         #   4) Different revision number with changes.
+         #   5) Against trunk.
+         #   6) Same revision number (no difference).
+         mkdir rdiff-short; cd rdiff-short
+         mkdir abc
+         dotest rdiff-short-init-1 \
+"${testcvs} -q import -I ! -m initial-import abc vendor initial" \
+'
+No conflicts created by this import'
+
+         dotest rdiff-short-init-2 "${testcvs} -q get abc" ''
+         cd abc
+         echo "abc" >file1.txt
+         dotest rdiff-short-init-3 "${testcvs} add file1.txt" \
+"${SPROG} add: scheduling file .file1\.txt' for addition
+${SPROG} add: use \`${SPROG} commit' to add this file permanently"
+         dotest rdiff-short-init-4 \
+"${testcvs} commit -madd-file1 file1.txt" \
+"${CVSROOT_DIRNAME}/abc/file1\.txt,v  <--  file1\.txt
+initial revision: 1\.1"
+         echo def >>file1.txt
+         dotest rdiff-short-init-5 \
+"${testcvs} commit -mchange-file1 file1.txt" \
+"${CVSROOT_DIRNAME}/abc/file1\.txt,v  <--  file1\.txt
+new revision: 1\.2; previous revision: 1\.1"
+         echo "abc" >file1.txt
+         dotest rdiff-short-init-6 \
+"${testcvs} commit -mrestore-file1-rev1 file1.txt" \
+"${CVSROOT_DIRNAME}/abc/file1\.txt,v  <--  file1\.txt
+new revision: 1\.3; previous revision: 1\.2"
+         dotest rdiff-short-init-7 \
+"${testcvs} tag -r 1.1 tag1 file1.txt" \
+"T file1\.txt"
+         dotest rdiff-short-init-8 \
+"${testcvs} tag -r 1.2 tag2 file1.txt" \
+"T file1\.txt"
+         dotest rdiff-short-init-9 \
+"${testcvs} tag -r 1.3 tag3 file1.txt" \
+"T file1\.txt"
+         echo "abc" >file2.txt
+         dotest rdiff-short-init-10 \
+"${testcvs} add file2.txt" \
+"${SPROG} add: scheduling file .file2\.txt' for addition
+${SPROG} add: use \`${SPROG} commit' to add this file permanently"
+         dotest rdiff-add-remove-nodiff-init-11 \
+"${testcvs} commit -madd-file2 file2.txt" \
+"${CVSROOT_DIRNAME}/abc/file2\.txt,v  <--  file2\.txt
+initial revision: 1\.1"
+         dotest rdiff-short-init-12 \
+"${testcvs} tag -r 1.1 tag4 file2.txt" \
+"T file2\.txt"
+         dotest rdiff-short-init-13 \
+"${testcvs} tag -r 1.1 tag5 file2.txt" \
+"T file2\.txt"
+         cd ../..
+         rm -fr rdiff-short
+
+         # 3) Different revision number with no difference.
+         dotest rdiff-short-no-real-change \
+"${testcvs} -q rdiff -s -r tag1 -r tag3 abc"
+
+         # 4) Different revision number with changes.
+         dotest rdiff-short-real-change \
+"${testcvs} -q rdiff -s -r tag1 -r tag2 abc" \
+'File abc/file1.txt changed from revision 1\.1 to 1\.2'
+
+         # 1) Added file.
+         # 2) Removed file.
+         dotest_sort rdiff-short-remove-add \
+"${testcvs} -q rdiff -s -r tag2 -r tag4 abc" \
+'File abc/file1\.txt is removed; tag2 revision 1\.2
+File abc/file2\.txt is new; tag4 revision 1\.1'
+
+         # 6) Same revision number (no difference).
+         dotest rdiff-short-no-change \
+"${testcvs} -q rdiff -s -r tag4 -r tag5 abc"
+
+         # 5) Against trunk.
+         # Check that the messages change when we diff against the trunk
+         # rather than a tag or date.
+         dotest rdiff-short-against-trunk-1 \
+"${testcvs} -q rdiff -s -rtag4 abc" \
+"File abc/file1\.txt is new; current revision 1\.3"
+
+         dotest rdiff-short-against-trunk-2 \
+"${testcvs} -q rdiff -s -rtag2 abc" \
+"File abc/file1\.txt changed from revision 1\.2 to 1\.3
+File abc/file2\.txt is new; current revision 1\.1"
+
+         modify_repo rm -rf $CVSROOT_DIRNAME/abc
+         ;;
+
+
+
+       rdiff2)
+         # Test for the segv problem reported by James Cribb
+         # Somewhere to work
+         mkdir rdiff2; cd rdiff2         
+         # Create a module "m" with files "foo" and "d/bar"
+         mkdir m; cd m
+         echo foo >foo
+         mkdir d
+         echo bar >d/bar
+         dotest_sort  rdiff2-1 \
+"${testcvs} -q import -I ! -m initial-import m vendor initial" \
+'
+
+N m/d/bar
+N m/foo
+No conflicts created by this import'
+
+         cd ..
+         rm -r m
+         
+         # Remove "foo"
+         dotest rdiff2-2 "${testcvs} get m" \
+"${SPROG} checkout: Updating m
+U m/foo
+${SPROG} checkout: Updating m/d
+U m/d/bar"
+         cd m
+         dotest rdiff2-3 "${testcvs} rm -f foo" \
+"${SPROG} remove: scheduling .foo. for removal
+${SPROG} remove: use .${SPROG} commit. to remove this file permanently"
+
+         dotest rdiff2-4 "${testcvs} commit -m Removed foo" \
+"${CVSROOT_DIRNAME}/m/foo,v  <--  foo
+new revision: delete; previous revision: 1\.1\.1\.1"
+
+         # Modify "d/bar"
+         echo foo >d/bar
+         dotest rdiff2-5 "${testcvs} commit -m Changed d/bar" \
+"${CVSROOT_DIRNAME}/m/d/bar,v  <--  d/bar
+new revision: 1\.2; previous revision: 1\.1"
+         
+         # Crash before showing d/bar diffs
+         dotest_fail rdiff2-6 "${testcvs} rdiff -t m" \
+"${SPROG} rdiff: Diffing m
+${SPROG} rdiff: Diffing m/d
+Index: m/d/bar
+diff -c m/d/bar:1\.1\.1\.1 m/d/bar:1\.2
+\*\*\* m/d/bar:1\.1\.1\.1      ${DATE}
+--- m/d/bar    ${DATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+! bar
+--- 1 ----
+! foo"
+
+         dokeep
+         cd ../..
+         rm -rf rdiff2
+         modify_repo rm -rf $CVSROOT_DIRNAME/m
+         ;;
+
+
+
+       diff)
+         # Various tests specific to the "cvs diff" command.
+         # Related tests:
+         #   death2: -N
+         #   rcslib: cvs diff and $Name.
+         #   rdiff: cvs rdiff.
+         #   diffmerge*: nuts and bolts (stuff within diff library)
+         mkdir 1; cd 1
+         dotest diff-1 "$testcvs -q co -l ."
+         mkdir first-dir
+         dotest diff-2 "$testcvs add first-dir" \
+"Directory $CVSROOT_DIRNAME/first-dir put under version control"
+         cd first-dir
+
+         # diff is anomalous.  Most CVS commands print the "nothing
+         # known" message (or worse yet, no message in some cases) but
+         # diff says "I know nothing".  Shrug.
+         dotest_fail diff-3 "${testcvs} diff xyzpdq" \
+"${SPROG} diff: I know nothing about xyzpdq"
+         touch abc
+         dotest diff-4 "${testcvs} add abc" \
+"${SPROG} add: scheduling file .abc. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest diff-5 "${testcvs} -q ci -mtest" \
+"$CVSROOT_DIRNAME/first-dir/abc,v  <--  abc
+initial revision: 1\.1"
+         echo "extern int gethostname ();" >abc
+         dotest diff-6 "${testcvs} -q ci -mtest" \
+"$CVSROOT_DIRNAME/first-dir/abc,v  <--  abc
+new revision: 1\.2; previous revision: 1\.1"
+         echo "#include <winsock.h>" >abc
+         # check the behavior of the --ifdef=MACRO option
+         dotest_fail diff-7 "${testcvs} -q diff --ifdef=HAVE_WINSOCK_H" \
+"Index: abc
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
+retrieving revision 1\.2
+diff --ifdef HAVE_WINSOCK_H -r1\.2 abc
+#ifndef HAVE_WINSOCK_H
+extern int gethostname ();
+#else /\* HAVE_WINSOCK_H \*/
+#include <winsock\.h>
+#endif /\* HAVE_WINSOCK_H \*/"
+
+         dokeep
+         cd ../..
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         rm -r 1
+         ;;
+
+
+
+       diffnl)
+         # Test handling of 'cvs diff' of files without newlines
+         mkdir 1; cd 1
+         dotest diffnl-000 "${testcvs} -q co -l ." ''
+         mkdir first-dir
+         dotest diffnl-001 "${testcvs} add first-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
+          cd first-dir
+
+         ${AWK} 'BEGIN {printf("one\ntwo\nthree\nfour\nfive\nsix")}' </dev/null >abc
+         dotest diffnl-002 "${testcvs} add abc" \
+"${SPROG} add: scheduling file .abc. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+          dotest diffnl-003 "${testcvs} -q ci -mtest" \
+"$CVSROOT_DIRNAME/first-dir/abc,v  <--  abc
+initial revision: 1\.1"
+
+         # change to line near EOF
+         ${AWK} 'BEGIN {printf("one\ntwo\nthree\nfour\nsix")}' </dev/null >abc
+         dotest_fail diffnl-100 "${testcvs} diff abc" \
+"Index: abc
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
+retrieving revision 1\.1
+diff -r1\.1 abc
+5d4
+< five"
+          dotest_fail diffnl-101 "${testcvs} diff -u abc" \
+"Index: abc
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
+retrieving revision 1\.1
+diff -u -r1\.1 abc
+--- abc        ${RFCDATE}      1\.1
++++ abc        ${RFCDATE}
+@@ -2,5 +2,4 @@
+ two
+ three
+ four
+-five
+ six
+\\\\ No newline at end of file"
+          dotest diffnl-102 "${testcvs} -q ci -mtest abc" \
+"$CVSROOT_DIRNAME/first-dir/abc,v  <--  abc
+new revision: 1\.2; previous revision: 1\.1"
+
+          # Change to last line
+         ${AWK} 'BEGIN {printf("one\ntwo\nthree\nfour\nseven")}' </dev/null >abc
+          dotest_fail diffnl-200 "${testcvs} diff abc" \
+"Index: abc
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
+retrieving revision 1\.2
+diff -r1\.2 abc
+5c5
+< six
+\\\\ No newline at end of file
+---
+> seven
+\\\\ No newline at end of file"
+         dotest_fail diffnl-201 "${testcvs} diff -u abc" \
+"Index: abc
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
+retrieving revision 1\.2
+diff -u -r1\.2 abc
+--- abc        ${RFCDATE}      1\.2
++++ abc        ${RFCDATE}
+@@ -2,4 +2,4 @@
+ two
+ three
+ four
+-six
+\\\\ No newline at end of file
++seven
+\\\\ No newline at end of file"
+         dotest diffnl-202 "${testcvs} ci -mtest abc" \
+"${CVSROOT_DIRNAME}/first-dir/abc,v  <--  abc
+new revision: 1\.3; previous revision: 1\.2"
+
+         # Addition of newline
+         echo "one
+two
+three
+four
+seven" > abc
+         dotest_fail diffnl-300 "${testcvs} diff abc" \
+"Index: abc
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
+retrieving revision 1\.3
+diff -r1\.3 abc
+5c5
+< seven
+\\\\ No newline at end of file
+---
+> seven"
+         dotest_fail diffnl-301 "${testcvs} diff -u abc" \
+"Index: abc
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
+retrieving revision 1\.3
+diff -u -r1\.3 abc
+--- abc        ${RFCDATE}      1\.3
++++ abc        ${RFCDATE}
+@@ -2,4 +2,4 @@
+ two
+ three
+ four
+-seven
+\\\\ No newline at end of file
++seven"
+         dotest diffnl-302 "${testcvs} ci -mtest abc" \
+"${CVSROOT_DIRNAME}/first-dir/abc,v  <--  abc
+new revision: 1\.4; previous revision: 1\.3"
+
+         # Removal of newline
+         ${AWK} 'BEGIN {printf("one\ntwo\nthree\nfour\nseven")}' </dev/null >abc
+         dotest_fail diffnl-400 "${testcvs} diff abc" \
+"Index: abc
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
+retrieving revision 1\.4
+diff -r1\.4 abc
+5c5
+< seven
+---
+> seven
+\\\\ No newline at end of file"
+         dotest_fail diffnl-401 "${testcvs} diff -u abc" \
+"Index: abc
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
+retrieving revision 1\.4
+diff -u -r1\.4 abc
+--- abc        ${RFCDATE}      1\.4
++++ abc        ${RFCDATE}
+@@ -2,4 +2,4 @@
+ two
+ three
+ four
+-seven
++seven
+\\\\ No newline at end of file"
+
+         dokeep
+         cd ../..
+         rm -r 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       death)
+               # next dive.  test death support.
+
+               # NOTE: this section has reached the size and
+               # complexity where it is getting to be a good idea to
+               # add new death support tests to a new section rather
+               # than continuing to piggyback them onto the tests here.
+
+               modify_repo mkdir $CVSROOT_DIRNAME/first-dir
+               dotest death-init-1 "$testcvs -Q co first-dir"
+
+               cd first-dir
+
+               # Create a directory with only dead files, to make sure CVS
+               # doesn't get confused by it.
+               mkdir subdir
+               dotest 65a0 "${testcvs} add subdir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir/subdir put under version control"
+               cd subdir
+               echo file in subdir >sfile
+               dotest 65a1 "${testcvs} add sfile" \
+"${SPROG}"' add: scheduling file `sfile'\'' for addition
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+               dotest 65a2 "${testcvs} -q ci -m add-it" \
+"$CVSROOT_DIRNAME/first-dir/subdir/sfile,v  <--  sfile
+initial revision: 1\.1"
+               rm sfile
+               dotest 65a3 "${testcvs} rm sfile" \
+"${SPROG}"' remove: scheduling `sfile'\'' for removal
+'"${SPROG}"' remove: use .'"${SPROG}"' commit. to remove this file permanently'
+               dotest 65a4 "${testcvs} -q ci -m remove-it" \
+"$CVSROOT_DIRNAME/first-dir/subdir/sfile,v  <--  sfile
+new revision: delete; previous revision: 1\.1"
+               cd ..
+               dotest 65a5 "${testcvs} -q update -P" ''
+               dotest_fail 65a6 "test -d subdir" ''
+
+               # add a file.
+               touch file1
+               if ${CVS} add file1  2>> ${LOGFILE}; then
+                   pass 66
+               else
+                   fail 66
+               fi
+
+               # commit
+               if ${CVS} ci -m test  >> ${LOGFILE} 2>&1; then
+                   pass 67
+               else
+                   fail 67
+               fi
+
+               # remove
+               rm file1
+               if ${CVS} rm file1  2>> ${LOGFILE}; then
+                   pass 68
+               else
+                   fail 68
+               fi
+
+               # commit
+               if ${CVS} ci -m test  >>${LOGFILE} ; then
+                   pass 69
+               else
+                   fail 69
+               fi
+
+               dotest_fail 69a0 "test -f file1" ''
+               # get the old contents of file1 back
+               if ${testcvs} update -p -r 1.1 file1 >file1 2>>${LOGFILE}; then
+                 pass 69a1
+               else
+                 fail 69a1
+               fi
+               dotest 69a2 "cat file1" ''
+
+               # create second file
+               touch file2
+               if ${CVS} add file1 file2  2>> ${LOGFILE}; then
+                   pass 70
+               else
+                   fail 70
+               fi
+
+               # commit
+               if ${CVS} ci -m test  >> ${LOGFILE} 2>&1; then
+                   pass 71
+               else
+                   fail 71
+               fi
+
+               # log
+               if ${CVS} log file1  >> ${LOGFILE}; then
+                   pass 72
+               else
+                   fail 72
+               fi
+
+               # file4 will be dead at the time of branching and stay dead.
+               echo file4 > file4
+               dotest death-file4-add "${testcvs} add file4" \
+"${SPROG}"' add: scheduling file `file4'\'' for addition
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+               dotest death-file4-ciadd "${testcvs} -q ci -m add file4" \
+"$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+initial revision: 1\.1"
+               rm file4
+               dotest death-file4-rm "${testcvs} remove file4" \
+"${SPROG}"' remove: scheduling `file4'\'' for removal
+'"${SPROG}"' remove: use .'"${SPROG}"' commit. to remove this file permanently'
+               dotest death-file4-cirm "${testcvs} -q ci -m remove file4" \
+"$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+new revision: delete; previous revision: 1\.1"
+
+               # Tag the branchpoint.
+               dotest death-72a "${testcvs} -q tag bp_branch1" 'T file1
+T file2'
+
+               # branch1
+               if ${CVS} tag -b branch1  ; then
+                   pass 73
+               else
+                   fail 73
+               fi
+
+               # and move to the branch.
+               if ${CVS} update -r branch1  ; then
+                   pass 74
+               else
+                   fail 74
+               fi
+
+               dotest_fail death-file4-3 "test -f file4" ''
+
+               # add a file in the branch
+               echo line1 from branch1 >> file3
+               if ${CVS} add file3  2>> ${LOGFILE}; then
+                   pass 75
+               else
+                   fail 75
+               fi
+
+               # commit
+               if ${CVS} ci -m test  >> ${LOGFILE} 2>&1; then
+                   pass 76
+               else
+                   fail 76
+               fi
+
+               dotest death-76a0 \
+"${testcvs} -q rdiff -r bp_branch1 -r branch1 first-dir" \
+"Index: first-dir/file3
+diff -c /dev/null first-dir/file3:1\.1\.2\.1
+\*\*\* /dev/null       ${DATE}
+--- first-dir/file3    ${DATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 0 \*\*\*\*
+--- 1 ----
+${PLUS} line1 from branch1"
+               dotest death-76a1 \
+"${testcvs} -q rdiff -r branch1 -r bp_branch1 first-dir" \
+"Index: first-dir/file3
+diff -c first-dir/file3:1\.1\.2\.1 first-dir/file3:removed
+\*\*\* first-dir/file3:1\.1\.2\.1      ${DATE}
+--- first-dir/file3    ${DATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+- line1 from branch1
+--- 0 ----"
+
+               # remove
+               rm file3
+               if ${CVS} rm file3  2>> ${LOGFILE}; then
+                   pass 77
+               else
+                   fail 77
+               fi
+
+               # commit
+               if ${CVS} ci -m test  >>${LOGFILE} ; then
+                   pass 78
+               else
+                   fail 78
+               fi
+
+               # add again
+               echo line1 from branch1 >> file3
+               if ${CVS} add file3  2>> ${LOGFILE}; then
+                   pass 79
+               else
+                   fail 79
+               fi
+
+               # commit
+               if ${CVS} ci -m test  >> ${LOGFILE} 2>&1; then
+                   pass 80
+               else
+                   fail 80
+               fi
+
+               # change the first file
+               echo line2 from branch1 >> file1
+
+               # commit
+               if ${CVS} ci -m test  >> ${LOGFILE} 2>&1; then
+                   pass 81
+               else
+                   fail 81
+               fi
+
+               # remove the second
+               rm file2
+               if ${CVS} rm file2  2>> ${LOGFILE}; then
+                   pass 82
+               else
+                   fail 82
+               fi
+
+               # commit
+               if ${CVS} ci -m test  >>${LOGFILE}; then
+                   pass 83
+               else
+                   fail 83
+               fi
+
+               # back to the trunk.
+               if ${CVS} update -A  2>> ${LOGFILE}; then
+                   pass 84
+               else
+                   fail 84
+               fi
+
+               dotest_fail death-file4-4 "test -f file4" ''
+
+               if test -f file3 ; then
+                   fail 85
+               else
+                   pass 85
+               fi
+
+               # join
+               dotest death-86 "$testcvs -q update -j branch1" \
+"RCS file: $CVSROOT_DIRNAME/first-dir/file1,v
+retrieving revision 1\.3
+retrieving revision 1\.3\.2\.1
+Merging differences between 1\.3 and 1\.3\.2\.1 into file1
+${SPROG} update: scheduling \`file2' for removal
+U file3"
+
+               dotest_fail death-file4-5 "test -f file4" ''
+
+               if test -f file3 ; then
+                   pass 87
+               else
+                   fail 87
+               fi
+
+               # Make sure that we joined the correct change to file1
+               if echo line2 from branch1 | cmp - file1 >/dev/null; then
+                   pass 87a
+               else
+                   fail 87a
+               fi
+
+               # update
+               if ${CVS} update  ; then
+                   pass 88
+               else
+                   fail 88
+               fi
+
+               # commit
+               dotest 89 "${testcvs} -q ci -m test" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.4; previous revision: 1\.3
+$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+new revision: delete; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file3,v  <--  file3
+new revision: 1\.2; previous revision: 1\.1"
+               cd ..
+               mkdir 2
+               cd 2
+               dotest 89a "${testcvs} -q co first-dir" 'U first-dir/file1
+U first-dir/file3'
+               cd ..
+               rm -r 2
+               cd first-dir
+
+               # remove first file.
+               rm file1
+               if ${CVS} rm file1  2>> ${LOGFILE}; then
+                   pass 90
+               else
+                   fail 90
+               fi
+
+               # commit
+               if ${CVS} ci -m test  >>${LOGFILE}; then
+                   pass 91
+               else
+                   fail 91
+               fi
+
+               if test -f file1 ; then
+                   fail 92
+               else
+                   pass 92
+               fi
+
+               # typo; try to get to the branch and fail
+               dotest_fail 92.1a "$testcvs update -r brnach1" \
+                 "$SPROG \[update aborted\]: no such tag \`brnach1'"
+               # Make sure we are still on the trunk
+               if test -f file1 ; then
+                   fail 92.1b
+               else
+                   pass 92.1b
+               fi
+               if test -f file3 ; then
+                   pass 92.1c
+               else
+                   fail 92.1c
+               fi
+
+               # back to branch1
+               if ${CVS} update -r branch1  2>> ${LOGFILE}; then
+                   pass 93
+               else
+                   fail 93
+               fi
+
+               dotest_fail death-file4-6 "test -f file4" ''
+
+               if test -f file1 ; then
+                   pass 94
+               else
+                   fail 94
+               fi
+
+               # and join
+               dotest 95 "${testcvs} -q update -j HEAD" \
+"${SPROG}"' update: file file1 has been modified, but has been removed in revision HEAD
+'"${SPROG}"' update: file file3 exists, but has been added in revision HEAD'
+
+               dotest_fail death-file4-7 "test -f file4" ''
+
+               # file2 should not have been recreated.  It was
+               # deleted on the branch, and has not been modified on
+               # the trunk.  That means that there have been no
+               # changes between the greatest common ancestor (the
+               # trunk version) and HEAD.
+               dotest_fail death-file2-1 "test -f file2" ''
+
+               dokeep
+               cd ..
+               rm -r first-dir
+               modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+               ;;
+
+
+
+       death2)
+         # More tests of death support.
+         modify_repo mkdir $CVSROOT_DIRNAME/first-dir
+         dotest death2-1 "$testcvs -q co first-dir"
+
+         cd first-dir
+
+         # Add two files on the trunk.
+         echo "first revision" > file1
+         echo "file4 first revision" > file4
+         dotest death2-2 "${testcvs} add file1 file4" \
+"${SPROG}"' add: scheduling file `file1'\'' for addition
+'"${SPROG}"' add: scheduling file `file4'\'' for addition
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add these files permanently'
+
+         dotest death2-3 "${testcvs} -q commit -m add" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+initial revision: 1\.1"
+
+         # Make a branch and a non-branch tag.
+         dotest death2-4 "${testcvs} -q tag -b branch" \
+'T file1
+T file4'
+         dotest death2-5 "${testcvs} -q tag tag" \
+'T file1
+T file4'
+
+         # Switch over to the branch.
+         dotest death2-6 "${testcvs} -q update -r branch" ''
+
+         # Delete the file on the branch.
+         rm file1
+         dotest death2-7 "${testcvs} rm file1" \
+"${SPROG} remove: scheduling .file1. for removal
+${SPROG} remove: use .${SPROG} commit. to remove this file permanently"
+
+         # Test diff of the removed file before it is committed.
+         dotest_fail death2-diff-1 "${testcvs} -q diff file1" \
+"${SPROG} diff: file1 was removed, no comparison available"
+
+         dotest_fail death2-diff-2 "${testcvs} -q diff -N -c file1" \
+"Index: file1
+===================================================================
+RCS file: file1
+diff -N file1
+\*\*\* file1   ${RFCDATE}      [0-9.]*
+--- /dev/null  ${RFCDATE_EPOCH}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+- first revision
+--- 0 ----"
+
+         dotest death2-8 "${testcvs} -q ci -m removed" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: delete; previous revision: 1\.1"
+
+         # Test diff of a dead file.
+         dotest_fail death2-diff-3 \
+"${testcvs} -q diff -r1.1 -rbranch -c file1" \
+"${SPROG} diff: Tag branch refers to a dead (removed) revision in file .file1.\.
+${SPROG} diff: No comparison available\.  Pass .-N. to .${SPROG} diff.${QUESTION}"
+         # and in reverse
+         dotest_fail death2-diff-3a \
+"${testcvs} -q diff -rbranch -r1.1 -c file1" \
+"${SPROG} diff: Tag branch refers to a dead (removed) revision in file .file1.\.
+${SPROG} diff: No comparison available\.  Pass .-N. to .${SPROG} diff.${QUESTION}"
+
+         dotest_fail death2-diff-4 \
+"${testcvs} -q diff -r1.1 -rbranch -N -c file1" \
+"Index: file1
+===================================================================
+RCS file: file1
+diff -N file1
+\*\*\* file1   ${RFCDATE}      [0-9.]*
+--- /dev/null  ${RFCDATE_EPOCH}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+- first revision
+--- 0 ----"
+         # and in reverse
+         dotest_fail death2-diff-4a \
+"${testcvs} -q diff -rbranch -r1.1 -N -c file1" \
+"Index: file1
+===================================================================
+RCS file: file1
+diff -N file1
+\*\*\* /dev/null       ${RFCDATE_EPOCH}
+--- file1      ${RFCDATE}      [0-9.]*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 0 \*\*\*\*
+--- 1 ----
++ first revision"
+
+
+         dotest_fail death2-diff-5 "${testcvs} -q diff -rtag -c ." \
+"${SPROG} diff: file1 no longer exists, no comparison available"
+
+         dotest_fail death2-diff-6 "${testcvs} -q diff -rtag -N -c ." \
+"Index: file1
+===================================================================
+RCS file: file1
+diff -N file1
+\*\*\* file1   [-a-zA-Z0-9: ]* [0-9.]*
+--- /dev/null  ${RFCDATE_EPOCH}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+- first revision
+--- 0 ----"
+
+         # Test rdiff of a dead file.
+         dotest death2-rdiff-1 \
+"${testcvs} -q rtag -rbranch rdiff-tag first-dir" ''
+
+         dotest death2-rdiff-2 "${testcvs} -q rdiff -rtag -rbranch first-dir" \
+"Index: first-dir/file1
+diff -c first-dir/file1:1\.1 first-dir/file1:removed
+\*\*\* first-dir/file1:1\.1    [a-zA-Z0-9: ]*
+--- first-dir/file1    [a-zA-Z0-9: ]*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+- first revision
+--- 0 ----"
+
+         # Readd the file to the branch.
+         echo "second revision" > file1
+         dotest death2-9 "${testcvs} add file1" \
+"${SPROG} add: Re-adding file \`file1' on branch \`branch' after dead revision 1\.1\.2\.1\.
+${SPROG} add: use \`${SPROG} commit' to add this file permanently"
+
+         # Test diff of the added file before it is committed.
+         dotest_fail death2-diff-7 "${testcvs} -q diff file1" \
+"${SPROG} diff: file1 is a new entry, no comparison available"
+
+         dotest_fail death2-diff-8 "${testcvs} -q diff -N -c file1" \
+"Index: file1
+===================================================================
+RCS file: file1
+diff -N file1
+\*\*\* /dev/null       ${RFCDATE_EPOCH}
+--- file1      ${RFCDATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 0 \*\*\*\*
+--- 1 ----
+${PLUS} second revision"
+
+         dotest death2-10 "${testcvs} -q commit -m add" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1"
+
+         # Delete file4 from the branch
+         dotest death2-10a "${testcvs} rm -f file4" \
+"${SPROG} remove: scheduling .file4. for removal
+${SPROG} remove: use .${SPROG} commit. to remove this file permanently"
+         dotest death2-10b "${testcvs} -q ci -m removed" \
+"$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+new revision: delete; previous revision: 1\.1"
+
+         # Back to the trunk.
+         dotest death2-11 "${testcvs} -q update -A" \
+"[UP] file1
+U file4"
+
+         # Add another file on the trunk.
+         echo "first revision" > file2
+         dotest death2-12 "${testcvs} add file2" \
+"${SPROG}"' add: scheduling file `file2'\'' for addition
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+         dotest death2-13 "${testcvs} -q commit -m add" \
+"$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+initial revision: 1\.1"
+
+         # Modify file4 on the trunk.
+         echo "new file4 revision" > file4
+         dotest death2-13a "${testcvs} -q commit -m mod" \
+"$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+new revision: 1\.2; previous revision: 1\.1"
+
+         # Back to the branch.
+         # The ``no longer in the repository'' message doesn't really
+         # look right to me, but that's what CVS currently prints for
+         # this case.
+         dotest death2-14 "${testcvs} -q update -r branch" \
+"[UP] file1
+${SPROG} update: \`file2' is no longer in the repository
+${SPROG} update: \`file4' is no longer in the repository"
+
+         # Add a file on the branch with the same name.
+         echo "branch revision" > file2
+         dotest death2-15 "${testcvs} add file2" \
+"${SPROG}"' add: scheduling file `file2'\'' for addition on branch `branch'\''
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+         dotest death2-16 "${testcvs} -q commit -m add" \
+"$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1"
+
+         # Add a new file on the branch.
+         echo "first revision" > file3
+         dotest death2-17 "${testcvs} add file3" \
+"${SPROG}"' add: scheduling file `file3'\'' for addition on branch `branch'\''
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+         dotest death2-18 "${testcvs} -q commit -m add" \
+"$CVSROOT_DIRNAME/first-dir/Attic/file3,v  <--  file3
+new revision: 1\.1\.2\.1; previous revision: 1\.1"
+
+         # Test diff of a nonexistent tag
+         dotest_fail death2-diff-9 "$testcvs -q diff -rtag -c file3" \
+"$SPROG diff: tag tag is not in file file3"
+
+         dotest_fail death2-diff-10 "${testcvs} -q diff -rtag -N -c file3" \
+"Index: file3
+===================================================================
+RCS file: file3
+diff -N file3
+\*\*\* /dev/null       ${RFCDATE_EPOCH}
+--- file3      ${RFCDATE}      [0-9.]*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 0 \*\*\*\*
+--- 1 ----
+${PLUS} first revision"
+
+         dotest_fail death2-diff-11 "${testcvs} -q diff -rtag -c ." \
+"Index: file1
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
+retrieving revision 1\.1
+retrieving revision 1\.1\.2\.2
+diff -c -r1\.1 -r1\.1\.2\.2
+\*\*\* file1   ${RFCDATE}      [0-9.]*
+--- file1      ${RFCDATE}      [0-9.]*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+! first revision
+--- 1 ----
+! second revision
+${SPROG} diff: tag tag is not in file file2
+${SPROG} diff: tag tag is not in file file3
+${SPROG} diff: file4 no longer exists, no comparison available"
+
+         dotest_fail death2-diff-12 "${testcvs} -q diff -rtag -c -N ." \
+"Index: file1
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
+retrieving revision 1\.1
+retrieving revision 1\.1\.2\.2
+diff -c -r1\.1 -r1\.1\.2\.2
+\*\*\* file1   ${RFCDATE}      [0-9.]*
+--- file1      ${RFCDATE}      [0-9.]*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+! first revision
+--- 1 ----
+! second revision
+Index: file2
+===================================================================
+RCS file: file2
+diff -N file2
+\*\*\* /dev/null       ${RFCDATE_EPOCH}
+--- file2      ${RFCDATE}      [0-9.]*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 0 \*\*\*\*
+--- 1 ----
+${PLUS} branch revision
+Index: file3
+===================================================================
+RCS file: file3
+diff -N file3
+\*\*\* /dev/null       ${RFCDATE_EPOCH}
+--- file3      ${RFCDATE}      [0-9.]*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 0 \*\*\*\*
+--- 1 ----
+${PLUS} first revision
+Index: file4
+===================================================================
+RCS file: file4
+diff -N file4
+\*\*\* file4   ${RFCDATE}      [0-9.]*
+--- /dev/null  ${RFCDATE_EPOCH}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+- file4 first revision
+--- 0 ----"
+
+         # Switch to the nonbranch tag.
+         dotest death2-19 "${testcvs} -q update -r tag" \
+"[UP] file1
+${SPROG} update: \`file2' is no longer in the repository
+${SPROG} update: \`file3' is no longer in the repository
+U file4"
+
+         dotest_fail death2-20 "test -f file2"
+
+         # Make sure diff only reports appropriate files.
+         dotest_fail death2-diff-13 "${testcvs} -q diff -r rdiff-tag" \
+"${SPROG} diff: Tag rdiff-tag refers to a dead (removed) revision in file .file1.\.
+${SPROG} diff: No comparison available\.  Pass .-N. to .${SPROG} diff.${QUESTION}"
+
+         dotest_fail death2-diff-14 "${testcvs} -q diff -r rdiff-tag -c -N" \
+"Index: file1
+===================================================================
+RCS file: file1
+diff -N file1
+\*\*\* /dev/null       ${RFCDATE_EPOCH}
+--- file1      ${RFCDATE}      [0-9.]*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 0 \*\*\*\*
+--- 1 ----
+${PLUS} first revision"
+
+         # now back to the trunk
+         dotest death2-21 "${testcvs} -q update -A" \
+"U file2
+[UP] file4"
+
+         # test merging with a dead file
+         dotest death2-22 "${testcvs} -q co first-dir" \
+"U first-dir/file1
+U first-dir/file2
+U first-dir/file4"
+
+         cd first-dir
+         dotest death2-23 "${testcvs} rm -f file4" \
+"${SPROG} remove: scheduling .file4. for removal
+${SPROG} remove: use .${SPROG} commit. to remove this file permanently"
+         dotest death2-24 "${testcvs} -q ci -m removed file4" \
+"$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+new revision: delete; previous revision: 1\.2"
+         cd ..
+         echo "new stuff" >file4
+         dotest_fail death2-25 "${testcvs} up file4" \
+"${SPROG} update: conflict: \`file4' is modified but no longer in the repository
+C file4"
+
+         dokeep
+         cd ..
+         rm -r first-dir
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       rm-update-message)
+         # FIXME
+         # local CVS prints a warning message when update notices a missing
+         # file and client/server CVS doesn't.  These should be identical.
+         mkdir rm-update-message; cd rm-update-message
+         modify_repo mkdir $CVSROOT_DIRNAME/rm-update-message
+         dotest rm-update-message-setup-1 "$testcvs -q co rm-update-message" ''
+         cd rm-update-message
+         file=x
+         echo >$file
+         dotest rm-update-message-setup-2 "$testcvs -q add $file" \
+"${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest rm-update-message-setup-3 "$testcvs -q ci -mcreate $file" \
+"$CVSROOT_DIRNAME/rm-update-message/$file,v  <--  $file
+initial revision: 1\.1"
+
+         rm $file
+         dotest rm-update-message-1 "$testcvs up $file" \
+"${SPROG} update: warning: \`$file' was lost
+U $file"
+
+         dokeep
+         cd ../..
+         rm -r rm-update-message
+         modify_repo rm -rf $CVSROOT_DIRNAME/rm-update-message
+         ;;
+
+
+
+       rmadd)
+         # More tests of adding and removing files.
+         # In particular ci -r.
+         # Other ci -r tests:
+         #   * editor-9: checking in a modified file,
+         #     where "ci -r" means a branch.
+         #   * basica-8a1: checking in a modified file with numeric revision.
+         #   * basica-8a2: likewise.
+         #   * keywordlog-4: adding a new file with numeric revision.
+         mkdir 1; cd 1
+         dotest rmadd-1 "$testcvs -q co -l ."
+         mkdir first-dir
+         dotest rmadd-2 "${testcvs} add first-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
+         cd first-dir
+         echo first file1 >file1
+         dotest rmadd-3 "${testcvs} add file1" \
+"${SPROG} add: scheduling file .file1. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+
+         dotest_fail rmadd-4 "${testcvs} -q ci -r 1.2.2.4 -m add" \
+"${SPROG} commit: cannot add file .file1' with revision .1\.2\.2\.4'; must be on trunk
+${SPROG} \[commit aborted\]: correct above errors first!"
+         dotest_fail rmadd-5 "${testcvs} -q ci -r 1.2.2 -m add" \
+"${SPROG} commit: cannot add file .file1' with revision .1\.2\.2'; must be on trunk
+${SPROG} \[commit aborted\]: correct above errors first!"
+         dotest_fail rmadd-6 "$testcvs -q ci -r mybranch -m add" \
+"$SPROG \[commit aborted\]: no such tag \`mybranch'"
+
+         # The thing with the trailing periods strikes me as a very
+         # bizarre behavior, but it would seem to be intentional
+         # (see commit.c).  It probably could go away....
+         dotest rmadd-7 "${testcvs} -q ci -r 7.... -m add" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+initial revision: 7\.1"
+         if $remote; then
+           # I guess remote doesn't set a sticky tag in this case.
+           # Kind of odd, in the sense that rmadd-24a does set one
+           # both local and remote.
+           dotest_fail rmadd-7a "test -f CVS/Tag"
+           echo T7 >CVS/Tag
+         else
+           dotest rmadd-7a "cat CVS/Tag" "T7"
+         fi
+
+         dotest rmadd-8 "${testcvs} -q tag -b mybranch" "T file1"
+         dotest rmadd-9 "${testcvs} -q tag mynonbranch" "T file1"
+
+         touch file2
+         # The previous "cvs ci -r" set a sticky tag of '7'.  Seems a
+         # bit odd, and I guess commit.c (findmaxrev) makes '7' sticky
+         # tags unnecessary (?).  I kind of suspect that it should be
+         # saying "sticky tag is not a branch" like keywordlog-4b.
+         # Or something.
+         dotest rmadd-10 "${testcvs} add file2" \
+"${SPROG} add: scheduling file .file2. for addition on branch .7'
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         # As in the previous example, CVS is confused....
+         dotest rmadd-11 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+initial revision: 7\.1"
+
+         dotest rmadd-12 "${testcvs} -q update -A" ""
+         touch file3
+         dotest rmadd-13 "${testcvs} add file3" \
+"${SPROG} add: scheduling file .file3. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         # Huh?  file2 is not up to date?  Seems buggy to me....
+         dotest_fail rmadd-14 "${testcvs} -q ci -r mybranch -m add" \
+"${SPROG} commit: Up-to-date check failed for .file2'
+${SPROG} \[commit aborted\]: correct above errors first!"
+         # Whatever, let's not let file2 distract us....
+         dotest rmadd-15 "${testcvs} -q ci -r mybranch -m add file3" \
+"$CVSROOT_DIRNAME/first-dir/Attic/file3,v  <--  file3
+new revision: 1\.1\.2\.1; previous revision: 1\.1"
+
+         touch file4
+         dotest rmadd-16 "${testcvs} add file4" \
+"${SPROG} add: scheduling file .file4. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         # Prior to CVS 1.12.10, this would fail with a, "no such tag" message
+         # since val-tags used to be updated the first time the tag was used
+         # rather than when it was created.
+
+         # Try to make CVS write val-tags.
+         if $proxy; then :; else
+           # First remove the tag.
+           grep -v mynonbranch $CVSROOT_DIRNAME/CVSROOT/val-tags \
+                >$CVSROOT_DIRNAME/CVSROOT/val-tags-tmp
+           mv $CVSROOT_DIRNAME/CVSROOT/val-tags-tmp \
+              $CVSROOT_DIRNAME/CVSROOT/val-tags
+           rm -f $CVSROOT_DIRNAME/CVSROOT/val-tags.db
+
+           dotest rmadd-18 "$testcvs -q update -p -r mynonbranch file1" \
+"first file1"
+           # Oops, -p suppresses writing val-tags (probably a questionable
+           # behavior).
+           dotest_fail rmadd-19 \
+"$testcvs -q ci -r mynonbranch -m add file4" \
+"$SPROG \[commit aborted\]: no such tag \`mynonbranch'"
+           # Now make CVS write val-tags for real.
+           dotest rmadd-20 "$testcvs -q update -r mynonbranch file1"
+         fi # !$proxy
+
+         # Oops - CVS isn't distinguishing between a branch tag and
+         # a non-branch tag.
+         dotest rmadd-21 \
+"${testcvs} -q ci -r mynonbranch -m add file4" \
+"$CVSROOT_DIRNAME/first-dir/Attic/file4,v  <--  file4
+new revision: 1\.1\.2\.1; previous revision: 1\.1"
+
+         # OK, we add this one in a vanilla way, but then check in
+         # a modification with ci -r and sniff around for sticky tags.
+         echo file5 >file5
+         dotest rmadd-22 "${testcvs} add file5" \
+"${SPROG} add: scheduling file .file5. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         if $remote; then
+           # Interesting bug (or missing feature) here.  findmaxrev
+           # gets the major revision from the Entries.  Well, remote
+           # doesn't send the entries for files which are not involved.
+           dotest rmadd-23r "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/file5,v  <--  file5
+initial revision: 1\.1"
+           dotest rmadd-23-workaroundr \
+"${testcvs} -q ci -r 7 -m bump-it file5" \
+"$CVSROOT_DIRNAME/first-dir/file5,v  <--  file5
+new revision: 7\.1; previous revision: 1\.1"
+         else
+           dotest rmadd-23 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/file5,v  <--  file5
+initial revision: 7\.1"
+         fi
+         echo change it >file5
+         dotest_fail rmadd-24 "$testcvs -q ci -r 4.8 -m change file5" \
+"$CVSROOT_DIRNAME/first-dir/file5,v  <--  file5
+$SPROG commit: $CVSROOT_DIRNAME/first-dir/file5,v: revision 4\.8 too low; must be higher than 7\.1
+$SPROG commit: could not check in file5"
+         dotest rmadd-24a "${testcvs} -q ci -r 8.4 -m change file5" \
+"$CVSROOT_DIRNAME/first-dir/file5,v  <--  file5
+new revision: 8\.4; previous revision: 7\.1"
+         # I'm not really sure that a sticky tag make sense here.
+         # It seems to be longstanding behavior for what that is worth.
+         dotest rmadd-25 "${testcvs} status file5" \
+"===================================================================
+File: file5                    Status: Up-to-date
+
+   Working revision:   8\.4.*
+   Repository revision:        8\.4    ${CVSROOT_DIRNAME}/first-dir/file5,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         8\.4
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+
+         # now try forced revision with recursion
+         mkdir sub
+         dotest rmadd-26 "${testcvs} -q add sub" \
+"Directory ${CVSROOT_DIRNAME}/first-dir/sub put under version control"
+         echo hello >sub/subfile
+         dotest rmadd-27 "${testcvs} -q add sub/subfile" \
+"${SPROG} add: use .${SPROG} commit. to add this file permanently"
+
+         dotest rmadd-28 "${testcvs} -q ci -m. sub" \
+"$CVSROOT_DIRNAME/first-dir/sub/subfile,v  <--  sub/subfile
+initial revision: 1\.1"
+
+         # lose the branch
+         dotest rmadd-29 "${testcvs} -q up -A" \
+"${SPROG} update: \`file3' is no longer in the repository
+${SPROG} update: \`file4' is no longer in the repository"
+
+         # -f disables recursion
+         dotest rmadd-30 "${testcvs} -q ci -f -r9 -m." \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 9\.1; previous revision: 7\.1
+$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+new revision: 9\.1; previous revision: 7\.1
+$CVSROOT_DIRNAME/first-dir/file5,v  <--  file5
+new revision: 9\.1; previous revision: 8\.4"
+
+         # add -R to force recursion
+         dotest rmadd-31 "${testcvs} -q ci -f -r9 -R -m." \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 9\.2; previous revision: 9\.1
+$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+new revision: 9\.2; previous revision: 9\.1
+$CVSROOT_DIRNAME/first-dir/file5,v  <--  file5
+new revision: 9\.2; previous revision: 9\.1
+$CVSROOT_DIRNAME/first-dir/sub/subfile,v  <--  sub/subfile
+new revision: 9\.1; previous revision: 1\.1"
+
+         if $remote; then
+           # as noted above, remote doesn't set a sticky tag
+           :
+         else
+           dotest rmadd-32 "cat CVS/Tag" "T9"
+           dotest rmadd-33 "cat sub/CVS/Tag" "T9"
+         fi
+
+         dokeep
+         cd ../..
+         rm -r 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       rmadd2)
+         # Tests of undoing commits, including in the presence of
+         # adding and removing files.  See join for a list of -j tests.
+         mkdir 1; cd 1
+         dotest rmadd2-1 "${testcvs} -q co -l ." ''
+         mkdir first-dir
+         dotest rmadd2-2 "${testcvs} add first-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
+         cd first-dir
+         echo 'initial contents' >file1
+         dotest rmadd2-3 "${testcvs} add file1" \
+"${SPROG} add: scheduling file .file1. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest rmadd2-4 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+initial revision: 1\.1"
+         dotest rmadd2-4a "${testcvs} -Q tag tagone" ""
+         dotest rmadd2-5 "${testcvs} rm -f file1" \
+"${SPROG} remove: scheduling .file1. for removal
+${SPROG} remove: use .${SPROG} commit. to remove this file permanently"
+         dotest rmadd2-6 "${testcvs} -q ci -m remove" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: delete; previous revision: 1\.1"
+         dotest rmadd2-7 "$testcvs -q update -j 1.2 -j 1.1 file1" "U file1"
+         dotest rmadd2-8 "${testcvs} -q ci -m readd" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.3; previous revision: 1\.2"
+         echo 'new contents' >file1
+         dotest rmadd2-9 "${testcvs} -q ci -m modify" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.4; previous revision: 1\.3"
+         dotest rmadd2-10 "${testcvs} -q update -j 1.4 -j 1.3 file1" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
+retrieving revision 1\.4
+retrieving revision 1\.3
+Merging differences between 1\.4 and 1\.3 into file1"
+         dotest rmadd2-11 "${testcvs} -q ci -m undo" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.5; previous revision: 1\.4"
+         dotest rmadd2-12 "cat file1" "initial contents"
+         dotest rmadd2-13 "${testcvs} -q update -p -r 1.3" "initial contents"
+
+         # Hmm, might be a bit odd that this works even if 1.3 is not
+         # the head.
+         dotest rmadd2-14 "${testcvs} -q update -j 1.3 -j 1.2 file1" \
+"${SPROG} update: scheduling \`file1' for removal"
+
+         # Check that -p can get arbitrary revisions of a removed file
+         dotest rmadd2-14a "${testcvs} -q update -p" "initial contents"
+         dotest rmadd2-14b "${testcvs} -q update -p -r 1.5" "initial contents"
+         dotest rmadd2-14c "${testcvs} -q update -p -r 1.3" "initial contents"
+
+         dotest rmadd2-15 "${testcvs} -q ci -m re-remove" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: delete; previous revision: 1\.5"
+         dotest rmadd2-16 "${testcvs} log -h file1" "
+RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
+Working file: file1
+head: 1\.6
+branch:
+locks: strict
+access list:
+symbolic names:
+       tagone: 1\.1
+keyword substitution: kv
+total revisions: 6
+============================================================================="
+         dotest rmadd2-17 "${testcvs} status -v file1" \
+"===================================================================
+File: no file file1            Status: Up-to-date
+
+   Working revision:   No entry for file1
+   Repository revision:        1\.6    ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
+   Commit Identifier:  ${commitid}
+
+   Existing Tags:
+       tagone                          (revision: 1.1)"
+
+         dokeep
+         cd ../..
+         rm -r 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       rmadd3)
+          # This test demonstrates that CVS notices that file1 exists rather
+         # that deleting or writing over it after:
+         #
+         #   cvs remove -f file1; touch file1; cvs add file1.
+         #
+          # According to the manual, this should work for:
+         #
+         #   rm file1; cvs remove file1; cvs add file1
+         #
+         # but in past version of CVS, new content in file1 would be
+         # erroneously deleted when file1 reappeared between the remove and
+         # the add.
+         #
+         # Later versions of CVS would refuse to perform the add, but still
+         # allow a subsequent local commit to erase the file from the
+         # workspace, possibly losing data.
+         mkdir 1; cd 1
+         dotest rmadd3-init1 "${testcvs} -q co -l ." ''
+         mkdir first-dir
+         dotest rmadd3-init2 "${testcvs} add first-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
+         cd first-dir
+
+         echo initial content for file1 >file1
+         dotest rmadd3-init3 "${testcvs} add file1" \
+"${SPROG} add: scheduling file \`file1' for addition
+${SPROG} add: use \`${SPROG} commit' to add this file permanently"
+         dotest rmadd3-init4 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+initial revision: 1\.1"
+
+         # Here begins the guts of this test, as detailed above.
+         dotest rmadd3-1 "${testcvs} rm -f file1" \
+"${SPROG} remove: scheduling \`file1' for removal
+${SPROG} remove: use \`${SPROG} commit' to remove this file permanently"
+
+          # Now recreate the file:
+         echo desired future contents for file1 >file1
+
+         # And attempt to resurrect it at the same time:
+         dotest_fail rmadd3-2 "${testcvs} add file1" \
+"${SPROG} add: \`file1' should be removed and is still there (or is back again)"
+
+         # Now prove that commit knows that it shouldn't erase files.
+         dotest_fail rmadd3-3 "${testcvs} -q ci -m." \
+"$CPROG commit: \`file1' should be removed and is still there (or is back again)
+$CPROG \[commit aborted\]: correct above errors first!"
+
+         # Then these should pass too:
+         dotest rmadd3-4 "test -f file1"
+         dotest rmadd3-5 "cat file1" "desired future contents for file1"
+
+         if $keep; then
+           echo Keeping ${TESTDIR} and exiting due to --keep
+           exit 0
+         fi
+
+         dokeep
+         cd ../..
+         rm -r 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       resurrection)
+         # This test tests a few file resurrection scenarios.
+         mkdir 1; cd 1
+         dotest resurrection-init1 "$testcvs -q co -l ." ''
+         mkdir first-dir
+         dotest resurrection-init2 "$testcvs add first-dir" \
+"Directory $CVSROOT_DIRNAME/first-dir put under version control"
+         cd first-dir
+
+         echo initial content for file1 >file1
+         dotest resurrection-init3 "$testcvs add file1" \
+"$SPROG add: scheduling file \`file1' for addition
+$SPROG add: use \`$SPROG commit' to add this file permanently"
+         dotest resurrection-init4 "$testcvs -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+initial revision: 1\.1"
+
+         dotest resurrection-init5 "$testcvs -Q rm -f file1"
+
+         # The first test is that `cvs add' will resurrect a file before its
+         # removal has been committed.
+         dotest_sort resurrection-1 "$testcvs add file1" \
+"U file1
+$SPROG add: \`file1', version 1\.1, resurrected"
+         dotest resurrection-2 "$testcvs -Q diff file1" ""
+
+         dotest resurrection-init6 "$testcvs -Q tag -b resurrection"
+         dotest resurrection-init7 "$testcvs -Q rm -f file1"
+         dotest resurrection-init8 "$testcvs -Q ci -mrm"
+
+         # The next test is that CVS will resurrect a committed removal.
+         dotest_sort resurrection-3 "$testcvs add file1" \
+"U file1
+$SPROG add: Re-adding file \`file1' after dead revision 1\.2\.
+$SPROG add: Resurrecting file \`file1' from revision 1\.1\.
+$SPROG add: use \`$SPROG commit' to add this file permanently"
+         dotest resurrection-4 "$testcvs -q diff -r1.1 file1" ""
+         dotest resurrection-5 "$testcvs -q ci -mreadd" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.3; previous revision: 1\.2"
+
+         dotest resurrection-init9 "$testcvs -Q up -rresurrection"
+         dotest resurrection-init10 "$testcvs -Q rm -f file1"
+         dotest resurrection-init11 "$testcvs -Q ci -mrm-on-resurrection"
+
+         # The next test is that CVS will resurrect a committed removal to a
+         # branch.
+         dotest_sort resurrection-6 "$testcvs -r add file1" \
+"U file1
+$SPROG add: Re-adding file \`file1' on branch \`resurrection' after dead revision 1\.1\.2\.1\.
+$SPROG add: Resurrecting file \`file1' from revision 1\.1\.
+$SPROG add: use \`$SPROG commit' to add this file permanently"
+         # If the file is modified, it had better be read-write
+         # regardless of what the user has requested with the CVSREAD
+         # environment variable or the global -r switch
+          dotest resurrection-6b 'test -w file1' ''
+         dotest resurrection-7 "$testcvs -Q diff -r1.1 file1" ""
+         dotest resurrection-8 "$testcvs -q ci -mreadd" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1"
+
+         # The next few tests verify that an attempted resurrection of a file
+         # with no previous revision on the trunk fails.
+         touch file2
+         dotest resurrection-9 "$testcvs -Q add file2"
+         dotest resurrection-10 "$testcvs -Q ci -mnew-file2"
+         dotest resurrection-11 "$testcvs -Q up -A"
+
+         # This command once caused an assertion failure.
+         dotest resurrection-12 "$testcvs add file2" \
+"$SPROG add: File \`file2' has no previous revision to resurrect\."
+
+         # Check what 'cvs -r add' does with resurrected files.
+         dotest resurrection-13 "$testcvs -Q rm -f file1"
+         dotest_sort resurrection-14 "$testcvs -r add file1" \
+"U file1
+$SPROG add: \`file1', version 1\.3, resurrected"
+         dotest_fail resurrection-15 'test -w file1' ''
+
+         dokeep
+         cd ../..
+         rm -rf 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       dirs)
+         # Tests related to removing and adding directories.
+         # See also:
+         #   conflicts (especially dir1 in conflicts-130): What happens if
+         #     directory exists in repository and a non-CVS-controlled
+         #     directory in the working directory?
+         #   conflicts3-15.  More cases, especially where CVS directory
+         #     exists but without CVS/Repository and friends.
+         #   conflicts3-22.  Similar to conflicts-130 but there is a file
+         #     in the directory.
+         #   dirs2.  Sort of similar to conflicts3-22 but somewhat different.
+         mkdir imp-dir; cd imp-dir
+         echo file1 >file1
+         mkdir sdir
+         echo sfile >sdir/sfile
+         dotest_sort dirs-1 \
+"${testcvs} import -m import-it dir1 vend rel" "
+
+N dir1/file1
+N dir1/sdir/sfile
+No conflicts created by this import
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/dir1/sdir"
+         cd ..
+
+         mkdir 1; cd 1
+         dotest dirs-2 "$testcvs -Q co dir1" ""
+
+         # Various CVS administrators are in the habit of removing
+         # the repository directory for things they don't want any
+         # more.  I've even been known to do it myself (on rare
+         # occasions).  Not the usual recommended practice, but we want
+         # to try to come up with some kind of reasonable/documented/sensible
+         # behavior.
+         modify_repo rm -rf $CVSROOT_DIRNAME/dir1/sdir
+
+         dotest dirs-3 "${testcvs} update" \
+"${SPROG} update: Updating dir1
+${SPROG} update: Updating dir1/sdir
+${SPROG} update: cannot open directory ${CVSROOT_DIRNAME}/dir1/sdir: No such file or directory
+${SPROG} update: skipping directory dir1/sdir"
+         dotest dirs-3a "${testcvs} update -d" \
+"${SPROG} update: Updating dir1
+${SPROG} update: Updating dir1/sdir
+${SPROG} update: cannot open directory ${CVSROOT_DIRNAME}/dir1/sdir: No such file or directory
+${SPROG} update: skipping directory dir1/sdir"
+
+         # If we say "yes", then CVS gives errors about not being able to
+         # create lock files.
+         # The fact that it says "skipping directory " rather than
+         # "skipping directory dir1/sdir" is some kind of bug.
+         dotest dirs-4 "echo no | ${testcvs} release -d dir1/sdir" \
+"${SPROG} update: cannot open directory ${CVSROOT_DIRNAME}/dir1/sdir: No such file or directory
+${SPROG} update: skipping directory 
+You have \[0\] altered files in this repository\.
+Are you sure you want to release (and delete) directory .dir1/sdir': .. .release' aborted by user choice."
+
+         # OK, if "cvs release" won't help, we'll try it the other way...
+         rm -r dir1/sdir
+
+         dotest dirs-5 "cat dir1/CVS/Entries" \
+"/file1/1.1.1.1/[a-zA-Z0-9 :]*//
+D/sdir////"
+         dotest dirs-6 "${testcvs} update" "${SPROG} update: Updating dir1"
+         dotest dirs-7 "cat dir1/CVS/Entries" \
+"/file1/1.1.1.1/[a-zA-Z0-9 :]*//
+D/sdir////"
+         dotest dirs-8 "${testcvs} update -d dir1" \
+"${SPROG} update: Updating dir1"
+
+         dokeep
+         cd ..
+         rm -r imp-dir 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/dir1
+         ;;
+
+
+
+       dirs2)
+         # See "dirs" for a list of tests involving adding and
+         # removing directories.
+         mkdir 1; cd 1
+         dotest dirs2-1 "$testcvs -q co -l ."
+         mkdir first-dir
+         dotest dirs2-2 "${testcvs} add first-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
+         cd first-dir
+         mkdir sdir
+         dotest dirs2-3 "${testcvs} add sdir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir/sdir put under version control"
+         touch sdir/file1
+         dotest dirs2-4 "${testcvs} add sdir/file1" \
+"${SPROG} add: scheduling file .sdir/file1. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest dirs2-5 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/sdir/file1,v  <--  sdir/file1
+initial revision: 1\.1"
+         rm -r sdir/CVS
+         if $remote; then
+           # This is just like conflicts3-23
+           dotest_fail dirs2-6r "${testcvs} update -d" \
+"${QUESTION} sdir
+${SPROG} update: Updating \.
+${SPROG} update: Updating sdir
+${CPROG} update: move away \`sdir/file1'; it is in the way
+C sdir/file1"
+           rm sdir/file1
+           rm -r sdir/CVS
+
+           # This is where things are not just like conflicts3-23
+           dotest dirs2-7r "${testcvs} update -d" \
+"${QUESTION} sdir
+${SPROG} update: Updating \.
+${SPROG} update: Updating sdir
+U sdir/file1"
+         else
+           dotest dirs2-6 "${testcvs} update -d" \
+"${CPROG} update: Updating \.
+${QUESTION} sdir"
+           rm sdir/file1
+           dotest dirs2-7 "${testcvs} update -d" \
+"${CPROG} update: Updating \.
+${QUESTION} sdir"
+         fi
+         cd ../..
+
+         # Now, the same thing (more or less) on a branch.
+         mkdir 2; cd 2
+         dotest dirs2-8 "${testcvs} -q co first-dir" 'U first-dir/sdir/file1'
+         cd first-dir
+         dotest dirs2-9 "${testcvs} -q tag -b br" "T sdir/file1"
+         rm -r sdir/CVS
+
+         if $remote; then
+           # val-tags used to have a cute little quirk; if an update didn't
+           # recurse into the directories where the tag is defined, val-tags
+           # wouldn't get updated.  This is no longer a problem as of 1.12.10.
+           dotest_fail dirs2-10-againr "$testcvs update -d -r br" \
+"$QUESTION sdir
+$SPROG update: Updating \.
+$SPROG update: Updating sdir
+$CPROG update: move away \`sdir/file1'; it is in the way
+C sdir/file1"
+         else
+           dotest dirs2-10 "${testcvs} update -d -r br" \
+"$SPROG update: Updating \.
+$QUESTION sdir"
+# This is what used to happen.  I'm not sure why it changed with 1.12.10, but
+# as near as I can tell from the comments in update_direntproc, the new
+# behavior was the intended behavior.
+#"$CPROG update: in directory \`sdir':
+#$CPROG \[update aborted\]: there is no version here; do \`$CPROG checkout' first"
+         fi
+         cd ../..
+
+         # OK, the above tests make the situation somewhat harder
+         # than it might be, in the sense that they actually have a
+         # file which is alive on the branch we are updating.  Let's
+         # try it where it is just a directory where all the files
+         # have been removed.
+         mkdir 3; cd 3
+         dotest dirs2-11 "${testcvs} -q co -r br first-dir" \
+"U first-dir/sdir/file1"
+         cd first-dir
+         # Hmm, this doesn't mention the branch like add does.  That's
+         # an odd non-orthogonality.
+         dotest dirs2-12 "${testcvs} rm -f sdir/file1" \
+"${SPROG} remove: scheduling .sdir/file1. for removal
+${SPROG} remove: use .${SPROG} commit. to remove this file permanently"
+         dotest dirs2-13 "${testcvs} -q ci -m remove" \
+"$CVSROOT_DIRNAME/first-dir/sdir/file1,v  <--  sdir/file1
+new revision: delete; previous revision: 1\.1"
+         cd ../../2/first-dir
+         if $remote; then
+           dotest dirs2-14 "${testcvs} update -d -r br" \
+"${QUESTION} sdir/file1
+${SPROG} update: Updating \.
+${SPROG} update: Updating sdir"
+         else
+           dotest dirs2-14 "${testcvs} update -d -r br" \
+"${CPROG} update: Updating \.
+${QUESTION} sdir"
+         fi
+
+         dokeep
+         cd ../..
+         rm -r 1 2 3
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       branches)
+         # More branch tests, including branches off of branches
+         modify_repo mkdir $CVSROOT_DIRNAME/first-dir
+         dotest branches-1 "$testcvs -q co first-dir"
+         cd first-dir
+         echo 1:ancest >file1
+         echo 2:ancest >file2
+         echo 3:ancest >file3
+         echo 4:trunk-1 >file4
+         dotest branches-2 "${testcvs} add file1 file2 file3 file4" \
+"$SPROG add: scheduling file \`file1' for addition
+$SPROG add: scheduling file \`file2' for addition
+$SPROG add: scheduling file \`file3' for addition
+$SPROG add: scheduling file \`file4' for addition
+$SPROG add: use .$SPROG commit. to add these files permanently"
+         dotest branches-2a "$testcvs -n -q ci -m dont-commit"
+         dotest_lit branches-3 "$testcvs -q ci -m add-it" <<HERE
+$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+initial revision: 1.1
+$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+initial revision: 1.1
+${CVSROOT_DIRNAME}/first-dir/file3,v  <--  file3
+initial revision: 1.1
+${CVSROOT_DIRNAME}/first-dir/file4,v  <--  file4
+initial revision: 1.1
+HERE
+         echo 4:trunk-2 >file4
+         dotest branches-3.2 "${testcvs} -q ci -m trunk-before-branch" \
+"$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+new revision: 1\.2; previous revision: 1\.1"
+         # The "cvs log file4" in test branches-14.3 will test that we
+         # didn't really add the tag.
+         dotest branches-3.3 "${testcvs} -qn tag dont-tag" \
+"T file1
+T file2
+T file3
+T file4"
+         # Modify this file before branching, to deal with the case where
+         # someone is hacking along, says "oops, I should be doing this on
+         # a branch", and only then creates the branch.
+         echo 1:br1 >file1
+         dotest branches-4 "${testcvs} tag -b br1" "${SPROG}"' tag: Tagging \.
+T file1
+T file2
+T file3
+T file4'
+         dotest branches-5 "${testcvs} update -r br1" \
+"${SPROG} update: Updating \.
+M file1"
+         echo 2:br1 >file2
+         echo 4:br1 >file4
+         dotest branches-6 "${testcvs} -q ci -m modify" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+new revision: 1\.2\.2\.1; previous revision: 1\.2"
+         dotest branches-7 "${testcvs} -q tag -b brbr" 'T file1
+T file2
+T file3
+T file4'
+         dotest branches-8 "${testcvs} -q update -r brbr" ''
+         echo 1:brbr >file1
+         echo 4:brbr >file4
+         dotest branches-9 "${testcvs} -q ci -m modify" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.1\.2\.1\.2\.1; previous revision: 1\.1\.2\.1
+$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+new revision: 1\.2\.2\.1\.2\.1; previous revision: 1\.2\.2\.1"
+         dotest branches-10 "cat file1 file2 file3 file4" '1:brbr
+2:br1
+3:ancest
+4:brbr'
+         dotest branches-11 "${testcvs} -q update -r br1" \
+'[UP] file1
+[UP] file4'
+         dotest branches-12 "cat file1 file2 file3 file4" '1:br1
+2:br1
+3:ancest
+4:br1'
+         echo 4:br1-2 >file4
+         dotest branches-12.2 "${testcvs} -q ci -m change-on-br1" \
+"$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+new revision: 1\.2\.2\.2; previous revision: 1\.2\.2\.1"
+         dotest branches-13 "${testcvs} -q update -A" '[UP] file1
+[UP] file2
+[UP] file4'
+         dotest branches-14 "cat file1 file2 file3 file4" '1:ancest
+2:ancest
+3:ancest
+4:trunk-2'
+         echo 4:trunk-3 >file4
+         dotest branches-14.2 \
+           "${testcvs} -q ci -m trunk-change-after-branch" \
+"$CVSROOT_DIRNAME/first-dir/file4,v  <--  file4
+new revision: 1\.3; previous revision: 1\.2"
+         dotest branches-14.3 "${testcvs} log file4" \
+"
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
+Working file: file4
+head: 1\.3
+branch:
+locks: strict
+access list:
+symbolic names:
+       brbr: 1\.2\.2\.1\.0\.2
+       br1: 1\.2\.0\.2
+keyword substitution: kv
+total revisions: 6;    selected revisions: 6
+description:
+----------------------------
+revision 1\.3
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}1 -1;  commitid: ${commitid};
+trunk-change-after-branch
+----------------------------
+revision 1\.2
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}1 -1;  commitid: ${commitid};
+branches:  1\.2\.2;
+trunk-before-branch
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+add-it
+----------------------------
+revision 1\.2\.2\.2
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}1 -1;  commitid: ${commitid};
+change-on-br1
+----------------------------
+revision 1\.2\.2\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}1 -1;  commitid: ${commitid};
+branches:  1\.2\.2\.1\.2;
+modify
+----------------------------
+revision 1\.2\.2\.1\.2\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}1 -1;  commitid: ${commitid};
+modify
+============================================================================="
+         dotest_fail branches-14.4 \
+           "${testcvs} diff -c -r 1.1 -r 1.3 file4" \
+"Index: file4
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
+retrieving revision 1\.1
+retrieving revision 1\.3
+diff -c -r1\.1 -r1\.3
+\*\*\* file4   ${RFCDATE}      1\.1
+--- file4      ${RFCDATE}      1\.3
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+! 4:trunk-1
+--- 1 ----
+! 4:trunk-3"
+         dotest_fail branches-14.5 \
+           "${testcvs} diff -c -r 1.1 -r 1.2.2.1 file4" \
+"Index: file4
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
+retrieving revision 1\.1
+retrieving revision 1\.2\.2\.1
+diff -c -r1\.1 -r1\.2\.2\.1
+\*\*\* file4   ${RFCDATE}      1\.1
+--- file4      ${RFCDATE}      1\.2\.2\.1
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\* 1 \*\*\*\*
+! 4:trunk-1
+--- 1 ----
+! 4:br1"
+         dotest branches-15 \
+           "${testcvs} update -j 1.1.2.1 -j 1.1.2.1.2.1 file1" \
+           "RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
+retrieving revision 1\.1\.2\.1
+retrieving revision 1\.1\.2\.1\.2\.1
+Merging differences between 1\.1\.2\.1 and 1\.1\.2\.1\.2\.1 into file1
+rcsmerge: warning: conflicts during merge"
+         dotest branches-16 "cat file1" '<<<<<<< file1
+1:ancest
+[=]======
+1:brbr
+[>]>>>>>> 1\.1\.2\.1\.2\.1'
+
+         dotest branches-o1 "${testcvs} -q admin -o ::brbr" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
+done
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
+done
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file3,v
+done
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
+done"
+
+         dokeep
+         cd ..
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         rm -r first-dir
+         ;;
+
+
+
+       branches2)
+         # More branch tests.
+         # Test that when updating a new subdirectory in a directory
+         # which was checked out on a branch, the new subdirectory is
+         # created on the appropriate branch.  Test this when joining
+         # as well.
+
+         modify_repo mkdir $CVSROOT_DIRNAME/first-dir
+         mkdir trunk; cd trunk
+
+         # Create a file.
+         dotest branches2-1 "${testcvs} -q co first-dir"
+         cd first-dir
+         echo "file1 first revision" > file1
+         dotest branches2-2 "${testcvs} add file1" \
+"${SPROG} add: scheduling file .file1. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest branches2-3 "${testcvs} commit -m add file1" \
+"${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+initial revision: 1\.1"
+
+         # Tag the file.
+         dotest branches2-4 "${testcvs} -q tag tag1" 'T file1'
+
+         # Make two branches.
+         dotest branches2-5 "${testcvs} -q rtag -b -r tag1 b1 first-dir" ''
+         dotest branches2-6 "${testcvs} -q rtag -b -r tag1 b2 first-dir" ''
+
+         # Create some files and a subdirectory on branch b1.
+         cd ../..
+         mkdir b1; cd b1
+         dotest branches2-7 "${testcvs} -q co -r b1 first-dir" \
+"U first-dir/file1"
+         cd first-dir
+         echo "file2 first revision" > file2
+         dotest branches2-8 "${testcvs} add file2" \
+"${SPROG}"' add: scheduling file `file2'\'' for addition on branch `b1'\''
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+         mkdir dir1
+         dotest branches2-9 "${testcvs} add dir1" \
+"Directory ${CVSROOT_DIRNAME}/first-dir/dir1 put under version control
+--> Using per-directory sticky tag "'`'"b1'"
+         echo "file3 first revision" > dir1/file3
+         dotest branches2-10 "${testcvs} add dir1/file3" \
+"${SPROG}"' add: scheduling file `dir1/file3'\'' for addition on branch `b1'\''
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+         dotest branches2-11 "${testcvs} -q ci -madd ." \
+"$CVSROOT_DIRNAME/first-dir/Attic/file2,v  <--  file2
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/dir1/Attic/file3,v  <--  dir1/file3
+new revision: 1\.1\.2\.1; previous revision: 1\.1"
+
+         # Check out the second branch, and update the working
+         # directory to the first branch, to make sure the right
+         # happens with dir1.
+         cd ../..
+         mkdir b2; cd b2
+         dotest branches2-12 "${testcvs} -q co -r b2 first-dir" \
+'U first-dir/file1'
+         cd first-dir
+         dotest branches2-13 "${testcvs} update -d -r b1 dir1" \
+"${SPROG} update: Updating dir1
+U dir1/file3"
+         dotest branches2-14 "${testcvs} -q status" \
+"===================================================================
+File: file1                    Status: Up-to-date
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file1,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         b2 (branch: 1\.1\.4)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file3                    Status: Up-to-date
+
+   Working revision:   1\.1\.2\.1.*
+   Repository revision:        1\.1\.2\.1      ${CVSROOT_DIRNAME}/first-dir/dir1/Attic/file3,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         b1 (branch: 1\.1\.2)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+
+         # Test some calls to rls here because we can.  These should probably
+         # be somewhere else, but we already have some directories set up.
+          dotest branches2-14-rls-1 "$testcvs rls" \
+"$SPROG rls: Listing module: \`.'
+CVSROOT
+first-dir"
+          dotest branches2-14-rls-2 "$testcvs rls -R" \
+"$SPROG rls: Listing module: \`.'
+\.:
+CVSROOT
+first-dir
+
+CVSROOT:
+checkoutlist
+commitinfo
+config
+cvswrappers
+loginfo
+modules
+notify
+postadmin
+postproxy
+posttag
+postwatch
+preproxy
+rcsinfo
+taginfo
+verifymsg
+Emptydir
+
+CVSROOT/Emptydir:
+
+first-dir:
+file1
+dir1
+
+first-dir/dir1:"
+          dotest branches2-14-rls-3 "$testcvs rls -l -R" \
+"$SPROG rls: Listing module: \`.'
+\.:
+d--- $ISO8601DATE            CVSROOT
+d--- $ISO8601DATE            first-dir
+
+CVSROOT:
+---- $ISO8601DATE 1\.[0-9][0-9]*        checkoutlist
+---- $ISO8601DATE 1\.[0-9][0-9]*        commitinfo
+---- $ISO8601DATE 1\.[0-9][0-9]*        config
+---- $ISO8601DATE 1\.[0-9][0-9]*        cvswrappers
+---- $ISO8601DATE 1\.[0-9][0-9]*        loginfo
+---- $ISO8601DATE 1\.[0-9][0-9]*        modules
+---- $ISO8601DATE 1\.[0-9][0-9]*        notify
+---- $ISO8601DATE 1\.[0-9][0-9]*        postadmin
+---- $ISO8601DATE 1\.[0-9][0-9]*        postproxy
+---- $ISO8601DATE 1\.[0-9][0-9]*        posttag
+---- $ISO8601DATE 1\.[0-9][0-9]*        postwatch
+---- $ISO8601DATE 1\.[0-9][0-9]*        preproxy
+---- $ISO8601DATE 1\.[0-9][0-9]*        rcsinfo
+---- $ISO8601DATE 1\.[0-9][0-9]*        taginfo
+---- $ISO8601DATE 1\.[0-9][0-9]*        verifymsg
+d--- $ISO8601DATE            Emptydir
+
+CVSROOT/Emptydir:
+
+first-dir:
+---- $ISO8601DATE 1\.1        file1
+d--- $ISO8601DATE            dir1
+
+first-dir/dir1:"
+          dotest branches2-14-rls-4 "$testcvs rls -eR" \
+"$SPROG rls: Listing module: \`.'
+\.:
+D/CVSROOT////
+D/first-dir////
+
+CVSROOT:
+/checkoutlist/1\.[0-9][0-9]*/$DATE//
+/commitinfo/1\.[0-9][0-9]*/$DATE//
+/config/1\.[0-9][0-9]*/$DATE//
+/cvswrappers/1\.[0-9][0-9]*/$DATE//
+/loginfo/1\.[0-9][0-9]*/$DATE//
+/modules/1\.[0-9][0-9]*/$DATE//
+/notify/1\.[0-9][0-9]*/$DATE//
+/postadmin/1\.[0-9][0-9]*/$DATE//
+/postproxy/1\.[0-9][0-9]*/$DATE//
+/posttag/1\.[0-9][0-9]*/$DATE//
+/postwatch/1\.[0-9][0-9]*/$DATE//
+/preproxy/1\.[0-9][0-9]*/$DATE//
+/rcsinfo/1\.[0-9][0-9]*/$DATE//
+/taginfo/1\.[0-9][0-9]*/$DATE//
+/verifymsg/1\.[0-9][0-9]*/$DATE//
+D/Emptydir////
+
+CVSROOT/Emptydir:
+
+first-dir:
+/file1/1\.1/$DATE//
+D/dir1////
+
+first-dir/dir1:"
+          dotest branches2-14-rls-5 "$testcvs -q rls -R" \
+"\.:
+CVSROOT
+first-dir
+
+CVSROOT:
+checkoutlist
+commitinfo
+config
+cvswrappers
+loginfo
+modules
+notify
+postadmin
+postproxy
+posttag
+postwatch
+preproxy
+rcsinfo
+taginfo
+verifymsg
+Emptydir
+
+CVSROOT/Emptydir:
+
+first-dir:
+file1
+dir1
+
+first-dir/dir1:"
+          dotest branches2-14-rls-6 "$testcvs -q rls -lRrb1" \
+"\.:
+d--- $ISO8601DATE            CVSROOT
+d--- $ISO8601DATE            first-dir
+
+CVSROOT:
+d--- $ISO8601DATE            Emptydir
+
+CVSROOT/Emptydir:
+
+first-dir:
+---- $ISO8601DATE 1\.1        file1
+---- $ISO8601DATE 1\.1\.2\.1    file2
+d--- $ISO8601DATE            dir1
+
+first-dir/dir1:
+---- $ISO8601DATE 1\.1\.2\.1    file3"
+          dotest branches2-14-rls-7 "$testcvs -q rls -lRrb2" \
+"\.:
+d--- $ISO8601DATE            CVSROOT
+d--- $ISO8601DATE            first-dir
+
+CVSROOT:
+d--- $ISO8601DATE            Emptydir
+
+CVSROOT/Emptydir:
+
+first-dir:
+---- $ISO8601DATE 1\.1        file1
+d--- $ISO8601DATE            dir1
+
+first-dir/dir1:"
+
+         # Now some calls to ls.  These are more appropriate here.
+         dotest branches2-14-ls-1 "$testcvs ls" \
+"file1
+dir1"
+         dotest branches2-14-ls-2 "$testcvs ls -e" \
+"/file1/1\.1/$DATE//
+D/dir1////"
+         dotest branches2-14-ls-3 "$testcvs ls -R" \
+"\.:
+file1
+dir1
+
+dir1:
+file3"
+         dotest branches2-14-ls-4 "$testcvs ls -eRrHEAD" \
+"\.:
+/file1/1\.1/$DATE//THEAD
+D/dir1////
+
+dir1:"
+         dotest branches2-14-ls-5 "$testcvs ls -eRrb1" \
+"\.:
+/file1/1\.1/$DATE//Tb1
+/file2/1\.1\.2\.1/$DATE//Tb1
+D/dir1////
+
+dir1:
+/file3/1\.1\.2\.1/$DATE//Tb1"
+         dotest branches2-14-ls-6 "$testcvs ls -eRrb2" \
+"\.:
+/file1/1.1/$DATE//Tb2
+D/dir1////
+
+dir1:"
+         # Nonexistant tags used to cause assertion failures.
+         dotest_fail branches2-14-ls-7 "$testcvs ls -eRrnosuchtag" \
+"$SPROG \[ls aborted\]: no such tag \`nosuchtag'"
+
+         # FIXME: Just clobbering the directory like this is a bit
+         # tacky, although people generally expect it to work.  Maybe
+         # we should release it instead.  We do it a few other places
+         # below as well.
+         rm -r dir1
+         dotest branches2-15 "${testcvs} update -d -j b1 dir1" \
+"${SPROG} update: Updating dir1
+U dir1/file3"
+         # FIXCVS: The `No revision control file' stuff seems to be
+         # CVS's way of telling us that we're adding the file on a
+         # branch, and the file is not on that branch yet.  This
+         # should be nicer.
+         dotest branches2-16 "${testcvs} -q status" \
+"===================================================================
+File: file1                    Status: Up-to-date
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file1,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         b2 (branch: 1\.1\.4)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file3                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        No revision control file
+   Sticky Tag:         b2 - MISSING from RCS file!
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+
+         cd ../../trunk/first-dir
+         dotest branches2-17 "${testcvs} update -d -P dir1" \
+"${SPROG} update: Updating dir1"
+         dotest_fail branches2-18 "test -d dir1"
+         dotest branches2-19 "${testcvs} update -d -P -r b1 dir1" \
+"${SPROG} update: Updating dir1
+U dir1/file3"
+         dotest branches2-20 "${testcvs} -q status" \
+"===================================================================
+File: file1                    Status: Up-to-date
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file1,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file3                    Status: Up-to-date
+
+   Working revision:   1\.1\.2\.1.*
+   Repository revision:        1\.1\.2\.1      ${CVSROOT_DIRNAME}/first-dir/dir1/Attic/file3,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         b1 (branch: 1\.1\.2)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+
+         rm -r dir1
+         dotest branches2-21 "${testcvs} update -d -P -j b1 dir1" \
+"${SPROG} update: Updating dir1
+U dir1/file3"
+         dotest branches2-22 "${testcvs} -q status" \
+"===================================================================
+File: file1                    Status: Up-to-date
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file1,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+===================================================================
+File: file3                    Status: Locally Added
+
+   Working revision:   New file!
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/dir1/Attic/file3,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+
+         cd ../..
+         rm -r b1 b2
+
+         # Check out branch b1 twice.  Crate a new directory in one
+         # working directory, then do a cvs update in the other
+         # working directory and see if the tags are right.
+         mkdir b1a
+         mkdir b1b
+         cd b1b
+         dotest branches2-23 "${testcvs} -q co -r b1 first-dir" \
+'U first-dir/file1
+U first-dir/file2
+U first-dir/dir1/file3'
+         cd ../b1a
+         dotest branches2-24 "${testcvs} -q co -r b1 first-dir" \
+'U first-dir/file1
+U first-dir/file2
+U first-dir/dir1/file3'
+         cd first-dir
+         mkdir dir2
+         dotest branches2-25 "${testcvs} add dir2" \
+"Directory ${CVSROOT_DIRNAME}/first-dir/dir2 put under version control
+--> Using per-directory sticky tag "'`'"b1'"
+         echo "file4 first revision" > dir2/file4
+         dotest branches2-26 "${testcvs} add dir2/file4" \
+"${SPROG}"' add: scheduling file `dir2/file4'\'' for addition on branch `b1'\''
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+         dotest branches2-27 "${testcvs} -q commit -madd" \
+"$CVSROOT_DIRNAME/first-dir/dir2/Attic/file4,v  <--  dir2/file4
+new revision: 1\.1\.2\.1; previous revision: 1\.1"
+
+         cd ../../b1b/first-dir
+         dotest branches2-28 "${testcvs} update -d dir2" \
+"${SPROG} update: Updating dir2
+U dir2/file4"
+         cd dir2
+         dotest branches2-29 "${testcvs} -q status" \
+"===================================================================
+File: file4                    Status: Up-to-date
+
+   Working revision:   1\.1\.2\.1.*
+   Repository revision:        1\.1\.2\.1      ${CVSROOT_DIRNAME}/first-dir/dir2/Attic/file4,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         b1 (branch: 1\.1\.2)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+         dotest branches2-30 "cat CVS/Tag" 'Tb1'
+
+         # Test update -A on a subdirectory
+         cd ..
+         rm -r dir2
+         dotest branches2-31 "${testcvs} update -A -d dir2" \
+"${SPROG} update: Updating dir2"
+         cd dir2
+         dotest branches2-32 "${testcvs} -q status" ''
+         dotest_fail branches2-33 "test -f CVS/Tag"
+
+         # Add a file on the trunk.
+         echo "file5 first revision" > file5
+         dotest branches2-34 "${testcvs} add file5" \
+"${SPROG}"' add: scheduling file `file5'\'' for addition
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+         dotest branches2-35 "${testcvs} -q commit -madd" \
+"$CVSROOT_DIRNAME/first-dir/dir2/file5,v  <--  file5
+initial revision: 1\.1"
+
+         cd ../../../trunk/first-dir
+         dotest branches2-36 "${testcvs} -q update -d dir2" 'U dir2/file5'
+         cd dir2
+         dotest branches2-37 "${testcvs} -q status" \
+"===================================================================
+File: file5                    Status: Up-to-date
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/dir2/file5,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         (none)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+         dotest_fail branches2-38 "test -f CVS/status"
+
+          dotest branches2-39 "$testcvs rls -rb1 -l -R first-dir" \
+"$SPROG rls: Listing module: \`first-dir'
+first-dir:
+---- $ISO8601DATE 1\.1        file1
+---- $ISO8601DATE 1\.1\.2\.1    file2
+d--- $ISO8601DATE            dir1
+d--- $ISO8601DATE            dir2
+
+first-dir/dir1:
+---- $ISO8601DATE 1\.1\.2\.1    file3
+
+first-dir/dir2:
+---- $ISO8601DATE 1\.1\.2\.1    file4"
+
+         dokeep
+         cd ../../..
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         rm -r trunk b1a b1b
+         ;;
+
+
+
+       branches3)
+         # test local branch number support
+
+         # This test is skipped in $remotehost mode since the
+         # CVS_LOCAL_BRANCH_NUM is not inherited by the server process as it
+         # is with :fork:, for hopefully obvious reasons.
+         #
+         # FIXCVS?  Is this correct?  Should CVS_LOCAL_BRANCH_NUM be sent as
+         # a protocol extension or is it reasonable to only want this set on
+         # the server?
+
+         if test -n "$remotehost"; then :;else
+           modify_repo mkdir $CVSROOT_DIRNAME/first-dir
+           mkdir branches3; cd branches3
+
+           dotest branches3-1 "$testcvs -q co first-dir"
+           cd first-dir
+           echo "file1 first revision" > file1
+           dotest branches3-2 "${testcvs} add file1" \
+"${SPROG} add: scheduling file .file1. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+           dotest branches3-3 "${testcvs} commit -m add file1" \
+"${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+initial revision: 1\.1"
+
+           # Tag the file using a CVS_LOCAL_BRANCH_NUM of 1000
+           CVS_LOCAL_BRANCH_NUM=1000; export CVS_LOCAL_BRANCH_NUM
+           dotest branches3-4 "${testcvs} -q tag -b tag1" 'T file1'
+           unset CVS_LOCAL_BRANCH_NUM
+           dotest branches3-5 "${testcvs} -q log file1" \
+"
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
+Working file: file1
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+       tag1: 1\.1\.0\.1000
+keyword substitution: kv
+total revisions: 1;    selected revisions: 1
+description:
+----------------------------
+revision 1.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+add
+============================================================================="
+
+           dokeep
+           cd ../..
+           modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+           rm -r branches3
+         fi # !$remotehost
+         ;;
+
+
+
+       branches4)
+         # test where a tag is a branch tag in some files and a revision
+         # tag in others
+
+         modify_repo mkdir $CVSROOT_DIRNAME/first-dir
+         mkdir branches4; cd branches4
+
+         dotest branches4-1 "$testcvs -q co first-dir"
+         cd first-dir
+         mkdir branches mixed mixed2 versions
+         dotest branches4-2 "${testcvs} -q add branches mixed mixed2 versions" \
+"Directory ${CVSROOT_DIRNAME}/first-dir/branches put under version control
+Directory ${CVSROOT_DIRNAME}/first-dir/mixed put under version control
+Directory ${CVSROOT_DIRNAME}/first-dir/mixed2 put under version control
+Directory ${CVSROOT_DIRNAME}/first-dir/versions put under version control"
+
+         echo file1 >branches/file1
+         echo file2 >branches/file2
+         echo file3 >branches/file3
+         echo file4 >branches/file4
+         cp branches/file* mixed
+         cp branches/file* mixed2
+         cp branches/file* versions
+
+         dotest branches4-3 "${testcvs} -q add */file*" \
+"${SPROG} add: use .${SPROG} commit. to add these files permanently"
+         dotest branches4-3a "${testcvs} -Q ci -m."
+
+         dotest branches4-4 "${testcvs} -q tag xxx versions/file* mixed*/file1 mixed*/file3" \
+"T versions/file1
+T versions/file2
+T versions/file3
+T versions/file4
+T mixed/file1
+T mixed/file3
+T mixed2/file1
+T mixed2/file3"
+
+         dotest branches4-5 "${testcvs} -q tag -b xxx branches/file* mixed*/file2 mixed*/file4" \
+"T branches/file1
+T branches/file2
+T branches/file3
+T branches/file4
+T mixed/file2
+T mixed/file4
+T mixed2/file2
+T mixed2/file4"
+
+         # make sure we get the appropriate warnings when updating       
+         dotest branches4-6 "${testcvs} update -r xxx" \
+"${SPROG} update: Updating \.
+${SPROG} update: Updating branches
+${SPROG} update: Updating mixed
+${SPROG} update: warning: xxx is a branch tag in some files and a revision tag in others\.
+${SPROG} update: Updating mixed2
+${SPROG} update: warning: xxx is a branch tag in some files and a revision tag in others\.
+${SPROG} update: Updating versions"
+
+         # make sure we don't get warned in quiet modes
+         dotest branches4-7 "${testcvs} -q update -A"
+         dotest branches4-8 "${testcvs} -q update -r xxx"
+         dotest branches4-9 "${testcvs} -q update -A"
+         dotest branches4-10 "${testcvs} -Q update -r xxx"
+
+         # make sure the Tag files are correct
+         dotest branches4-11 "cat branches/CVS/Tag" "Txxx"
+         dotest branches4-12 "cat mixed/CVS/Tag" "Nxxx"
+         dotest branches4-13 "cat mixed2/CVS/Tag" "Nxxx"
+         dotest branches4-14 "cat versions/CVS/Tag" "Nxxx"
+
+         # We only warn if there's mixed usage in a single directory.
+         # We may want to consider changing that in the future.
+         dotest branches4-15 "${testcvs} update -r xxx branches versions" \
+"${SPROG} update: Updating branches
+${SPROG} update: Updating versions"
+
+         dokeep
+         cd ../..
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         rm -r branches4
+         ;;
+
+
+
+       tagc)
+         # Test the tag -c option.
+         mkdir 1; cd 1
+         dotest tagc-1 "${testcvs} -q co -l ." ''
+         mkdir first-dir
+         dotest tagc-2 "${testcvs} add first-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
+         cd first-dir
+         touch file1 file2
+         dotest tagc-3 "${testcvs} add file1 file2" \
+"${SPROG} add: scheduling file .file1. for addition
+${SPROG} add: scheduling file .file2. for addition
+${SPROG} add: use .${SPROG} commit. to add these files permanently"
+         dotest tagc-4 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+initial revision: 1\.1"
+         dotest tagc-5 "${testcvs} -q tag -c tag1" \
+"T file1
+T file2"
+         touch file1 file2
+         dotest tagc-6 "${testcvs} -q tag -c tag2" \
+"T file1
+T file2"
+         # Avoid timestamp granularity bugs (FIXME: CVS should be
+         # doing the sleep, right?).
+         sleep 2
+         echo myedit >>file1
+         dotest tagc-6a "${testcvs} rm -f file2" \
+"${SPROG} remove: scheduling .file2. for removal
+${SPROG} remove: use .${SPROG} commit. to remove this file permanently"
+         touch file3
+         dotest tagc-6b "${testcvs} add file3" \
+"${SPROG} add: scheduling file .file3. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest_fail tagc-7 "${testcvs} -q tag -c tag3" \
+"${SPROG} tag: file1 is locally modified
+${SPROG} tag: file2 is locally modified
+${SPROG} tag: file3 is locally modified
+${SPROG} \[tag aborted\]: correct the above errors first!"
+         cd ../..
+         mkdir 2
+         cd 2
+         dotest tagc-8 "${testcvs} -q co first-dir" \
+"U first-dir/file1
+U first-dir/file2"
+         cd ../1/first-dir
+         dotest tagc-9 "${testcvs} -q ci -m modify" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.2; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+new revision: delete; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file3,v  <--  file3
+initial revision: 1\.1"
+         cd ../../2/first-dir
+         dotest tagc-10 "${testcvs} -q tag -c tag4" \
+"${SPROG} tag: \`file2' is no longer in the repository
+T file1
+T file2"
+
+         dokeep
+         cd ../..
+         rm -r 1 2
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       update-p)
+         # Make sure `cvs update -p -rT FILE' works from a branch when
+         # FILE is already on the trunk and is being added to that branch.
+
+         mkdir 1; cd 1
+         module=x
+
+         echo > unused-file
+
+         # Create the module.
+         dotest update-p-1 \
+           "$testcvs -Q import -m. $module X Y" ''
+
+         file=F
+         # Check it out and tag it.
+         dotest update-p-2 "$testcvs -Q co $module" ''
+         cd $module
+         dotest update-p-3 "$testcvs -Q tag -b B" ''
+         echo v1 > $file
+         dotest update-p-4 "$testcvs -Q add $file" ''
+         dotest update-p-5 "$testcvs -Q ci -m. $file"
+         dotest update-p-6 "$testcvs -Q tag T $file" ''
+         dotest update-p-7 "$testcvs -Q update -rB" ''
+
+         # This merge effectively adds file F on branch B.
+         dotest update-p-8 "$testcvs -Q update -jT" ''
+
+         # Before the fix that prompted the addition of this test,
+         # the following command would fail with this diagnostic:
+         # cvs update: conflict: F created independently by second party
+         dotest update-p-9 "$testcvs update -p -rT $file" \
+"===================================================================
+Checking out $file
+RCS:  ${CVSROOT_DIRNAME}/$module/$file,v
+VERS: 1\.1
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+v1"
+
+         # Repeat the above, but with $file removed.
+         # This exercises a slightly different code path.
+         rm $file
+         # Before the fix that prompted the addition of this test,
+         # the following command would fail with this diagnostic:
+         # cvs update: warning: new-born \`F' has disappeared
+         dotest update-p-10 "$testcvs update -p -rT $file" \
+"===================================================================
+Checking out $file
+RCS:  ${CVSROOT_DIRNAME}/$module/$file,v
+VERS: 1\.1
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+v1"
+
+         # Exercise yet another code path:
+         # the one that involves reviving a `dead' file.
+         # And a little more, for good measure...
+         touch new
+         dotest update-p-a1 "$testcvs -Q add new" ''
+         dotest update-p-a2 "$testcvs -Q update -p new" ''
+         dotest update-p-a3 "$testcvs -Q rm -f new" ''
+
+         # Both an update -A, *and* the following update are required
+         # to return to the state of being on the trunk with a $file
+         # that we can then remove.
+         dotest update-p-undead-0 "$testcvs update -A" \
+"${SPROG} update: Updating \.
+${SPROG} update: warning: new-born \`$file' has disappeared"
+         dotest update-p-undead-1 "$testcvs update" \
+"${SPROG} update: Updating \.
+U $file"
+         dotest update-p-undead-2 "$testcvs -Q update -p -rT $file" v1
+         dotest update-p-undead-3 "$testcvs -Q rm -f $file" ''
+         dotest update-p-undead-4 "$testcvs -Q update -p -rT $file" v1
+         dotest update-p-undead-5 "$testcvs -Q ci -m. $file"
+         dotest update-p-undead-6 "$testcvs -Q update -p -rT $file" v1
+         echo v2 > $file
+         dotest update-p-undead-7 "$testcvs -Q update -p -rT $file" v1
+         dotest update-p-undead-8 "$testcvs add $file" \
+"$SPROG add: Re-adding file .$file. after dead revision 1\.2\.
+$SPROG add: use \`$SPROG commit' to add this file permanently"
+
+         dotest update-p-undead-9 "$testcvs -Q update -p -rT $file" v1
+
+         dokeep
+         cd ../..
+         rm -rf 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/$module
+         ;;
+
+
+
+       tagf)
+         # More tagging tests, including using tag -F -B to convert a
+         # branch tag to a regular tag and recovering thereof.
+
+         # Setup; check in first-dir/file1
+         mkdir 1; cd 1
+         dotest tagf-1 "${testcvs} -q co -l ." ''
+         mkdir first-dir
+         dotest tagf-2 "${testcvs} add first-dir" \
+"Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
+         cd first-dir
+         touch file1 file2
+         dotest tagf-3 "${testcvs} add file1 file2" \
+"${SPROG} add: scheduling file .file1. for addition
+${SPROG} add: scheduling file .file2. for addition
+${SPROG} add: use .${SPROG} commit. to add these files permanently"
+         dotest tagf-4 "${testcvs} -q ci -m add" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+initial revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+initial revision: 1\.1"
+
+         # Now create a branch and commit a revision there.
+         dotest tagf-5 "${testcvs} -q tag -b br" "T file1
+T file2"
+         dotest tagf-6 "${testcvs} -q update -r br" ""
+         echo brmod >> file1
+         echo brmod >> file2
+         dotest tagf-7 "${testcvs} -q ci -m modify" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+new revision: 1\.1\.2\.1; previous revision: 1\.1"
+         # Here we try to make it a non-branch tag, but will
+         # succeed in getting only warnings, even with -F 
+         # because converting a branch tag to non-branch 
+         # is potentially catastrophic.
+         dotest tagf-8a "${testcvs} -q tag -F br" \
+"${SPROG} tag: file1: Not moving branch tag .br. from 1\.1\.2\.1 to 1\.1\\.2\.1\.
+${SPROG} tag: file2: Not moving branch tag .br. from 1\.1\.2\.1 to 1\.1\.2\.1\."
+         # however, if we *really* are sure we want to move a branch tag,
+         # "-F -B" will do the trick
+         dotest tagf-8 "${testcvs} -q tag -F -B br" "T file1
+T file2"
+         echo moremod >> file1
+         echo moremod >> file2
+         dotest tagf-9 "${testcvs} -q status -v file1" \
+"===================================================================
+File: file1                    Status: Locally Modified
+
+   Working revision:   1\.1\.2\.1.*
+   Repository revision:        1\.1\.2\.1      ${CVSROOT_DIRNAME}/first-dir/file1,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         br (revision: 1\.1\.2\.1)
+   Sticky Date:                (none)
+   Sticky Options:     (none)
+
+   Existing Tags:
+       br                              (revision: 1\.1\.2\.1)"
+
+         # Now, how do we recover?
+         dotest tagf-10 "${testcvs} -q tag -d br" "D file1
+D file2"
+         # This creates a new branch, 1.1.4.  See the code in RCS_magicrev
+         # which will notice that there is a (non-magic) 1.1.2 and thus
+         # skip that number.
+         dotest tagf-11 "${testcvs} -q tag -r 1.1 -b br file1" "T file1"
+         # Fix it with admin -n (cf admin-18, admin-26-4).
+         dotest tagf-12 "${testcvs} -q admin -nbr:1.1.2 file2" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
+done"
+         # Another variation on the file2 test would be to use two working
+         # directories so that the update -r br would need to
+         # a merge to get from 1.1.2.1 to the head of the 1.1.2 branch.
+         dotest tagf-13 "${testcvs} -q update -r br" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
+retrieving revision 1\.1\.2\.1
+retrieving revision 1\.1
+Merging differences between 1\.1\.2\.1 and 1\.1 into file1
+rcsmerge: warning: conflicts during merge
+${SPROG} update: conflicts found in file1
+C file1
+M file2"
+         # CVS is giving a conflict because we are trying to get back to
+         # 1.1.4.  I'm not sure why it is a conflict rather than just
+         # "M file1".
+         dotest tagf-14 "cat file1" \
+"<<<<<<< file1
+brmod
+moremod
+[=]======
+[>]>>>>>> 1\.1"
+         echo resolve >file1
+         dotest tagf-15 "${testcvs} -q ci -m recovered" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.1\.4\.1; previous revision: 1\.1
+$CVSROOT_DIRNAME/first-dir/file2,v  <--  file2
+new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1"
+         # try accidentally deleting branch tag, "tag -d"
+         dotest_fail tagf-16 "${testcvs} tag -d br" \
+"${SPROG} tag: Untagging \.
+${SPROG} tag: Not removing branch tag .br. from .${CVSROOT_DIRNAME}/first-dir/file1,v.\.
+${SPROG} tag: Not removing branch tag .br. from .${CVSROOT_DIRNAME}/first-dir/file2,v.\."
+         # try accidentally deleting branch tag, "rtag -d"
+         dotest_fail tagf-17 "${testcvs} rtag -d br first-dir" \
+"${SPROG} rtag: Untagging first-dir
+${SPROG} rtag: Not removing branch tag .br. from .${CVSROOT_DIRNAME}/first-dir/file1,v.\.
+${SPROG} rtag: Not removing branch tag .br. from .${CVSROOT_DIRNAME}/first-dir/file2,v.\."
+         # try accidentally converting branch tag to non-branch tag "tag -F"
+         dotest tagf-18 "${testcvs} tag -r1.1 -F br file1" \
+"${SPROG} tag: file1: Not moving branch tag .br. from 1\.1\.4\.1 to 1\.1\."
+         # try accidentally converting branch tag to non-branch tag "rtag -F"
+         dotest tagf-19 "${testcvs} rtag -r1.1 -F br first-dir" \
+"${SPROG} rtag: Tagging first-dir
+${SPROG} rtag: first-dir/file1: Not moving branch tag .br. from 1\.1\.4\.1 to 1\.1\.
+${SPROG} rtag: first-dir/file2: Not moving branch tag .br. from 1\.1\.2\.2 to 1\.1\."
+         # create a non-branch tag
+         dotest tagf-20 "${testcvs} rtag regulartag first-dir" \
+"${SPROG} rtag: Tagging first-dir"
+         # try accidentally converting non-branch tag to branch tag (tag -F -B -b)
+         dotest tagf-21 "${testcvs} tag -F -B -b regulartag file1" \
+"${SPROG} tag: file1: Not moving non-branch tag .regulartag. from 1\.1 to 1\.1\.4\.1\.0\.2 due to .-B. option\."
+         # try accidentally converting non-branch tag to branch rtag (rtag -F -B -b)
+         dotest tagf-22 "${testcvs} rtag -F -B -b regulartag first-dir" \
+"${SPROG} rtag: Tagging first-dir
+${SPROG} rtag: first-dir/file1: Not moving non-branch tag .regulartag. from 1\.1 to 1\.1\.0\.6 due to .-B. option\.
+${SPROG} rtag: first-dir/file2: Not moving non-branch tag .regulartag. from 1\.1 to 1\.1\.0\.4 due to .-B. option\."
+         # Try accidentally deleting non-branch: (tag -d -B)
+         dotest_fail tagf-23 "${testcvs} tag -d -B regulartag file1" \
+"${SPROG} tag: Not removing non-branch tag .regulartag. from .${CVSROOT_DIRNAME}/first-dir/file1,v. due to .-B. option\."
+         # Try accidentally deleting non-branch: (rtag -d -B)
+         dotest_fail tagf-24 \
+               "${testcvs} rtag -d -B regulartag first-dir" \
+"${SPROG} rtag: Untagging first-dir
+${SPROG} rtag: Not removing non-branch tag .regulartag. from .${CVSROOT_DIRNAME}/first-dir/file1,v. due to .-B. option\.
+${SPROG} rtag: Not removing non-branch tag .regulartag. from .${CVSROOT_DIRNAME}/first-dir/file2,v. due to .-B. option\."
+
+         # the following tests (throught the next commit) keep moving the same
+         # tag back and forth between 1.1.6 & 1.1.8  in file1 and between
+         # 1.1.4 and 1.1.6 in file2 since nothing was checked in on some of
+         # these branches and CVS only tracks branches via tags unless they contain data.
+
+         # try intentionally converting non-branch tag to branch tag (tag -F -b)
+         dotest tagf-25a "${testcvs} tag -F -b regulartag file1" "T file1"
+         # try intentionally moving a branch tag to a newly created branch (tag -F -b -B)
+         dotest tagf-25b "${testcvs} tag -F -B -b -r1.1 regulartag file1" \
+"T file1"
+         # try intentionally converting mixed tags to branch tags (rtag -F -b)
+         dotest tagf-26a "${testcvs} rtag -F -b regulartag first-dir" \
+"${SPROG} rtag: Tagging first-dir
+${SPROG} rtag: first-dir/file1: Not moving branch tag .regulartag. from 1\.1 to 1\.1\.0\.8\."
+         # try intentionally converting a branch to a new branch tag (rtag -F -b -B)
+         dotest tagf-26b "${testcvs} rtag -F -B -b -r1.1 regulartag first-dir" \
+"${SPROG} rtag: Tagging first-dir"
+         # update to our new branch
+         dotest tagf-27 "${testcvs} update -r regulartag" \
+"${SPROG} update: Updating \.
+U file1
+U file2"
+         # commit some changes and see that all rev numbers look right
+         echo changes >> file1
+         echo changes >> file2
+         dotest tagf-28 "${testcvs} ci -m changes" \
+"${CPROG} commit: Examining \.
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.8\.1; previous revision: 1\.1
+${CVSROOT_DIRNAME}/first-dir/file2,v  <--  file2
+new revision: 1\.1\.6\.1; previous revision: 1\.1"
+         # try intentional branch to non-branch (tag -F -B)
+         dotest tagf-29 "${testcvs} tag -F -B -r1.1 regulartag file1" \
+"T file1"
+         # try non-branch to non-branch (tag -F -B)
+         dotest tagf-29a "${testcvs} tag -F -B -r br regulartag file1" \
+"${SPROG} tag: file1: Not moving non-branch tag .regulartag. from 1\.1 to 1\.1\.4\.1 due to .-B. option\."
+         # try mixed-branch to non-branch (rtag -F -B )
+         dotest tagf-29b "${testcvs} rtag -F -B -r br regulartag first-dir" \
+"${SPROG} rtag: Tagging first-dir
+${SPROG} rtag: first-dir/file1: Not moving non-branch tag .regulartag. from 1\.1 to 1\.1\.4\.1 due to .-B. option\."
+         # at this point, regulartag is a regular tag within
+         # file1 and file2
+
+         # try intentional branch to non-branch (rtag -F -B)
+         dotest tagf-30 "${testcvs} rtag -F -B -r1.1 br first-dir"  \
+"${SPROG} rtag: Tagging first-dir"
+         # create a branch tag so we can try to delete it.
+         dotest tagf-31 "${testcvs} rtag -b brtag first-dir"  \
+"${SPROG} rtag: Tagging first-dir"
+       
+         # try intentinal deletion of branch tag (tag -d -B)
+         dotest tagf-32 "${testcvs} tag -d -B brtag file1" "D file1"
+         # try intentinal deletion of branch tag (rtag -d -B)
+         dotest tagf-33 "${testcvs} rtag -d -B brtag first-dir" \
+"${SPROG} rtag: Untagging first-dir"
+
+         dokeep
+         cd ../..
+         rm -r 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         ;;
+
+
+
+       tag-space)
+         # Test tags with spaces in the names.
+         #
+         # Prior to releases 1.11.18 & 1.12.10, some commands used with
+         # tags with spaces in the names could hang CVS.
+
+         # Setup; check in first-dir/file1
+         mkdir 1; cd 1
+         dotest tag-space-init-1 "$testcvs -q co -l ."
+         mkdir first-dir
+         dotest tag-space-init-2 "$testcvs add first-dir" \
+"Directory $CVSROOT_DIRNAME/first-dir put under version control"
+         cd first-dir
+         touch file1
+         dotest tag-space-init-3 "$testcvs add file1" \
+"$SPROG add: scheduling file \`file1' for addition
+$SPROG add: use \`$SPROG commit' to add this file permanently"
+         dotest tag-space-init-4 "$testcvs -Q ci -m add"
+
+         # Reportedly, the following two tags make it past WinCVS.
+         dotest_fail tag-space-1 "$testcvs tag ' spacetag '" \
+"$SPROG \[tag aborted\]: tag \` spacetag ' must start with a letter"
+         dotest_fail tag-space-2 "$testcvs tag 'spacetag '" \
+"$SPROG \[tag aborted\]: tag \`spacetag ' has non-visible graphic characters"
+
+         if $remote; then
+           # Verify that this isn't a client check.
+           dotest tag-space-3 "$testcvs server" \
+"E $SPROG \[tag aborted\]: tag \` spacetag ' must start with a letter
+error  " <<EOF
+Root $CVSROOT_DIRNAME
+UseUnchanged
+Argument --
+Argument  spacetag 
+Directory .
+$CVSROOT_DIRNAME/first-dir
+Entry /file1/1.1///
+Unchanged file1
+tag
+EOF
+
+           dotest tag-space-4 "$testcvs server" \
+"E $SPROG \[tag aborted\]: tag \`spacetag ' has non-visible graphic characters
+error  " <<EOF
+Root $CVSROOT_DIRNAME
+UseUnchanged
+Argument --
+Argument spacetag 
+Directory .
+$CVSROOT_DIRNAME/first-dir
+Entry /file1/1.1///
+Unchanged file1
+tag
+EOF
+         fi # $remote
+
+         # Any number of normal tags and branches were handled correctly.
+         dotest tag-space-5 "$testcvs -Q tag t1"
+         dotest tag-space-5b "$testcvs -Q tag t2"
+         dotest tag-space-5c "$testcvs -Q tag -b b1"
+
+         cd ../..
+         mkdir 2; cd 2
+
+         # But once a vendor branch exists, it's all over.
+         mkdir project; cd project
+         touch file1
+         dotest tag-space-init-4 \
+"$testcvs -Q import -mimport second-dir VENDOR RELEASE"
+
+         cd ..
+
+         dotest_fail tag-space-6 "$testcvs -Q co -r ' spacetag ' first-dir" \
+"$SPROG \[checkout aborted\]: tag \` spacetag ' must start with a letter"
+
+         # But when any files were imported, this test hung prior to CVS
+         # versions 1.11.18 & 1.12.10.
+         dotest_fail tag-space-7 "$testcvs -Q co -r ' spacetag ' second-dir" \
+"$SPROG \[checkout aborted\]: tag \` spacetag ' must start with a letter"
+
+         if $remote; then
+           # I based the client input in the next two tests on actual input
+           # from WinCVS 1.2.
+           dotest tag-space-8 "$testcvs server" \
+"E $SPROG \[checkout aborted\]: tag \` spacetag ' must start with a letter
+error  " <<EOF
+Root $CVSROOT_DIRNAME
+Argument -P
+Argument -r
+Argument  spacetag 
+Argument first-dir
+Directory .
+$CVSROOT_DIRNAME
+co
+EOF
+
+           # Verify the test is not on the client side.
+           dotest tag-space-9 "$testcvs server" \
+"E $SPROG \[checkout aborted\]: tag \` spacetag ' must start with a letter
+error  " <<EOF
+Root $CVSROOT_DIRNAME
+Argument -P
+Argument -r
+Argument  spacetag 
+Argument second-dir
+Directory .
+$CVSROOT_DIRNAME
+co
+EOF
+         fi # $remote
+
+         dotest tag-space-10 "$testcvs -Q co second-dir"
+         cd second-dir
+
+         # This test would also hang.
+         dotest_fail tag-space-11 "$testcvs -Q up -r ' spacetag '" \
+"$SPROG \[update aborted\]: tag \` spacetag ' must start with a letter"
+
+         if $remote; then
+           dotest tag-space-12 "$testcvs server" \
+"E $SPROG \[update aborted\]: tag \` spacetag ' must start with a letter
+error  " <<EOF
+Root $CVSROOT_DIRNAME
+Argument -r
+Argument  spacetag 
+Argument -u
+Argument --
+Directory .
+$CVSROOT_DIRNAME
+Unchanged file1
+update
+EOF
+         fi # $remote
+
+         # I'm skipping tests for other commands that may have had the same
+         # problem.  Hopefully, if a new issue arises, one of the above tests
+         # will catch the problem.
+
+         if $keep; then
+           echo Keeping $TESTDIR and exiting due to --keep
+           exit 0
+         fi
+
+         cd ../..
+         rm -r 1 2
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir \
+                            $CVSROOT_DIRNAME/second-dir
+         ;;
+
+
+
+       rcslib)
+         # Test librarification of RCS.
+         # First: test whether `cvs diff' handles $Name expansion
+         # correctly.  We diff two revisions with their symbolic tags;
+         # neither tag should be expanded in the output.  Also diff
+         # one revision with the working copy.
+
+         modify_repo mkdir $CVSROOT_DIRNAME/first-dir
+         dotest rcsdiff-1 "${testcvs} -q co first-dir" ''
+         cd first-dir
+         echo "I am the first foo, and my name is $""Name$." > foo.c
+         dotest rcsdiff-2 "${testcvs} add -m new-file foo.c" \
+"${SPROG} add: scheduling file .foo\.c. for addition
+${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest rcsdiff-3 "${testcvs} commit -m rev1 foo.c" \
+"${CVSROOT_DIRNAME}/first-dir/foo.c,v  <--  foo\.c
+initial revision: 1\.1"
+         dotest rcsdiff-4 "${testcvs} tag first foo.c" "T foo\.c"
+         dotest rcsdiff-5 "${testcvs} update -p -r first foo.c" \
+"===================================================================
+Checking out foo\.c
+RCS:  ${CVSROOT_DIRNAME}/first-dir/foo\.c,v
+VERS: 1\.1
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+I am the first foo, and my name is \$""Name: first \$\."
+
+         echo "I am the second foo, and my name is $""Name$." > foo.c
+         dotest rcsdiff-6 "${testcvs} commit -m rev2 foo.c" \
+"${CVSROOT_DIRNAME}/first-dir/foo\.c,v  <--  foo\.c
+new revision: 1\.2; previous revision: 1\.1"
+         dotest rcsdiff-7 "${testcvs} tag second foo.c" "T foo\.c"
+         dotest rcsdiff-8 "${testcvs} update -p -r second foo.c" \
+"===================================================================
+Checking out foo\.c
+RCS:  ${CVSROOT_DIRNAME}/first-dir/foo\.c,v
+VERS: 1\.2
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+I am the second foo, and my name is \$""Name: second \$\."
+
+       dotest_fail rcsdiff-9 "${testcvs} diff -r first -r second" \
+"${SPROG} diff: Diffing \.
+Index: foo\.c
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/foo\.c,v
+retrieving revision 1\.1
+retrieving revision 1\.2
+diff -r1\.1 -r1\.2
+1c1
+< I am the first foo, and my name is \$""Name:  \$\.
+---
+> I am the second foo, and my name is \$""Name:  \$\."
+
+         echo "I am the once and future foo, and my name is $""Name$." > foo.c
+         dotest_fail rcsdiff-10 "${testcvs} diff -r first" \
+"${SPROG} diff: Diffing \.
+Index: foo\.c
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/foo\.c,v
+retrieving revision 1\.1
+diff -r1\.1 foo\.c
+1c1
+< I am the first foo, and my name is \$""Name:  \$\.
+---
+> I am the once and future foo, and my name is \$""Name\$\."
+
+         # Test handling of libdiff options.  diff gets quite enough
+         # of a workout elsewhere in sanity.sh, so we assume that it's
+         # mostly working properly if it passes all the other tests.
+         # The main one we want to try is regex handling, since we are
+         # using CVS's regex matcher and not diff's.
+
+         cat >rgx.c <<EOF
+test_regex (whiz, bang)
+{
+foo;
+bar;
+baz;
+grumble;
+}
+EOF
+
+         dotest rcslib-diffrgx-1 "${testcvs} -q add -m '' rgx.c" \
+"${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest rcslib-diffrgx-2 "${testcvs} -q ci -m '' rgx.c" \
+"$CVSROOT_DIRNAME/first-dir/rgx\.c,v  <--  rgx\.c
+initial revision: 1\.1"
+         cat >rgx.c <<EOF
+test_regex (whiz, bang)
+{
+foo;
+bar;
+baz;
+mumble;
+}
+EOF
+         # Use dotest_fail because exit status from `cvs diff' must be 1.
+         #
+         # Incidentally test that CVS no longer splits diff arguments on
+         # spaces.
+         dotest_fail rcslib-diffrgx-3 "$testcvs diff -c -F'.* (' rgx.c" \
+"Index: rgx\.c
+===================================================================
+RCS file: ${CVSROOT_DIRNAME}/first-dir/rgx\.c,v
+retrieving revision 1\.1
+diff -c -F '\.\* (' -r1\.1 rgx\.c
+\*\*\* rgx\.c  ${RFCDATE}      1\.1
+--- rgx\.c     ${RFCDATE}
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* test_regex (whiz, bang)
+\*\*\* 3,7 \*\*\*\*
+  foo;
+  bar;
+  baz;
+! grumble;
+  }
+--- 3,7 ----
+  foo;
+  bar;
+  baz;
+! mumble;
+  }"
+
+         # Tests of rcsmerge/diff3.  Merge operations get a good general
+         # workout elsewhere; we want to make sure that options are still
+         # handled properly.  Try merging two branches with -kv, to test
+         # both -j and -k switches.
+
+         cd ..
+
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         rm -r first-dir
+
+         mkdir 1; cd 1
+         dotest rcslib-merge-1 "$testcvs -q co -l ."
+         mkdir first-dir
+         dotest rcslib-merge-2 "$testcvs -q add first-dir" \
+"Directory $CVSROOT_DIRNAME.*/first-dir put under version control"
+         cd ..; rm -r 1
+
+         dotest rcslib-merge-3 "$testcvs -q co first-dir" ""
+         cd first-dir
+
+         echo '$''Revision$' > file1
+         echo '2' >> file1
+         echo '3' >> file1
+         dotest rcslib-merge-4 "${testcvs} -q add file1" \
+"${SPROG} add: use .${SPROG} commit. to add this file permanently"
+         dotest rcslib-merge-5 "${testcvs} -q commit -m '' file1" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+initial revision: 1\.1"
+         sed -e 's/2/two/' file1 > f; mv f file1
+         dotest rcslib-merge-6 "${testcvs} -q commit -m '' file1" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.2; previous revision: 1\.1"
+         dotest rcslib-merge-7 "${testcvs} -q tag -b -r 1.1 patch1" "T file1"
+         dotest rcslib-merge-8 "${testcvs} -q update -r patch1" "[UP] file1"
+         dotest rcslib-merge-9 "${testcvs} -q status" \
+"===================================================================
+File: file1                    Status: Up-to-date
+
+   Working revision:   1\.1.*
+   Repository revision:        1\.1    ${CVSROOT_DIRNAME}/first-dir/file1,v
+   Commit Identifier:  ${commitid}
+   Sticky Tag:         patch1 (branch: 1\.1\.2)
+   Sticky Date:                (none)
+   Sticky Options:     (none)"
+         dotest rcslib-merge-10 "cat file1" \
+'$''Revision: 1\.1 $
+2
+3'
+         sed -e 's/3/three/' file1 > f; mv f file1
+         dotest rcslib-merge-11 "${testcvs} -q commit -m '' file1" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.1\.2\.1; previous revision: 1\.1"
+         dotest rcslib-merge-12 "${testcvs} -q update -kv -j1.2" \
+"U file1
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
+retrieving revision 1\.1
+retrieving revision 1\.2
+Merging differences between 1\.1 and 1\.2 into file1
+rcsmerge: warning: conflicts during merge"
+         dotest rcslib-merge-13 "cat file1" \
+"<<<<<<< file1
+1\.1\.2\.1
+2
+three
+[=]======
+1\.2
+two
+3
+[>]>>>>>> 1\.2"
+
+         # Test behavior of symlinks in the repository.
+         if test -n "$remotehost"; then
+           # Create the link on the remote system.  This is because Cygwin's
+           # Windows support creates *.lnk files for Windows.  When creating
+           # these in an SMB share from UNIX, these links won't work from the
+           # UNIX side.
+           modify_repo $CVS_RSH $remotehost "'ln -s file1,v $CVSROOT_DIRNAME/first-dir/file2,v'"
+         else
+           modify_repo ln -s file1,v $CVSROOT_DIRNAME/first-dir/file2,v
+         fi
+         dotest rcslib-symlink-2 "$testcvs update file2" "U file2"
+         echo "This is a change" >> file2
+         dotest rcslib-symlink-3 "$testcvs ci -m because file2" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file2
+new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1"
+
+         # Switch as for rcslib-symlink-1
+         if test -n "$remotehost"; then
+           dotest rcslib-symlink-4 "$CVS_RSH $remotehost 'ls -l $CVSROOT_DIRNAME/first-dir/file2,v'" \
+".*$CVSROOT_DIRNAME/first-dir/file2,v -> file1,v"
+         else
+           dotest rcslib-symlink-4 "ls -l $CVSROOT_DIRNAME/first-dir/file2,v" \
+".*$CVSROOT_DIRNAME/first-dir/file2,v -> file1,v"
+         fi
+
+         # CVS was failing to check both the symlink and the file
+         # for timestamp changes for a while.  Test that.
+         rm file1
+         dotest rcslib-symlink-3a "${testcvs} -q up file1" \
+"${SPROG} update: warning: \`file1' was lost
+U file1"
+         echo "This is a change" >> file1
+         dotest rcslib-symlink-3b "${testcvs} ci -m because file1" \
+"${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.2\.[0-9]*; previous revision: 1\.1\.2\.[0-9]*"
+         dotest rcslib-symlink-3c "${testcvs} update file2" "[UP] file2"
+
+         echo some new text >file3
+         dotest rcslib-symlink-3d "${testcvs} -Q add file3" ''
+         dotest rcslib-symlink-3e "$testcvs -Q ci -mtest file3"
+
+         rm -f ${CVSROOT_DIRNAME}/first-dir/file2,v
+         # As for rcslib-symlink-1
+         if test -n "$remotehost"; then
+           modify_repo "$CVS_RSH $remotehost 'ln -s Attic/file3,v $CVSROOT_DIRNAME/first-dir/file2,v'"
+         else
+           modify_repo ln -s Attic/file3,v $CVSROOT_DIRNAME/first-dir/file2,v
+         fi
+
+         dotest rcslib-symlink-3g "$testcvs update file2" "U file2"
+
+         # restore the link to file1 for the following tests
+         dotest rcslib-symlink-3i "$testcvs -Q rm -f file3" ''
+         dotest rcslib-symlink-3j "$testcvs -Q ci -mwhatever file3"
+         rm -f $CVSROOT_DIRNAME/first-dir/file2,v
+         rm -f $CVSROOT_DIRNAME/first-dir/Attic/file3,v
+         # As for rcslib-symlink-1
+         if test -n "$remotehost"; then
+           modify_repo "$CVS_RSH $remotehost 'ln -s file1,v $CVSROOT_DIRNAME/first-dir/file2,v'"
+         else
+           modify_repo ln -s file1,v $CVSROOT_DIRNAME/first-dir/file2,v
+         fi
+
+         # Test 5 reveals a problem with having symlinks in the
+         # repository.  CVS will try to tag both of the files
+         # separately.  After processing one, it will do the same
+         # operation to the other, which is actually the same file,
+         # so the tag will already be there.  FIXME: do we bother
+         # changing operations to notice cases like this?  This
+         # strikes me as a difficult problem.  -Noel
+         dotest rcslib-symlink-5 "$testcvs tag the_tag" \
+"$SPROG tag: Tagging .
+T file1
+W file2 : the_tag already exists on version 1.1.2.3 : NOT MOVING tag to version 1.1.2.1"
+         # As for rcslib-symlink-1
+         if test -n "$remotehost"; then
+           dotest rcslib-symlink-6 "$CVS_RSH $remotehost 'ls -l $CVSROOT_DIRNAME/first-dir/file2,v'" \
+".*$CVSROOT_DIRNAME/first-dir/file2,v -> file1,v"
+         else
+           dotest rcslib-symlink-6 "ls -l $CVSROOT_DIRNAME/first-dir/file2,v" \
+".*$CVSROOT_DIRNAME/first-dir/file2,v -> file1,v"
+         fi
+
+         # Symlinks tend to interact poorly with the Attic.
+         cd ..
+         mkdir 2; cd 2
+         dotest rcslib-symlink-7 "$testcvs -q co first-dir" \
+"U first-dir/file1
+U first-dir/file2"
+         cd first-dir
+         dotest rcslib-symlink-8 "$testcvs rm -f file2" \
+"$SPROG remove: scheduling .file2. for removal
+$SPROG remove: use .$SPROG commit. to remove this file permanently"
+         dotest rcslib-symlink-9 "$testcvs -q ci -m rm-it" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file2
+new revision: delete; previous revision: 1\.2"
+         # OK, why this message happens twice is relatively clear
+         # (the check_* and rtag_* calls to start_recursion).
+         # Why it happens a third time I didn't try to find out.
+         #
+         # DRP: One of the error messages disappeared while I was making
+         # proxy modifications.  Until I detect a deeper issue, I'm not
+         # going to stress over it.
+         #
+         # DRP: Both messages disappear starting with glibc 2.3.3 due to a bug
+         # in the glob function which causes it to fail to return broken
+         # symlinks.  I'm submitting a bug fix to glibc which will hopefully
+         # be released with glibc 2.3.6.  Once it is released and versions
+         # 2.3.3-2.3.5 of glibc become uncommon, the first, empty case below
+         # should be removed again.
+         dotest rcslib-symlink-10 \
+"$testcvs -q rtag -b -r the_tag brtag first-dir" "" \
+"$SPROG rtag: could not read RCS file for first-dir/file2
+$SPROG rtag: could not read RCS file for first-dir/file2"
+
+         # Restore file1 for the next test.
+         dotest rcslib-long-symlink-init-1 "$testcvs -Q up -A"
+         dotest rcslib-long-symlink-init-2 "$testcvs -Q add file1"
+         dotest rcslib-long-symlink-init-3 "$testcvs -Q ci -mback"
+
+         cd ../..  # $TESTDIR
+
+         # CVS has a hard-coded default link path size of 127 characters.
+         # Make sure it knows how to exceed that.
+         longpath=$CVSROOT_DIRNAME
+         count=0
+         while test $count -lt 10; do
+           # 10 * 30 characters + len $CVSROOT_DIRNAME
+           count=`expr $count + 1`
+           longpath=$longpath/123456789012345678901234567890
+           modify_repo mkdir $longpath
+         done
+         modify_repo cp $CVSROOT_DIRNAME/first-dir/file1,v $longpath
+         modify_repo mkdir $CVSROOT_DIRNAME/second-dir
+
+         # Switch as for rcslib-symlink-1
+         if test -n "$remotehost"; then
+           modify_repo $CVS_RSH $remotehost \
+           'ln -s $longpath/file1,v $CVSROOT_DIRNAME/second-dir/fileX,v'
+         else
+           modify_repo ln -s $longpath/file1,v \
+                             $CVSROOT_DIRNAME/second-dir/fileX,v
+         fi
+
+         dotest rcslib-long-symlink-2 "$testcvs co second-dir" \
+"$SPROG checkout: Updating second-dir
+U second-dir/fileX"
+
+         cd second-dir
+         echo change-it >>fileX
+
+         # Writes actually cause symlinks to be resolved.
+         dotest rcslib-long-symlink-3 "$testcvs -q ci -mwrite-it" \
+"$CVSROOT_DIRNAME/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/file1,v  <--  fileX
+new revision: 1\.5; previous revision: 1\.4"
+
+         dokeep
+         cd ..
+
+         # Must remove the symlink first.  Samba doesn't appear to show
+         # broken symlink across the SMB share, and rm -rf by itself
+         # will remove file1,v first and leave file2,v a broken link and the
+         # rm -rf will fail since it doesn't find file2,v and it still gets
+         # directory not empty errors removing cvsroot/first-dir.
+         #
+         # I'm not sure why I need to do this on $remotehost.  The rm above
+         # rcslib-symlink-3j works fine, but the next one doesn't unless run
+         # remotely under Cygwin and using a TESTDIR on a Samba share.
+         if test -n "$remotehost"; then
+           $CVS_RSH $remotehost \
+"rm -f $CVSROOT_DIRNAME/first-dir/file2,v $CVSROOT_DIRNAME/second-dir/fileX,v"
+         fi
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir \
+                            $CVSROOT_DIRNAME/second-dir \
+                            $CVSROOT_DIRNAME/123456789012345678901234567890
+         rm -r first-dir second-dir 2
+         ;;
+
+
+
+       multibranch)
+         # Test the ability to have several branchpoints coming off the
+         # same revision.
+         modify_repo mkdir $CVSROOT_DIRNAME/first-dir
+         dotest multibranch-1 "${testcvs} -q co first-dir" ''
+         cd first-dir
+         echo 1:trunk-1 >file1
+         dotest multibranch-2 "${testcvs} add file1" \
+"${SPROG}"' add: scheduling file `file1'\'' for addition
+'"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
+         dotest_lit multibranch-3 "${testcvs} -q ci -m add-it" <<HERE
+$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+initial revision: 1.1
+HERE
+         dotest multibranch-4 "${testcvs} tag -b br1" \
+"${SPROG} tag: Tagging \.
+T file1"
+         dotest multibranch-5 "${testcvs} tag -b br2" \
+"${SPROG} tag: Tagging \.
+T file1"
+         dotest multibranch-6 "${testcvs} -q update -r br1" ''
+         echo on-br1 >file1
+         dotest multibranch-7 "${testcvs} -q ci -m modify-on-br1" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.1\.2\.1; previous revision: 1\.1"
+         dotest multibranch-8 "${testcvs} -q update -r br2" '[UP] file1'
+         echo br2 adds a line >>file1
+         dotest multibranch-9 "${testcvs} -q ci -m modify-on-br2" \
+"$CVSROOT_DIRNAME/first-dir/file1,v  <--  file1
+new revision: 1\.1\.4\.1; previous revision: 1\.1"
+         dotest multibranch-10 "${testcvs} -q update -r br1" '[UP] file1'
+         dotest multibranch-11 "cat file1" 'on-br1'
+         dotest multibranch-12 "${testcvs} -q update -r br2" '[UP] file1'
+         dotest multibranch-13 "cat file1" '1:trunk-1
+br2 adds a line'
+
+         dotest multibranch-14 "${testcvs} log file1" \
+"
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
+Working file: file1
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+       br2: 1\.1\.0\.4
+       br1: 1\.1\.0\.2
+keyword substitution: kv
+total revisions: 3;    selected revisions: 3
+description:
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+branches:  1\.1\.2;  1\.1\.4;
+add-it
+----------------------------
+revision 1\.1\.4\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}1 -0;  commitid: ${commitid};
+modify-on-br2
+----------------------------
+revision 1\.1\.2\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}1 -1;  commitid: ${commitid};
+modify-on-br1
+============================================================================="
+
+         dokeep
+         cd ..
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+         rm -r first-dir
+         ;;
+
+
+
+       import) # test death after import
+               # Tests of "cvs import":
+               # basic2
+               # rdiff  -- imports with keywords
+               # import  -- more tests of imports with keywords
+               # importb  -- -b option.
+               # importc -- bunch o' files in bunch o' directories
+               # importX  -- -X option.
+               # importX2 -- CVSROOT/config ImportNewFilesToVendorBranchOnly
+               #             flag
+               # modules3
+               # mflag -- various -m messages
+               # ignore  -- import and cvsignore
+               # binwrap -- import and -k wrappers
+               # info -- imports which are rejected by verifymsg
+               # head -- intended to test vendor branches and HEAD,
+               #   although it doesn't really do it yet.
+               # import-CVS -- refuse to import directories named "CVS".
+               # import-quirks -- short tests of import quirks.
+
+               # import
+               mkdir import-dir ; cd import-dir
+
+               for i in 1 2 3 4 ; do
+                 echo imported file"$i" > imported-f"$i"
+               done
+
+               # This directory should be on the default ignore list,
+               # so it shouldn't get imported.
+               mkdir RCS
+               echo ignore.me >RCS/ignore.me
+
+               echo 'import should not expand $''Id$' >>imported-f2
+               cp imported-f2 ../imported-f2-orig.tmp
+
+               dotest_sort import-96 \
+"${testcvs} import -m first-import first-dir vendor-branch junk-1_0" \
+"
+
+I first-dir/RCS
+N first-dir/imported-f1
+N first-dir/imported-f2
+N first-dir/imported-f3
+N first-dir/imported-f4
+No conflicts created by this import"
+
+               dotest import-96.5 "cmp ../imported-f2-orig.tmp imported-f2" ''
+
+               cd ..
+
+               # co
+               dotest import-97 "${testcvs} -q co first-dir" \
+"U first-dir/imported-f1
+U first-dir/imported-f2
+U first-dir/imported-f3
+U first-dir/imported-f4"
+
+               cd first-dir
+
+               for i in 1 2 3 4 ; do
+                 dotest import-98-$i "test -f imported-f$i" ''
+               done
+               dotest_fail import-98.5 "test -d RCS" ''
+
+               # remove
+               rm imported-f1
+               dotest import-99 "${testcvs} rm imported-f1" \
+"${SPROG}"' remove: scheduling `imported-f1'\'' for removal
+'"${SPROG}"' remove: use .'"${SPROG}"' commit. to remove this file permanently'
+
+               # change
+               echo local-change >> imported-f2
+
+               # commit
+               dotest import-100 "${testcvs} ci -m local-changes" \
+"${CPROG} commit: Examining .
+${CVSROOT_DIRNAME}/first-dir/imported-f1,v  <--  imported-f1
+new revision: delete; previous revision: 1\.1\.1\.1
+${CVSROOT_DIRNAME}/first-dir/imported-f2,v  <--  imported-f2
+new revision: 1\.2; previous revision: 1\.1"
+
+               # log
+               dotest import-101 "${testcvs} log imported-f1" \
+"
+RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/imported-f1,v
+Working file: imported-f1
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+       junk-1_0: 1\.1\.1\.1
+       vendor-branch: 1\.1\.1
+keyword substitution: kv
+total revisions: 3;    selected revisions: 3
+description:
+----------------------------
+revision 1\.2
+date: ${ISO8601DATE};  author: ${username};  state: dead;  lines: ${PLUS}0 -0;  commitid: ${commitid};
+local-changes
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+branches:  1\.1\.1;
+Initial revision
+----------------------------
+revision 1\.1\.1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}0 -0;  commitid: ${commitid};
+first-import
+============================================================================="
+
+               # update into the vendor branch.
+               dotest import-102 "${testcvs} update -rvendor-branch" \
+"${SPROG} update: Updating .
+[UP] imported-f1
+[UP] imported-f2"
+
+               # remove file4 on the vendor branch
+               rm imported-f4
+               dotest import-103 "${testcvs} rm imported-f4" \
+"${SPROG}"' remove: scheduling `imported-f4'\'' for removal
+'"${SPROG}"' remove: use .'"${SPROG}"' commit. to remove this file permanently'
+
+               # commit
+               dotest import-104 \
+"${testcvs} ci -m vendor-removed imported-f4" \
+"${CVSROOT_DIRNAME}/first-dir/imported-f4,v  <--  imported-f4
+new revision: delete; previous revision: 1\.1\.1\.1"
+
+               # update to main line
+               dotest import-105 "${testcvs} -q update -A" \
+"${SPROG} update: \`imported-f1' is no longer in the repository
+[UP] imported-f2"
+
+               # second import - file4 deliberately unchanged
+               cd ../import-dir
+               for i in 1 2 3 ; do
+                 echo rev 2 of file $i >> imported-f"$i"
+               done
+               cp imported-f2 ../imported-f2-orig.tmp
+
+               dotest_sort import-106 \
+"${testcvs} import -m second-import first-dir vendor-branch junk-2_0" \
+"
+
+
+ ${CPROG} checkout -j<prev_rel_tag> -jjunk-2_0 first-dir
+2 conflicts created by this import.
+C first-dir/imported-f1
+C first-dir/imported-f2
+I first-dir/RCS
+U first-dir/imported-f3
+U first-dir/imported-f4
+Use the following command to help the merge:"
+
+               dotest import-106.5 "cmp ../imported-f2-orig.tmp imported-f2" \
+''
+
+               cd ..
+
+               rm imported-f2-orig.tmp
+
+               # co
+               dotest import-107 "${testcvs} co first-dir" \
+"${SPROG} checkout: Updating first-dir
+[UP] first-dir/imported-f3
+[UP] first-dir/imported-f4"
+
+               cd first-dir
+
+               dotest_fail import-108 "test -f imported-f1" ''
+
+               for i in 2 3 ; do
+                 dotest import-109-$i "test -f imported-f$i" ''
+               done
+
+               # check vendor branch for file4
+               dotest import-110 "${testcvs} -q update -rvendor-branch" \
+"[UP] imported-f1
+[UP] imported-f2"
+
+               dotest import-111 "test -f imported-f4" ''
+
+               # update to main line
+               dotest import-112 "${testcvs} -q update -A" \
+"${SPROG} update: \`imported-f1' is no longer in the repository
+[UP] imported-f2"
+
+               cd ..
+
+               dotest import-113 \
+"${testcvs} -q co -jjunk-1_0 -jjunk-2_0 first-dir" \
+"${SPROG} checkout: file first-dir/imported-f1 does not exist, but is present in revision junk-2_0
+RCS file: ${CVSROOT_DIRNAME}/first-dir/imported-f2,v
+retrieving revision 1\.1\.1\.1
+retrieving revision 1\.1\.1\.2
+Merging differences between 1\.1\.1\.1 and 1\.1\.1\.2 into imported-f2
+rcsmerge: warning: conflicts during merge
+first-dir/imported-f3 already contains the differences between 1\.1\.1\.1 and 1\.1\.1\.2
+first-dir/imported-f4 already contains the differences between 1\.1\.1\.1 and 1\.1\.1\.3"
+
+               cd first-dir
+
+               dotest_fail import-114 "test -f imported-f1" ''
+
+               for i in 2 3 ; do
+                 dotest import-115-$i "test -f imported-f$i" ''
+               done
+
+               dotest import-116 'cat imported-f2' \
+'imported file2
+[<]<<<<<< imported-f2
+import should not expand \$''Id: imported-f2,v 1\.2 [0-9/]* [0-9:]* '"${username}"' Exp \$
+local-change
+[=]======
+import should not expand \$''Id: imported-f2,v 1\.1\.1\.2 [0-9/]* [0-9:]* '"${username}"' Exp \$
+rev 2 of file 2
+[>]>>>>>> 1\.1\.1\.2'
+
+               dokeep
+               cd ..
+               rm -r first-dir
+               modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
+               rm -r import-dir
+               ;;
+
+
+
+       importb)
+         # More cvs import tests, especially -b option.
+
+         # OK, first we get some sources from the NetMunger project, and
+         # import them into the 1.1.1 vendor branch.
+         mkdir imp-dir
+         cd imp-dir
+         echo 'OpenMunger sources' >file1
+         echo 'OpenMunger sources' >file2
+         dotest_sort importb-1 \
+"${testcvs} import -m add first-dir openmunger openmunger-1_0" \
+"
+
+N first-dir/file1
+N first-dir/file2
+No conflicts created by this import"
+         cd ..
+         rm -r imp-dir
+
+         # Now we put the sources we get from FreeMunger into 1.1.3
+         mkdir imp-dir
+         cd imp-dir
+         echo 'FreeMunger sources' >file1
+         echo 'FreeMunger sources' >file2
+         # Not completely sure how the conflict detection is supposed to
+         # be working here (haven't really thought about it).
+         # We use an explicit -d option to test that it is reflected
+         # in the suggested checkout.
+         dotest_sort importb-2 \
+"$testcvs -d '$CVSROOT' import -m add -b 1.1.3 \
+          first-dir freemunger freemunger-1_0" \
+"
+
+
+ ${CPROG} -d ${CVSROOT} checkout -j<prev_rel_tag> -jfreemunger-1_0 first-dir
+2 conflicts created by this import.
+C first-dir/file1
+C first-dir/file2
+Use the following command to help the merge:"
+         cd ..
+         rm -r imp-dir
+
+         # Now a test of main branch import (into second-dir, not first-dir).
+         mkdir imp-dir
+         cd imp-dir
+         echo 'my own stuff' >mine1.c
+         echo 'my own stuff' >mine2.c
+         dotest_fail importb-3 \
+"${testcvs} import -m add -b 1 second-dir dummy really_dumb_y" \
+"$CPROG \[import aborted\]: Only numeric branch specifications with two dots are
+supported by import, not \`1'\.  For example: \`1\.1\.1'\."
+         : when we implement main-branch import, should be \
+"N second-dir/mine1\.c
+N second-dir/mine2\.c
+
+No conflicts created by this import"
+         cd ..
+         rm -r imp-dir
+
+         mkdir 1
+         cd 1
+         # when we implement main branch import, will want to 
+         # add "second-dir" here.
+         dotest importb-4 "${testcvs} -q co first-dir" \
+"U first-dir/file1
+U first-dir/file2"
+         cd first-dir
+         dotest importb-5 "${testcvs} -q log file1" "
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
+Working file: file1
+head: 1\.1
+branch: 1\.1\.1
+locks: strict
+access list:
+symbolic names:
+       freemunger-1_0: 1\.1\.3\.1
+       freemunger: 1\.1\.3
+       openmunger-1_0: 1\.1\.1\.1
+       openmunger: 1\.1\.1
+keyword substitution: kv
+total revisions: 3;    selected revisions: 3
+description:
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
+branches:  1\.1\.1;  1\.1\.3;
+Initial revision
+----------------------------
+revision 1\.1\.3\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}1 -1;  commitid: ${commitid};
+add
+----------------------------
+revision 1\.1\.1\.1
+date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}0 -0;  commitid: ${commitid};
+add
+============================================================================="
+
+         dokeep
+         cd ../..
+         rm -r 1
+         modify_repo rm -rf $CVSROOT_DIRNAME/first-dir \
+                            $CVSROOT_DIRNAME/second-dir
+         ;;
+
+
+
+       importc)
+         # Test importing a bunch o' files in a bunch o' directories.
+         # Also the -d option.
+
+         # Set a predictable time zone for these tests.
+         save_TZ=$TZ
+         TZ=UTC0; export TZ
+
+         mkdir 1; cd 1
+         mkdir adir bdir cdir
+         mkdir adir/sub1 adir/sub2
+         mkdir adir/sub1/ssdir
+         mkdir bdir/subdir
+         touch adir/sub1/file1 adir/sub2/file2 adir/sub1/ssdir/ssfile
+         touch -t ${TOUCH1971} bdir/subdir/file1
+         touch -t ${TOUCH2034} cdir/cfile
+         dotest_sort importc-1 \
+"${testcvs} import -d -m import-it first-dir vendor release" \
+"
+
+N first-dir/adir/sub1/file1
+N first-dir/adir/sub1/ssdir/ssfile
+N first-dir/adir/sub2/file2
+N first-dir/bdir/subdir/file1
+N first-dir/cdir/cfile
+No conflicts created by this import
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/adir
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/adir/sub1
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/adir/sub1/ssdir
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/adir/sub2
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/bdir
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/bdir/subdir
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/cdir"
+         cd ..
+         mkdir 2; cd 2
+         dotest importc-2 "${testcvs} -q co first-dir" \
+"U first-dir/adir/sub1/file1
+U first-dir/adir/sub1/ssdir/ssfile
+U first-dir/adir/sub2/file2
+U first-dir/bdir/subdir/file1
+U first-dir/cdir/cfile"
+         cd first-dir
+         dotest importc-3 "${testcvs} update adir/sub1" \
+"${SPROG} update: Updating adir/sub1
+${SPROG} update: Updating adir/sub1/ssdir"
+         dotest importc-4 "${testcvs} update adir/sub1 bdir/subdir" \
+"${SPROG} update: Updating adir/sub1
+${SPROG} update: Updating adir/sub1/ssdir
+${SPROG} update: Updating bdir/subdir"
+
+         echo modify >>cdir/cfile
+         dotest importc-5 \
+"${testcvs} -q rtag -b -r release wip_test first-dir" ""
+         dotest importc-6 "${testcvs} -q update -r wip_test" "M cdir/cfile"
+
+         # This used to fail in local mode
+         dotest importc-7 "${testcvs} -q ci -m modify -r wip_test" \
+"$CVSROOT_DIRNAME/first-dir/cdir/cfile,v  <--  cdir/cfile
+new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1"
+
+         # TODO: should also be testing "import -d" when we update
+         # an existing file.
+         dotest importc-8 "${testcvs} -q log cdir/cfile" "
+RCS file: ${CVSROOT_DIRNAME}/first-dir/cdir/cfile,v
+Working file: cdir/cfile
+head: 1\.1
+branch: 1\.1\.1
+locks: strict
+access list:
+symbolic names:
+       wip_test: 1\.1\.1\.1\.0\.2
+       release: 1\.1\.1\.1
+       vendor: 1\.1\.1
+keyword substitution: kv
+total revisions: 3;    selected revisions: 3
+description:
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE2034};  author: ${username};  state: Exp;  commitid: ${commitid};
+branches:  1\.1\.1;
+Initial revision
+----------------------------
+revision 1\.1\.1\.1